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