"Fossies" - the Fresh Open Source Software Archive

Member "sysstat-12.1.5/sadf_misc.c" (31 May 2019, 50959 Bytes) of package /linux/misc/sysstat-12.1.5.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 latest Fossies "Diffs" side-by-side code changes report: 12.1.4_vs_12.1.5.

    1 /*
    2  * sadf_misc.c: Funtions used by sadf to display special records
    3  * (C) 2011-2019 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         }
  797     }
  798 #endif /* HAVE_PCP */
  799 }
  800 
  801 /*
  802  ***************************************************************************
  803  * Display the "timestamp" part of the report (db and ppc format).
  804  *
  805  * IN:
  806  * @fmt     Output format (F_DB_OUTPUT or F_PPC_OUTPUT).
  807  * @file_hdr    System activity file standard header.
  808  * @cur_date    Date string of current record.
  809  * @cur_time    Time string of current record.
  810  * @utc     True if @cur_time is expressed in UTC.
  811  * @itv     Interval of time with preceding record.
  812  *
  813  * RETURNS:
  814  * Pointer on the "timestamp" string.
  815  ***************************************************************************
  816  */
  817 char *print_dbppc_timestamp(int fmt, struct file_header *file_hdr, char *cur_date,
  818                 char *cur_time, int utc, unsigned long long itv)
  819 {
  820     int isdb = (fmt == F_DB_OUTPUT);
  821     static char pre[512];
  822     char temp1[128], temp2[256];
  823 
  824     /* This substring appears on every output line, preformat it here */
  825     snprintf(temp1, sizeof(temp1), "%s%s%lld%s",
  826          file_hdr->sa_nodename, seps[isdb], itv, seps[isdb]);
  827     if (strlen(cur_date)) {
  828         snprintf(temp2, sizeof(temp2), "%s%s ", temp1, cur_date);
  829     }
  830     else {
  831         strcpy(temp2, temp1);
  832     }
  833     snprintf(pre, sizeof(pre), "%s%s%s", temp2, cur_time,
  834          strlen(cur_date) && utc ? " UTC" : "");
  835     pre[sizeof(pre) - 1] = '\0';
  836 
  837     if (DISPLAY_HORIZONTALLY(flags)) {
  838         printf("%s", pre);
  839     }
  840 
  841     return pre;
  842 }
  843 
  844 /*
  845  ***************************************************************************
  846  * Display the "timestamp" part of the report (ppc format).
  847  *
  848  * IN:
  849  * @parm    Pointer on specific parameters (unused here).
  850  * @action  Action expected from current function.
  851  * @cur_date    Date string of current record.
  852  * @cur_time    Time string of current record.
  853  * @itv     Interval of time with preceding record.
  854  * @record_hdr  Record header for current sample (unused here).
  855  * @file_hdr    System activity file standard header.
  856  * @flags   Flags for common options.
  857  *
  858  * RETURNS:
  859  * Pointer on the "timestamp" string.
  860  ***************************************************************************
  861  */
  862 __tm_funct_t print_ppc_timestamp(void *parm, int action, char *cur_date,
  863                  char *cur_time, unsigned long long itv,
  864                  struct record_header *record_hdr,
  865                  struct file_header *file_hdr, unsigned int flags)
  866 {
  867     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
  868 
  869     if (action & F_BEGIN) {
  870         return print_dbppc_timestamp(F_PPC_OUTPUT, file_hdr, cur_date, cur_time, utc, itv);
  871     }
  872     if (action & F_END) {
  873         if (DISPLAY_HORIZONTALLY(flags)) {
  874             printf("\n");
  875         }
  876     }
  877 
  878     return NULL;
  879 }
  880 
  881 /*
  882  ***************************************************************************
  883  * Display the "timestamp" part of the report (db format).
  884  *
  885  * IN:
  886  * @parm    Pointer on specific parameters (unused here).
  887  * @action  Action expected from current function.
  888  * @cur_date    Date string of current record.
  889  * @cur_time    Time string of current record.
  890  * @itv     Interval of time with preceding record.
  891  * @record_hdr  Record header for current sample (unused here).
  892  * @file_hdr    System activity file standard header.
  893  * @flags   Flags for common options.
  894  *
  895  * RETURNS:
  896  * Pointer on the "timestamp" string.
  897  ***************************************************************************
  898  */
  899 __tm_funct_t print_db_timestamp(void *parm, int action, char *cur_date,
  900                 char *cur_time, unsigned long long itv,
  901                 struct record_header *record_hdr,
  902                 struct file_header *file_hdr, unsigned int flags)
  903 {
  904     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
  905 
  906     if (action & F_BEGIN) {
  907         return print_dbppc_timestamp(F_DB_OUTPUT, file_hdr, cur_date, cur_time, utc, itv);
  908     }
  909     if (action & F_END) {
  910         if (DISPLAY_HORIZONTALLY(flags)) {
  911             printf("\n");
  912         }
  913     }
  914 
  915     return NULL;
  916 }
  917 
  918 /*
  919  ***************************************************************************
  920  * Display the "timestamp" part of the report (XML format).
  921  *
  922  * IN:
  923  * @parm    Specific parameter. Here: number of tabulations.
  924  * @action  Action expected from current function.
  925  * @cur_date    Date string of current comment.
  926  * @cur_time    Time string of current comment.
  927  * @itv     Interval of time with preceding record.
  928  * @record_hdr  Record header for current sample (unused here).
  929  * @file_hdr    System activity file standard header (unused here).
  930  * @flags   Flags for common options.
  931  ***************************************************************************
  932  */
  933 __tm_funct_t print_xml_timestamp(void *parm, int action, char *cur_date,
  934                  char *cur_time, unsigned long long itv,
  935                  struct record_header *record_hdr,
  936                  struct file_header *file_hdr, unsigned int flags)
  937 {
  938     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
  939     int *tab = (int *) parm;
  940 
  941     if (action & F_BEGIN) {
  942         xprintf((*tab)++, "<timestamp date=\"%s\" time=\"%s\" utc=\"%d\" interval=\"%llu\">",
  943             cur_date, cur_time, utc ? 1 : 0, itv);
  944     }
  945     if (action & F_END) {
  946         xprintf(--(*tab), "</timestamp>");
  947     }
  948 
  949     return NULL;
  950 }
  951 
  952 /*
  953  ***************************************************************************
  954  * Display the "timestamp" part of the report (JSON format).
  955  *
  956  * IN:
  957  * @parm    Specific parameter. Here: number of tabulations.
  958  * @action  Action expected from current function.
  959  * @cur_date    Date string of current comment.
  960  * @cur_time    Time string of current comment.
  961  * @itv     Interval of time with preceding record.
  962  * @record_hdr  Record header for current sample (unused here).
  963  * @file_hdr    System activity file standard header (unused here).
  964  * @flags   Flags for common options.
  965  ***************************************************************************
  966  */
  967 __tm_funct_t print_json_timestamp(void *parm, int action, char *cur_date,
  968                   char *cur_time, unsigned long long itv,
  969                   struct record_header *record_hdr,
  970                   struct file_header *file_hdr, unsigned int flags)
  971 {
  972     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
  973     int *tab = (int *) parm;
  974 
  975     if (action & F_BEGIN) {
  976         xprintf0(*tab,
  977              "\"timestamp\": {\"date\": \"%s\", \"time\": \"%s\", "
  978              "\"utc\": %d, \"interval\": %llu}",
  979              cur_date, cur_time, utc ? 1 : 0, itv);
  980     }
  981     if (action & F_MAIN) {
  982         printf(",\n");
  983     }
  984     if (action & F_END) {
  985         printf("\n");
  986     }
  987 
  988     return NULL;
  989 }
  990 
  991 /*
  992  ***************************************************************************
  993  * Display the "timestamp" part of the report (raw format).
  994  *
  995  * IN:
  996  * @parm    Pointer on specific parameters (unused here).
  997  * @action  Action expected from current function.
  998  * @cur_date    Date string of current record.
  999  * @cur_time    Time string of current record.
 1000  * @itv     Interval of time with preceding record (unused here).
 1001  * @record_hdr  Record header for current sample (unused here).
 1002  * @file_hdr    System activity file standard header (unused here).
 1003  * @flags   Flags for common options.
 1004  *
 1005  * RETURNS:
 1006  * Pointer on the "timestamp" string.
 1007  ***************************************************************************
 1008  */
 1009 __tm_funct_t print_raw_timestamp(void *parm, int action, char *cur_date,
 1010                  char *cur_time, unsigned long long itv,
 1011                  struct record_header *record_hdr,
 1012                  struct file_header *file_hdr, unsigned int flags)
 1013 {
 1014     int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
 1015     static char pre[80];
 1016 
 1017     if (action & F_BEGIN) {
 1018         snprintf(pre, 80, "%s%s", cur_time, strlen(cur_date) && utc ? " UTC" : "");
 1019         pre[79] = '\0';
 1020         return pre;
 1021     }
 1022 
 1023     return NULL;
 1024 }
 1025 
 1026 /*
 1027  ***************************************************************************
 1028  * Display the "timestamp" part of the report (PCP format).
 1029  *
 1030  * IN:
 1031  * @parm    Pointer on specific parameters (unused here).
 1032  * @action  Action expected from current function.
 1033  * @cur_date    Date string of current record (unused here).
 1034  * @cur_time    Time string of current record (unused here).
 1035  * @itv     Interval of time with preceding record (unused here).
 1036  * @record_hdr  Record header for current sample.
 1037  * @file_hdr    System activity file standard header (unused here).
 1038  * @flags   Flags for common options.
 1039  *
 1040  * RETURNS:
 1041  * Pointer on the "timestamp" string.
 1042  ***************************************************************************
 1043  */
 1044 __tm_funct_t print_pcp_timestamp(void *parm, int action, char *cur_date,
 1045                  char *cur_time, unsigned long long itv,
 1046                  struct record_header *record_hdr,
 1047                  struct file_header *file_hdr, unsigned int flags)
 1048 {
 1049     if (action & F_END) {
 1050         pcp_write_data(record_hdr, flags);
 1051     }
 1052 
 1053     return NULL;
 1054 }
 1055 
 1056 /*
 1057  ***************************************************************************
 1058  * Display the header of the report (XML format).
 1059  *
 1060  * IN:
 1061  * @parm    Specific parameter. Here: number of tabulations.
 1062  * @action  Action expected from current function.
 1063  * @dfile   Unused here (PCP archive file).
 1064  * @file_magic  System activity file magic header.
 1065  * @file_hdr    System activity file standard header.
 1066  * @act     Array of activities (unused here).
 1067  * @id_seq  Activity sequence (unused here).
 1068  * @file_actlst List of (known or unknown) activities in file (unused here).
 1069  *
 1070  * OUT:
 1071  * @parm    Number of tabulations.
 1072  ***************************************************************************
 1073  */
 1074 __printf_funct_t print_xml_header(void *parm, int action, char *dfile,
 1075                   struct file_magic *file_magic,
 1076                   struct file_header *file_hdr,
 1077                   struct activity *act[], unsigned int id_seq[],
 1078                   struct file_activity *file_actlst)
 1079 {
 1080     struct tm rectime, loc_t;
 1081     char cur_time[TIMESTAMP_LEN];
 1082     int *tab = (int *) parm;
 1083 
 1084     if (action & F_BEGIN) {
 1085         printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 1086         printf("<!DOCTYPE sysstat PUBLIC \"DTD v%s sysstat //EN\"\n",
 1087                XML_DTD_VERSION);
 1088         printf("\"http://pagesperso-orange.fr/sebastien.godard/sysstat-%s.dtd\">\n",
 1089                XML_DTD_VERSION);
 1090 
 1091         xprintf(*tab, "<sysstat\n"
 1092                   "xmlns=\"http://pagesperso-orange.fr/sebastien.godard/sysstat\"\n"
 1093                   "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
 1094                   "xsi:schemaLocation=\"http://pagesperso-orange.fr/sebastien.godard sysstat.xsd\">");
 1095 
 1096         xprintf(++(*tab), "<sysdata-version>%s</sysdata-version>",
 1097             XML_DTD_VERSION);
 1098 
 1099         xprintf(*tab, "<host nodename=\"%s\">", file_hdr->sa_nodename);
 1100         xprintf(++(*tab), "<sysname>%s</sysname>", file_hdr->sa_sysname);
 1101         xprintf(*tab, "<release>%s</release>", file_hdr->sa_release);
 1102 
 1103         xprintf(*tab, "<machine>%s</machine>", file_hdr->sa_machine);
 1104         xprintf(*tab, "<number-of-cpus>%d</number-of-cpus>",
 1105             file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
 1106 
 1107         /* Fill file timestmap structure (rectime) */
 1108         get_file_timestamp_struct(flags, &rectime, file_hdr);
 1109         strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
 1110         xprintf(*tab, "<file-date>%s</file-date>", cur_time);
 1111 
 1112         if (gmtime_r((const time_t *) &file_hdr->sa_ust_time, &loc_t) != NULL) {
 1113             strftime(cur_time, sizeof(cur_time), "%T", &loc_t);
 1114             xprintf(*tab, "<file-utc-time>%s</file-utc-time>", cur_time);
 1115         }
 1116 
 1117     }
 1118     if (action & F_END) {
 1119         xprintf(--(*tab), "</host>");
 1120         xprintf(--(*tab), "</sysstat>");
 1121     }
 1122 }
 1123 
 1124 /*
 1125  ***************************************************************************
 1126  * Display the header of the report (JSON format).
 1127  *
 1128  * IN:
 1129  * @parm    Specific parameter. Here: number of tabulations.
 1130  * @action  Action expected from current function.
 1131  * @dfile   Unused here (PCP archive file).
 1132  * @file_magic  System activity file magic header.
 1133  * @file_hdr    System activity file standard header.
 1134  * @act     Array of activities (unused here).
 1135  * @id_seq  Activity sequence (unused here).
 1136  * @file_actlst List of (known or unknown) activities in file (unused here).
 1137  *
 1138  * OUT:
 1139  * @parm    Number of tabulations.
 1140  ***************************************************************************
 1141  */
 1142 __printf_funct_t print_json_header(void *parm, int action, char *dfile,
 1143                    struct file_magic *file_magic,
 1144                    struct file_header *file_hdr,
 1145                    struct activity *act[], unsigned int id_seq[],
 1146                    struct file_activity *file_actlst)
 1147 {
 1148     struct tm rectime, loc_t;
 1149     char cur_time[TIMESTAMP_LEN];
 1150     int *tab = (int *) parm;
 1151 
 1152     if (action & F_BEGIN) {
 1153         xprintf(*tab, "{\"sysstat\": {");
 1154 
 1155         xprintf(++(*tab), "\"hosts\": [");
 1156         xprintf(++(*tab), "{");
 1157         xprintf(++(*tab), "\"nodename\": \"%s\",", file_hdr->sa_nodename);
 1158         xprintf(*tab, "\"sysname\": \"%s\",", file_hdr->sa_sysname);
 1159         xprintf(*tab, "\"release\": \"%s\",", file_hdr->sa_release);
 1160 
 1161         xprintf(*tab, "\"machine\": \"%s\",", file_hdr->sa_machine);
 1162         xprintf(*tab, "\"number-of-cpus\": %d,",
 1163             file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
 1164 
 1165         /* Fill file timestmap structure (rectime) */
 1166         get_file_timestamp_struct(flags, &rectime, file_hdr);
 1167         strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
 1168         xprintf0(*tab, "\"file-date\": \"%s\"", cur_time);
 1169 
 1170         if (gmtime_r((const time_t *) &file_hdr->sa_ust_time, &loc_t) != NULL) {
 1171             strftime(cur_time, sizeof(cur_time), "%T", &loc_t);
 1172             printf(",\n");
 1173             xprintf0(*tab, "\"file-utc-time\": \"%s\"", cur_time);
 1174         }
 1175 
 1176     }
 1177     if (action & F_END) {
 1178         printf("\n");
 1179         xprintf(--(*tab), "}");
 1180         xprintf(--(*tab), "]");
 1181         xprintf(--(*tab), "}}");
 1182     }
 1183 }
 1184 
 1185 /*
 1186  ***************************************************************************
 1187  * Display data file header.
 1188  *
 1189  * IN:
 1190  * @parm    Specific parameter (unused here).
 1191  * @action  Action expected from current function.
 1192  * @dfile   Name of system activity data file (unused here).
 1193  * @file_magic  System activity file magic header.
 1194  * @file_hdr    System activity file standard header.
 1195  * @act     Array of activities.
 1196  * @id_seq  Activity sequence.
 1197  * @file_actlst List of (known or unknown) activities in file.
 1198  ***************************************************************************
 1199  */
 1200 __printf_funct_t print_hdr_header(void *parm, int action, char *dfile,
 1201                   struct file_magic *file_magic,
 1202                   struct file_header *file_hdr,
 1203                   struct activity *act[], unsigned int id_seq[],
 1204                   struct file_activity *file_actlst)
 1205 {
 1206     int i, p;
 1207     struct tm rectime, loc_t;
 1208     struct file_activity *fal;
 1209     char cur_time[TIMESTAMP_LEN];
 1210 
 1211     /* Actions F_MAIN and F_END ignored */
 1212     if (action & F_BEGIN) {
 1213         printf(_("System activity data file: %s (%#x)\n"),
 1214                dfile, file_magic->format_magic);
 1215 
 1216         display_sa_file_version(stdout, file_magic);
 1217 
 1218         if (file_magic->format_magic != FORMAT_MAGIC) {
 1219             return;
 1220         }
 1221 
 1222         printf(_("Genuine sa datafile: %s (%x)\n"),
 1223                file_magic->upgraded ? _("no") : _("yes"),
 1224                file_magic->upgraded);
 1225 
 1226         printf(_("Host: "));
 1227         print_gal_header(localtime_r((const time_t *) &(file_hdr->sa_ust_time), &rectime),
 1228                  file_hdr->sa_sysname, file_hdr->sa_release,
 1229                  file_hdr->sa_nodename, file_hdr->sa_machine,
 1230                  file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1,
 1231                  PLAIN_OUTPUT);
 1232 
 1233         /* Fill file timestmap structure (rectime) */
 1234         get_file_timestamp_struct(flags, &rectime, file_hdr);
 1235         strftime(cur_time, sizeof(cur_time), "%Y-%m-%d", &rectime);
 1236         printf(_("File date: %s\n"), cur_time);
 1237 
 1238         if (gmtime_r((const time_t *) &file_hdr->sa_ust_time, &loc_t) != NULL) {
 1239             printf(_("File time: "));
 1240             strftime(cur_time, sizeof(cur_time), "%T", &loc_t);
 1241             printf("%s UTC\n", cur_time);
 1242         }
 1243 
 1244         /* File composition: file_header, file_activity, record_header */
 1245         printf(_("File composition: (%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n"),
 1246                file_magic->hdr_types_nr[0], file_magic->hdr_types_nr[1], file_magic->hdr_types_nr[2],
 1247                file_hdr->act_types_nr[0], file_hdr->act_types_nr[1], file_hdr->act_types_nr[2],
 1248                file_hdr->rec_types_nr[0], file_hdr->rec_types_nr[1], file_hdr->rec_types_nr[2]);
 1249 
 1250         printf(_("Size of a long int: %d\n"), file_hdr->sa_sizeof_long);
 1251         printf("HZ = %lu\n", file_hdr->sa_hz);
 1252         printf(_("Number of activities in file: %u\n"),
 1253                file_hdr->sa_act_nr);
 1254 
 1255         printf(_("List of activities:\n"));
 1256         fal = file_actlst;
 1257         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
 1258 
 1259             p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND);
 1260 
 1261             printf("%02d: [%02x] ", fal->id, fal->magic);
 1262             if (p >= 0) {
 1263                 printf("%-20s", act[p]->name);
 1264             }
 1265             else {
 1266                 printf("%-20s", _("Unknown activity"));
 1267             }
 1268             printf(" %c:%4d", fal->has_nr ? 'Y' : 'N', fal->nr);
 1269             if (fal->nr2 > 1) {
 1270                 printf("x%d", fal->nr2);
 1271             }
 1272             printf("\t(%d,%d,%d)", fal->types_nr[0], fal->types_nr[1], fal->types_nr[2]);
 1273             if ((p >= 0) && (act[p]->magic == ACTIVITY_MAGIC_UNKNOWN)) {
 1274                 printf(_(" \t[Unknown format]"));
 1275             }
 1276             printf("\n");
 1277         }
 1278     }
 1279 }
 1280 
 1281 /*
 1282  ***************************************************************************
 1283  * Display the header of the report (SVG format).
 1284  *
 1285  * IN:
 1286  * @parm    Specific parameters. Here: number of rows of views to display
 1287  *      or canvas height entered on the command line (@graph_nr), and
 1288  *      max number of views on a single row (@views_per_row).
 1289  * @action  Action expected from current function.
 1290  * @dfile   Name of system activity data file (unused here).
 1291  * @file_magic  System activity file magic header (unused here).
 1292  * @file_hdr    System activity file standard header.
 1293  * @act     Array of activities (unused here).
 1294  * @id_seq  Activity sequence (unused here).
 1295  * @file_actlst List of (known or unknown) activities in file (unused here).
 1296  ***************************************************************************
 1297  */
 1298 __printf_funct_t print_svg_header(void *parm, int action, char *dfile,
 1299                   struct file_magic *file_magic,
 1300                   struct file_header *file_hdr,
 1301                   struct activity *act[], unsigned int id_seq[],
 1302                   struct file_activity *file_actlst)
 1303 {
 1304     struct svg_hdr_parm *hdr_parm = (struct svg_hdr_parm *) parm;
 1305     struct tm rectime;
 1306     unsigned int height = 0, ht = 0;
 1307     int i, p;
 1308 
 1309     if (action & F_BEGIN) {
 1310         printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 1311         printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ");
 1312         printf("\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
 1313         printf("<svg xmlns=\"http://www.w3.org/2000/svg\"");
 1314         if (DISPLAY_TOC(flags)) {
 1315             printf(" xmlns:xlink=\"http://www.w3.org/1999/xlink\"");
 1316         }
 1317         if (action & F_END) {
 1318             printf(">\n");
 1319         }
 1320     }
 1321 
 1322     if (action & F_MAIN) {
 1323         if (SET_CANVAS_HEIGHT(flags)) {
 1324             /*
 1325              * Option "-O height=..." used: @graph_nr is
 1326              * the SVG canvas height set on the command line.
 1327              */
 1328             height = hdr_parm->graph_nr;
 1329         }
 1330         else {
 1331             height = SVG_H_YSIZE +
 1332                  SVG_C_YSIZE * (DISPLAY_TOC(flags) ? hdr_parm->nr_act_dispd : 0) +
 1333                  SVG_T_YSIZE * hdr_parm->graph_nr;
 1334         }
 1335         if (height < 100) {
 1336             /* Min canvas height is 100 (at least to display "No data") */
 1337             height = 100;
 1338         }
 1339         printf(" width=\"%d\" height=\"%d\""
 1340                " fill=\"black\" stroke=\"#%06x\" stroke-width=\"1\">\n",
 1341                SVG_T_XSIZE * (hdr_parm->views_per_row), height,
 1342                svg_colors[palette][SVG_COL_DEFAULT_IDX]);
 1343         printf("<text x=\"0\" y=\"30\" text-anchor=\"start\" stroke=\"#%06x\">",
 1344                svg_colors[palette][SVG_COL_HEADER_IDX]);
 1345         print_gal_header(localtime_r((const time_t *) &(file_hdr->sa_ust_time), &rectime),
 1346                  file_hdr->sa_sysname, file_hdr->sa_release,
 1347                  file_hdr->sa_nodename, file_hdr->sa_machine,
 1348                  file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1,
 1349                  PLAIN_OUTPUT);
 1350         printf("</text>\n");
 1351         if (DISPLAY_TOC(flags)) {
 1352             for (i = 0; i < NR_ACT; i++) {
 1353                 if (!id_seq[i])
 1354                     continue;   /* Activity not in file */
 1355 
 1356                 p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
 1357                 if (!IS_SELECTED(act[p]->options) || !act[p]->g_nr)
 1358                     continue;   /* Activity not selected or no graph available */
 1359 
 1360                 printf("<a xlink:href=\"#g%d-0\" xlink:title=\"%s\">\n",
 1361                        act[p]->id, act[p]->name);
 1362                 printf("<text x=\"10\" y=\"%d\">%s</text></a>\n",
 1363                        SVG_H_YSIZE + ht, act[p]->desc);
 1364                 ht += SVG_C_YSIZE;
 1365             }
 1366         }
 1367     }
 1368 
 1369     if (action & F_END) {
 1370         if (!(action & F_BEGIN)) {
 1371             if (!hdr_parm->graph_nr) {
 1372                 /* No views displayed */
 1373                 printf("<text x= \"0\" y=\"%d\" text-anchor=\"start\" stroke=\"#%06x\">",
 1374                        SVG_H_YSIZE +
 1375                        SVG_C_YSIZE * (DISPLAY_TOC(flags) ? hdr_parm->nr_act_dispd : 0),
 1376                        svg_colors[palette][SVG_COL_ERROR_IDX]);
 1377                 printf("No data!</text>\n");
 1378             }
 1379             /* Give actual SVG height */
 1380             printf("<!-- Actual canvas height: %d -->\n",
 1381                    SVG_H_YSIZE +
 1382                    SVG_C_YSIZE * (DISPLAY_TOC(flags) ? hdr_parm->nr_act_dispd : 0) +
 1383                    SVG_T_YSIZE * hdr_parm->graph_nr);
 1384         }
 1385         printf("</svg>\n");
 1386     }
 1387 }
 1388 
 1389 /*
 1390  ***************************************************************************
 1391  * PCP header function.
 1392  *
 1393  * IN:
 1394  * @parm    Specific parameter (unused here).
 1395  * @action  Action expected from current function.
 1396  * @dfile   Name of PCP archive file.
 1397  * @file_magic  System activity file magic header (unused here).
 1398  * @file_hdr    System activity file standard header (unused here).
 1399  * @act     Array of activities (unused here).
 1400  * @id_seq  Activity sequence (unused here).
 1401  * @file_actlst List of (known or unknown) activities in file (unused here).
 1402  ***************************************************************************
 1403  */
 1404 __printf_funct_t print_pcp_header(void *parm, int action, char *dfile,
 1405                   struct file_magic *file_magic,
 1406                   struct file_header *file_hdr,
 1407                   struct activity *act[], unsigned int id_seq[],
 1408                   struct file_activity *file_actlst)
 1409 {
 1410 #ifdef HAVE_PCP
 1411     char buf[64];
 1412     struct tm lrectime;
 1413     unsigned long long utc_sec = file_hdr->sa_ust_time;
 1414 
 1415     if (action & F_BEGIN) {
 1416         /* Create new PCP context */
 1417         pmiStart(dfile, FALSE);
 1418 
 1419         if (PRINT_LOCAL_TIME(flags)) {
 1420             tzset();    /* Set timezone value in tzname */
 1421             pmiSetTimezone(tzname[0]);
 1422         }
 1423         else {
 1424             pmiSetTimezone("UTC");
 1425         }
 1426 
 1427         /* Save hostname */
 1428         pmiSetHostname(file_hdr->sa_nodename);
 1429 
 1430         /* Save number of CPU in PCP archive */
 1431         pmiAddMetric("hinv.ncpu",
 1432                  PM_IN_NULL, PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_DISCRETE,
 1433                  pmiUnits(0, 0, 1, 0, 0, PM_COUNT_ONE));
 1434         snprintf(buf, sizeof(buf), "%u",
 1435              file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
 1436         pmiPutValue("hinv.ncpu", NULL, buf);
 1437     }
 1438 
 1439     if (action & F_END) {
 1440         if (action & F_BEGIN) {
 1441             /* Only the header data will be written to PCP archive */
 1442             if (!PRINT_LOCAL_TIME(flags)) {
 1443                 /* Convert a time_t value from local time to UTC */
 1444                 if (gmtime_r((const time_t *) &(file_hdr->sa_ust_time), &lrectime)) {
 1445                     utc_sec = mktime(&lrectime);
 1446                 }
 1447             }
 1448             pmiWrite(utc_sec, 0);
 1449         }
 1450         pmiEnd();
 1451     }
 1452 #endif
 1453 }
 1454 
 1455 /*
 1456  ***************************************************************************
 1457  * Count the number of new network interfaces in current sample. If a new
 1458  * interface is found then add it to the linked list starting at
 1459  * @a->item_list.
 1460  *
 1461  * IN:
 1462  * @a       Activity structure with statistics.
 1463  * @curr    Index in array for current sample statistics.
 1464  *
 1465  * RETURNS:
 1466  * Number of new interfaces identified in current sample that were not
 1467  * previously in the list.
 1468  ***************************************************************************
 1469  */
 1470 __nr_t count_new_net_dev(struct activity *a, int curr)
 1471 {
 1472     int i, nr = 0;
 1473     struct stats_net_dev *sndc;
 1474 
 1475     for (i = 0; i < a->nr[curr]; i++) {
 1476         sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
 1477 
 1478         nr += add_list_item(&(a->item_list), sndc->interface, MAX_IFACE_LEN);
 1479     }
 1480 
 1481     return nr;
 1482 }
 1483 
 1484 /*
 1485  ***************************************************************************
 1486  * Count the number of new network interfaces in current sample. If a new
 1487  * interface is found then add it to the linked list starting at
 1488  * @a->item_list.
 1489  *
 1490  * IN:
 1491  * @a       Activity structure with statistics.
 1492  * @curr    Index in array for current sample statistics.
 1493  *
 1494  * RETURNS:
 1495  * Number of new interfaces identified in current sample that were not
 1496  * previously in the list.
 1497  ***************************************************************************
 1498  */
 1499 __nr_t count_new_net_edev(struct activity *a, int curr)
 1500 {
 1501     int i, nr = 0;
 1502     struct stats_net_edev *snedc;
 1503 
 1504     for (i = 0; i < a->nr[curr]; i++) {
 1505         snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
 1506 
 1507         nr += add_list_item(&(a->item_list), snedc->interface, MAX_IFACE_LEN);
 1508     }
 1509 
 1510     return nr;
 1511 }
 1512 
 1513 /*
 1514  ***************************************************************************
 1515  * Count the number of new filesystems in current sample. If a new
 1516  * filesystem is found then add it to the linked list starting at
 1517  * @a->item_list.
 1518  *
 1519  * IN:
 1520  * @a       Activity structure with statistics.
 1521  * @curr    Index in array for current sample statistics.
 1522  *
 1523  * RETURNS:
 1524  * Number of new filesystems identified in current sample that were not
 1525  * previously in the list.
 1526  ***************************************************************************
 1527  */
 1528 __nr_t count_new_filesystem(struct activity *a, int curr)
 1529 {
 1530     int i, nr = 0;
 1531     struct stats_filesystem *sfc;
 1532 
 1533     for (i = 0; i < a->nr[curr]; i++) {
 1534         sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
 1535 
 1536         nr += add_list_item(&(a->item_list),
 1537                     DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name,
 1538                     MAX_FS_LEN);
 1539     }
 1540 
 1541     return nr;
 1542 }
 1543 
 1544 /*
 1545  ***************************************************************************
 1546  * Count the number of new fchosts in current sample. If a new
 1547  * fchost is found then add it to the linked list starting at
 1548  * @a->item_list.
 1549  *
 1550  * IN:
 1551  * @a       Activity structure with statistics.
 1552  * @curr    Index in array for current sample statistics.
 1553  *
 1554  * RETURNS:
 1555  * Number of new fchosts identified in current sample that were not
 1556  * previously in the list.
 1557  ***************************************************************************
 1558  */
 1559 __nr_t count_new_fchost(struct activity *a, int curr)
 1560 {
 1561     int i, nr = 0;
 1562     struct stats_fchost *sfcc;
 1563 
 1564     for (i = 0; i < a->nr[curr]; i++) {
 1565         sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
 1566 
 1567         nr += add_list_item(&(a->item_list), sfcc->fchost_name, MAX_FCH_LEN);
 1568     }
 1569 
 1570     return nr;
 1571 }
 1572 
 1573 /*
 1574  ***************************************************************************
 1575  * Count the number of new block devices in current sample. If a new
 1576  * block device is found then add it to the linked list starting at
 1577  * @a->item_list.
 1578  *
 1579  * IN:
 1580  * @a       Activity structure with statistics.
 1581  * @curr    Index in array for current sample statistics.
 1582  *
 1583  * RETURNS:
 1584  * Number of new block devices identified in current sample that were not
 1585  * previously in the list.
 1586  ***************************************************************************
 1587  */
 1588 __nr_t count_new_disk(struct activity *a, int curr)
 1589 {
 1590     int i, nr = 0;
 1591     struct stats_disk *sdc;
 1592 
 1593     for (i = 0; i < a->nr[curr]; i++) {
 1594         sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
 1595 
 1596         nr += add_list_item(&(a->item_list),
 1597                     get_sa_devname(sdc->major, sdc->minor, flags),
 1598                     MAX_DEV_LEN);
 1599     }
 1600 
 1601     return nr;
 1602 }
 1603 
 1604 /*
 1605  ***************************************************************************
 1606  * Init custom color palette used to draw graphs (sadf -g).
 1607  ***************************************************************************
 1608  */
 1609 void init_custom_color_palette()
 1610 {
 1611     char *e, *p;
 1612     int len;
 1613     unsigned int val;
 1614 
 1615     /* Read S_COLORS_PALETTE environment variable */
 1616     if ((e = __getenv(ENV_COLORS_PALETTE)) == NULL)
 1617         /* Environment variable not set */
 1618         return;
 1619 
 1620     for (p = strtok(e, ":"); p; p =strtok(NULL, ":")) {
 1621 
 1622         len = strlen(p);
 1623         if ((len > 8) || (len < 3) || (*(p + 1) != '=') ||
 1624             (strspn(p + 2, "0123456789ABCDEFabcdef") != (len - 2)))
 1625             /* Ignore malformed codes */
 1626             continue;
 1627 
 1628         sscanf(p + 2, "%x", &val);
 1629 
 1630         if ((*p >= '0') && (*p <= '9')) {
 1631             svg_colors[SVG_CUSTOM_COL_PALETTE][*p & 0xf] = val;
 1632             continue;
 1633         }
 1634         else if (((*p >= 'A') && (*p <= 'F')) ||
 1635              ((*p >= 'a') && (*p <= 'f'))) {
 1636             svg_colors[SVG_CUSTOM_COL_PALETTE][9 + (*p & 0xf)] = val;
 1637             continue;
 1638         }
 1639 
 1640         switch (*p) {
 1641             case 'G':
 1642                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_GRID_IDX] = val;
 1643                 break;
 1644             case 'H':
 1645                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_HEADER_IDX] = val;
 1646                 break;
 1647             case 'I':
 1648                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_INFO_IDX] = val;
 1649                 break;
 1650             case 'K':
 1651                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_BCKGRD_IDX] = val;
 1652                 break;
 1653             case 'L':
 1654                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_DEFAULT_IDX] = val;
 1655                 break;
 1656             case 'T':
 1657                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_TITLE_IDX] = val;
 1658                 break;
 1659             case 'W':
 1660                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_ERROR_IDX] = val;
 1661                 break;
 1662             case 'X':
 1663                 svg_colors[SVG_CUSTOM_COL_PALETTE][SVG_COL_AXIS_IDX] = val;
 1664                 break;
 1665         }
 1666     }
 1667 }