2 * svg_stats.c: Functions used by sadf to display statistics in SVG format.
3 * (C) 2016-2021 by Sebastien GODARD (sysstat <at> orange.fr)
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. *
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 *
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 ***************************************************************************
30 #include "svg_stats.h"
35 #define _(string) gettext(string)
37 #define _(string) (string)
40 extern uint64_t flags;
43 unsigned int svg_colors[SVG_COL_PALETTE_NR][SVG_COL_PALETTE_SIZE] =
44 {{0x00cc00, 0xff00bf, 0x00ffff, 0xff0000, /* Default palette */
45 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
46 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
47 0xcc3300, 0x50040f, 0xffffbf, 0x193d55,
48 0x000000, 0xffffff, 0x202020, 0xffff00,
49 0xffff00, 0x808080, 0xa52a2a, 0xff0000},
51 {0x000000, 0x1a1aff, 0x1affb2, 0xb21aff, /* Custom color palette */
52 0x1ab2ff, 0xff1a1a, 0xffb31a, 0xb2ff1a,
53 0xefefef, 0x000000, 0x1a1aff, 0x1affb2,
54 0xb21aff, 0x1ab2ff, 0xff1a1a, 0xffb31a,
55 0xffffff, 0x000000, 0xbebebe, 0x000000,
56 0x000000, 0x000000, 0x000000, 0x000000},
58 {0x696969, 0xbebebe, 0x000000, 0xa9a9a9, /* Black & white palette */
59 0x708090, 0xc0c0c0, 0x808080, 0xd3d3d3,
60 0x909090, 0x696969, 0xbebebe, 0x000000,
61 0x000000, 0xa9a9a9, 0xc0c0c0, 0x808080,
62 0xffffff, 0x000000, 0xbebebe, 0x000000,
63 0x000000, 0x000000, 0x000000, 0x000000}};
66 ***************************************************************************
67 * Compare the values of a statistics sample with the max and min values
68 * already found in previous samples for this same activity. If some new
69 * min or max values are found, then save them.
70 * Assume values cannot be negative.
71 * The structure containing the statistics sample is composed of @llu_nr
72 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
73 * followed by @u_nr unsigned int fields.
76 * @types_nr Number of fields whose type is "long long", "long" and "int"
77 * composing the structure.
78 * @cs Pointer on current sample statistics structure.
79 * @ps Pointer on previous sample statistics structure (may be NULL).
80 * @itv Interval of time in 1/100th of a second.
81 * @spmin Array containing min values already found for this activity.
82 * @spmax Array containing max values already found for this activity.
83 * @g_fields Index in spmin/spmax arrays where extrema values for each
84 * activity metric will be saved. As a consequence spmin/spmax
85 * arrays may contain values in a different order than that of
86 * the fields in the statistics structure.
89 * @spmin Array containing the possible new min values for current activity.
90 * @spmax Array containing the possible new max values for current activity.
91 ***************************************************************************
93 void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
94 double *spmin, double *spmax, int g_fields[])
96 unsigned long long *lluc, *llup;
97 unsigned long *luc, *lup;
98 unsigned int *uc, *up;
102 /* Compare unsigned long long fields */
103 lluc = (unsigned long long *) cs;
104 llup = (unsigned long long *) ps;
105 for (i = 0; i < types_nr[0]; i++, m++) {
107 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
111 * If no pointer on previous sample has been given
112 * then the value is not a per-second one.
114 val = (double) *lluc;
116 if (val < *(spmin + g_fields[m])) {
117 *(spmin + g_fields[m]) = val;
119 if (val > *(spmax + g_fields[m])) {
120 *(spmax + g_fields[m]) = val;
122 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
124 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
128 /* Compare unsigned long fields */
129 luc = (unsigned long *) lluc;
130 lup = (unsigned long *) llup;
131 for (i = 0; i < types_nr[1]; i++, m++) {
133 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
138 if (val < *(spmin + g_fields[m])) {
139 *(spmin + g_fields[m]) = val;
141 if (val > *(spmax + g_fields[m])) {
142 *(spmax + g_fields[m]) = val;
144 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
146 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
150 /* Compare unsigned int fields */
151 uc = (unsigned int *) luc;
152 up = (unsigned int *) lup;
153 for (i = 0; i < types_nr[2]; i++, m++) {
155 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
160 if (val < *(spmin + g_fields[m])) {
161 *(spmin + g_fields[m]) = val;
163 if (val > *(spmax + g_fields[m])) {
164 *(spmax + g_fields[m]) = val;
166 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
168 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
174 ***************************************************************************
175 * Find the min and max values of all the graphs that will be drawn in the
176 * same view. The graphs have their own min and max values in
177 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
180 * @pos Position in array for the first graph extrema value.
181 * @n Number of graphs to scan.
182 * @spmin Array containing min values for graphs.
183 * @spmax Array containing max values for graphs.
186 * @gmin Global min value found.
187 * @gmax Global max value found.
188 ***************************************************************************
190 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
191 double *gmin, double *gmax)
195 *gmin = *(spmin + pos);
196 *gmax = *(spmax + pos);
198 for (i = 1; i < n; i++) {
199 if (*(spmin + pos + i) < *gmin) {
200 *gmin = *(spmin + pos + i);
202 if (*(spmax + pos + i) > *gmax) {
203 *gmax = *(spmax + pos + i);
209 ***************************************************************************
210 * Allocate arrays used to save graphs data, min and max values.
211 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
212 * array is returned. This is equivalent to "char data[][n]" where each
213 * element is of indeterminate size and will contain the graph data (eg.
214 * << path d="M12,14 L13,16..." ... >>.
215 * The size of element data[i] is given by outsize[i].
216 * Also allocate an array to save min values (equivalent to "double spmin[n]")
217 * and an array for max values (equivalent to "double spmax[n]").
220 * @n Number of graphs to draw for current activity.
223 * @outsize Array that will contain the sizes of each element in array
224 * of chars. Equivalent to "int outsize[n]" with
225 * outsize[n] = sizeof(data[][n]).
226 * @spmin Array that will contain min values for current activity.
227 * @spmax Array that will contain max values for current activity.
230 * Pointer on array of arrays of chars that will contain the graphs data.
232 * NB: @min and @max arrays contain values in the same order as the fields
233 * in the statistics structure.
234 ***************************************************************************
236 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
243 * Allocate an array of pointers. Each of these pointers will
244 * be an array of chars.
246 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
250 /* Allocate array that will contain the size of each array of chars */
251 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
255 /* Allocate array that will contain the min value of each graph */
256 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
260 /* Allocate array that will contain the max value of each graph */
261 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
265 /* Allocate arrays of chars that will contain graphs data */
266 for (i = 0; i < n; i++) {
267 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
272 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
273 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
274 *(*spmin + i) = DBL_MAX; /* Init min and max values */
275 *(*spmax + i) = -DBL_MAX;
282 ***************************************************************************
283 * Save SVG code for current graph.
286 * @data SVG code to append to current graph definition.
287 * @out Pointer on array of chars for current graph definition.
288 * @outsize Size of array of chars for current graph definition.
291 * @out Pointer on array of chars for current graph definition that
292 * has been updated with the addition of current sample data.
293 * @outsize Array that containing the (possibly new) sizes of each
294 * element in array of chars.
295 ***************************************************************************
297 void save_svg_data(char *data, char **out, int *outsize)
303 /* Determine space left in array */
304 len = *outsize - strlen(out_p) - 1;
305 if (strlen(data) >= len) {
307 * If current array of chars doesn't have enough space left
308 * then reallocate it with CHUNKSIZE more bytes.
310 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
312 *outsize += CHUNKSIZE;
315 strncat(out_p, data, len);
319 ***************************************************************************
320 * Update line graph definition by appending current X,Y coordinates.
323 * @timetag Timestamp in seconds since the epoch for current sample
324 * stats. Will be used as X coordinate.
325 * @value Value of current sample metric. Will be used as Y coordinate.
326 * @out Pointer on array of chars for current graph definition.
327 * @outsize Size of array of chars for current graph definition.
328 * @restart Set to TRUE if a RESTART record has been read since the last
332 * @out Pointer on array of chars for current graph definition that
333 * has been updated with the addition of current sample data.
334 * @outsize Array that containing the (possibly new) sizes of each
335 * element in array of chars.
336 ***************************************************************************
338 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
343 /* Prepare additional graph definition data */
344 snprintf(data, 128, " %c%llu,%.2f", restart ? 'M' : 'L', timetag, value);
347 save_svg_data(data, out, outsize);
351 ***************************************************************************
352 * Update line graph definition by appending current X,Y coordinates. Use
353 * (unsigned long) integer values here.
356 * @timetag Timestamp in seconds since the epoch for current sample
357 * stats. Will be used as X coordinate.
358 * @value Value of current sample metric. Will be used as Y coordinate.
359 * @out Pointer on array of chars for current graph definition.
360 * @outsize Size of array of chars for current graph definition.
361 * @restart Set to TRUE if a RESTART record has been read since the last
365 * @out Pointer on array of chars for current graph definition that
366 * has been updated with the addition of current sample data.
367 * @outsize Array that containing the (possibly new) sizes of each
368 * element in array of chars.
369 ***************************************************************************
371 void lniappend(unsigned long long timetag, unsigned long long value, char **out,
372 int *outsize, int restart)
376 /* Prepare additional graph definition data */
377 snprintf(data, 128, " %c%llu,%llu", restart ? 'M' : 'L', timetag, value);
380 save_svg_data(data, out, outsize);
384 ***************************************************************************
385 * Update bar graph definition by adding a new rectangle.
388 * @timetag Timestamp in seconds since the epoch for current sample
389 * stats. Will be used as X coordinate.
390 * @value Value of current sample metric. Will be used as rectangle
392 * @offset Offset for Y coordinate.
393 * @out Pointer on array of chars for current graph definition.
394 * @outsize Size of array of chars for current graph definition.
395 * @dt Interval of time in seconds between current and previous
399 * @out Pointer on array of chars for current graph definition that
400 * has been updated with the addition of current sample data.
401 * @outsize Array that containing the (possibly new) sizes of each
402 * element in array of chars.
403 ***************************************************************************
405 void brappend(unsigned long long timetag, double offset, double value, char **out,
406 int *outsize, unsigned long long dt)
409 unsigned long long t = 0;
411 /* Prepare additional graph definition data */
412 if ((value == 0.0) || (dt == 0))
413 /* Don't draw a flat rectangle! */
419 snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
420 t, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
423 save_svg_data(data, out, outsize);
428 ***************************************************************************
429 * Update CPU graph and min/max values for each metric.
432 * @timetag Timestamp in seconds since the epoch for current sample
433 * stats. Will be used as X coordinate.
434 * @offset Offset for Y coordinate.
435 * @value Value of current CPU metric. Will be used as rectangle
437 * @out Pointer on array of chars for current graph definition.
438 * @outsize Size of array of chars for current graph definition.
439 * @dt Interval of time in seconds between current and previous
441 * @spmin Min value already found for this CPU metric.
442 * @spmax Max value already found for this CPU metric.
445 * @offset New offset value, to use to draw next rectangle
446 * @out Pointer on array of chars for current graph definition that
447 * has been updated with the addition of current sample data.
448 * @outsize Array that containing the (possibly new) sizes of each
449 * element in array of chars.
450 ***************************************************************************
452 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
453 int *outsize, unsigned long long dt, double *spmin, double *spmax)
455 /* Save min and max values */
456 if (value < *spmin) {
459 if (value > *spmax) {
462 /* Prepare additional graph definition data */
463 brappend(timetag, *offset, value, out, outsize, dt);
469 ***************************************************************************
470 * Update rectangular graph and min/max values.
473 * @timetag Timestamp in seconds since the epoch for current sample
474 * stats. Will be used as X coordinate.
475 * @p_value Metric value for previous sample
476 * @value Metric value for current sample.
477 * @out Pointer on array of chars for current graph definition.
478 * @outsize Size of array of chars for current graph definition.
479 * @restart Set to TRUE if a RESTART record has been read since the last
481 * @dt Interval of time in seconds between current and previous
483 * @spmin Min value already found for this metric.
484 * @spmax Max value already found for this metric.
487 * @out Pointer on array of chars for current graph definition that
488 * has been updated with the addition of current sample data.
489 * @outsize Array that containing the (possibly new) sizes of each
490 * element in array of chars.
491 * @spmin Min value for this metric.
492 * @spmax Max value for this metric.
493 ***************************************************************************
495 void recappend(unsigned long long timetag, double p_value, double value, char **out,
496 int *outsize, int restart, unsigned long long dt,
497 double *spmin, double *spmax)
499 char data[512], data1[128], data2[128];
500 unsigned long long t = 0;
502 /* Save min and max values */
503 if (value < *spmin) {
506 if (value > *spmax) {
512 /* Prepare additional graph definition data */
514 snprintf(data1, sizeof(data1), " M%llu,%.2f", t, p_value);
515 data1[sizeof(data1) - 1] = '\0';
517 if (p_value != value) {
518 snprintf(data2, sizeof(data2), " L%llu,%.2f", timetag, value);
519 data2[sizeof(data2) - 1] = '\0';
521 snprintf(data, sizeof(data), "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
522 p_value != value ? data2 : "");
523 data[sizeof(data) - 1] = '\0';
525 save_svg_data(data, out, outsize);
529 ***************************************************************************
530 * Calculate 10 raised to the power of n.
533 * @n Power number to use.
536 * 10 raised to the power of n.
537 ***************************************************************************
539 unsigned int pwr10(int n)
544 for (i = 0; i < n; i++) {
552 ***************************************************************************
553 * Autoscale graphs of a given view.
556 * @asf_nr (Maximum) number of autoscale factors.
557 * @group Number of graphs in current view.
558 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
559 * @pos Position in array for the first graph in view.
560 * @gmax Global max value for all graphs in view.
561 * @spmax Array containing max values for graphs.
564 * @asfactor Autoscale factors (one for each graph).
565 ***************************************************************************
567 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
568 double gmax, double *spmax)
573 for (j = 0; j < asf_nr; j++) {
574 /* Init autoscale factors */
578 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
580 for (j = 0; (j < group) && (j < asf_nr); j++) {
581 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
584 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
585 if (strlen(val) > 0) {
586 asfactor[j] = pwr10(strlen(val) - 1);
593 ***************************************************************************
594 * Display background grid (horizontal lines) and corresponding graduations.
597 * @ypos Gap between two horizontal lines.
598 * @yfactor Scaling factor on Y axis.
599 * @lmax Max value for current view.
600 * @dp Number of decimal places for graduations.
601 ***************************************************************************
603 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
608 /* Print marker in debug mode */
609 if (DISPLAY_DEBUG_MODE(flags)) {
610 printf("<!-- Hgrid -->\n");
614 /* Display horizontal lines (except on X axis) */
616 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
617 "stroke: #%06x\" transform=\"scale(1,%f)\"/>\n",
618 ypos * j, SVG_G_XSIZE, ypos * j,
619 svg_colors[palette][SVG_COL_GRID_IDX],
624 * Display graduations.
625 * Use same rounded value for graduation numbers as for grid lines
626 * to make sure they are properly aligned.
628 sprintf(stmp, "%.2f", ypos * j);
629 printf("<text x=\"0\" y=\"%ld\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
630 "text-anchor: end\">%.*f.</text>\n",
631 (long) (atof(stmp) * yfactor),
632 svg_colors[palette][SVG_COL_AXIS_IDX],
636 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
640 ***************************************************************************
641 * Display background grid (vertical lines) and corresponding graduations.
644 * @xpos Gap between two vertical lines.
645 * @xfactor Scaling factor on X axis.
646 * @v_gridnr Default number of vertical lines to display. The actual
647 * number may vary between this value and 2 times this value.
648 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
649 ***************************************************************************
651 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
653 struct record_header stamp;
655 char cur_time[TIMESTAMP_LEN];
658 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
660 /* Print marker in debug mode */
661 if (DISPLAY_DEBUG_MODE(flags)) {
662 printf("<!-- Vgrid -->\n");
666 * What really matters to know when we should stop drawing vertical lines
667 * is the time end. v_gridnr is only informative and used to calculate
668 * the gap between two lines.
670 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
672 /* Display vertical lines */
673 if (sa_get_record_timestamp_struct(flags, &stamp, &rectime)) {
675 fprintf(stderr, "%s: ust_time: %llu\n", __FUNCTION__, stamp.ust_time);
679 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
680 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
681 "stroke: #%06x\" transform=\"scale(%f,1)\"/>\n",
682 xpos * j, xpos * j, -SVG_G_YSIZE,
683 svg_colors[palette][SVG_COL_GRID_IDX],
686 * Display graduations.
687 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
688 * In this case, we should rather display the exact time instead of only the hour.
690 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
691 printf("<text x=\"%ld\" y=\"15\" style=\"fill: #%06x; stroke: none; font-size: 14px; "
692 "text-anchor: start\">%2d:00</text>\n",
693 (long) (xpos * j * xfactor) - 15,
694 svg_colors[palette][SVG_COL_AXIS_IDX],
698 printf("<text x=\"%ld\" y=\"10\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
699 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
700 (long) (xpos * j * xfactor),
701 svg_colors[palette][SVG_COL_AXIS_IDX],
702 (long) (xpos * j * xfactor), cur_time);
704 stamp.ust_time += xpos;
707 if (!PRINT_LOCAL_TIME(flags)) {
708 printf("<text x=\"-10\" y=\"30\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
709 "text-anchor: end\">UTC</text>\n",
710 svg_colors[palette][SVG_COL_INFO_IDX]);
715 ***************************************************************************
716 * Calculate the value on the Y axis between two horizontal lines that will
717 * make the graph background grid.
720 * @lmax Max value reached for this graph.
723 * @dp Number of decimal places for Y graduations.
726 * Value between two horizontal lines.
727 ***************************************************************************
729 double ygrid(double lmax, int *dp)
740 n = (long) (lmax / SVG_H_GRIDNR);
743 return (lmax / SVG_H_GRIDNR);
745 snprintf(val, 32, "%ld", n);
752 return ((double) (((long) (n / e)) * e));
756 ***************************************************************************
757 * Calculate the value on the X axis between two vertical lines that will
758 * make the graph background grid.
761 * @timestart First data timestamp (X coordinate of the first data point).
762 * @timeend Last data timestamp (X coordinate of the last data point).
763 * @v_gridnr Number of vertical lines to display. Its value is normally
764 * SVG_V_GRIDNR, except when option "oneday" is used, in which
765 * case it is set to 12.
768 * Value between two vertical lines.
769 ***************************************************************************
771 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
773 if ((timeend - timestart) <= v_gridnr)
776 return ((timeend - timestart) / v_gridnr);
780 ***************************************************************************
781 * Free global graphs structures.
784 * @out Pointer on array of chars for each graph definition.
785 * @outsize Size of array of chars for each graph definition.
786 * @spmin Array containing min values for graphs.
787 * @spmax Array containing max values for graphs.
788 ***************************************************************************
790 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
807 ***************************************************************************
808 * Skip current view where all graphs have only zero values. This function
809 * is called when option "skipempty" has been used, or when "No data" have
810 * been found for current view.
813 * @out Pointer on array of chars for each graph definition.
814 * @pos Position of current view in the array of graphs definitions.
815 * @group Number of graphs in current view.
818 * @pos Position of next view in the array of graphs definitions.
819 ***************************************************************************
821 void skip_current_view(char **out, int *pos, int group)
826 for (j = 0; j < group; j++) {
827 out_p = *(out + *pos + j);
829 /* Even if not displayed, current graph data have to be freed */
837 ***************************************************************************
838 * Display all graphs for current activity.
841 * @g_nr Number of views to display.
842 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
843 * @title Titles for each set of graphs.
844 * @g_title Titles for each graph.
845 * @item_name Item (network interface, etc.) name.
846 * @group Indicate how graphs are grouped together to make sets.
847 * @spmin Array containing min values for graphs.
848 * @spmax Array containing max values for graphs.
849 * @out Pointer on array of chars for each graph definition.
850 * @outsize Size of array of chars for each graph definition.
851 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
852 * time for the first sample of stats (.@ust_time_first), and
853 * times used as start and end values on the X axis
854 * (.@ust_time_ref and .@ust_time_end).
855 * @record_hdr Pointer on record header of current stats sample.
856 * @skip_void Set to <> 0 if graphs with no data should be skipped.
857 * This is typicallly used to not display CPU offline on the
859 * @a Current activity structure.
860 * @xid Current activity extra id number.
863 * TRUE if at least one graph has been displayed.
864 ***************************************************************************
866 int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
867 int group[], double *spmin, double *spmax, char **out, int *outsize,
868 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
869 struct activity *a, unsigned int xid)
872 int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE, palpos;
873 int v_gridnr, xv, yv;
874 unsigned int asfactor[16];
876 double lmax, xfactor, yfactor, ypos, gmin, gmax;
877 char val[32], cur_date[TIMESTAMP_LEN];
880 /* Print activity name in debug mode */
881 if (DISPLAY_DEBUG_MODE(flags)) {
882 printf("<!-- Name: %s -->\n", a->name);
885 /* For each view which is part of current activity */
886 for (i = 0; i < g_nr; i++) {
888 /* Print view number in debug mode */
889 if (DISPLAY_DEBUG_MODE(flags)) {
890 printf("<!-- View %d -->\n", i + 1);
893 /* Used as index in color palette */
894 palpos = (palette == SVG_BW_COL_PALETTE ? 0 : pos);
896 /* Get global min and max value for current view */
897 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
899 /* Don't display empty views if requested */
900 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
901 skip_current_view(out, &pos, group[i]);
904 /* Skip void graphs */
905 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
909 /* Translate to proper position for current activity */
910 printf("<g id=\"g%d-%d\" transform=\"translate(0,%d)\">\n",
913 SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
914 SVG_T_YSIZE * svg_p->graph_no);
918 /* Increment number of views actually displayed */
921 /* Compute top left position of view */
922 if (PACK_VIEWS(flags)) {
923 xv = (views_nr - 1) * SVG_T_XSIZE;
928 yv = (views_nr - 1) * SVG_T_YSIZE;
931 /* Graph background */
932 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\" fill=\"#%06x\"/>\n",
933 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE,
934 svg_colors[palette][SVG_COL_BCKGRD_IDX]);
937 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">%s",
939 svg_colors[palette][SVG_COL_TITLE_IDX],
942 printf(" [%s]", item_name);
945 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
946 "(Min, Max values)</tspan>\n</text>\n",
947 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25,
948 svg_colors[palette][SVG_COL_INFO_IDX]);
951 * At least two samples are needed.
952 * And a min and max value should have been found.
954 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
955 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
957 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">No data</text>\n",
958 xv, yv + SVG_M_YSIZE,
959 svg_colors[palette][SVG_COL_ERROR_IDX]);
960 skip_current_view(out, &pos, group[i]);
965 printf("<polyline points=\"%d,%d %d,%d %d,%d\" style=\"fill: #%06x; stroke: #%06x; stroke-width: 2\"/>\n",
966 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
967 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
968 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
969 svg_colors[palette][SVG_COL_BCKGRD_IDX],
970 svg_colors[palette][SVG_COL_AXIS_IDX]);
972 /* Autoscaling graphs if needed */
973 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
976 for (j = 0; j < group[i]; j++) {
977 /* Set dp to TRUE (1) if current metric is based on integer values */
978 dp = (g_title[pos + j][0] == '~');
979 snprintf(val, 32, "x%u ", asfactor[j]);
980 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
981 "%s %s(%.*f, %.*f)</text>\n",
982 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
983 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
984 asfactor[j] == 1 ? "" : val,
985 !dp * 2, *(spmin + pos + j) * asfactor[j],
986 !dp * 2, *(spmax + pos + j) * asfactor[j]);
989 if (DISPLAY_INFO(flags)) {
990 /* Display additional info (hostname, date) */
991 printf("<text x=\"%d\" y=\"%d\" "
992 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
994 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
995 svg_colors[palette][SVG_COL_INFO_IDX],
996 svg_p->file_hdr->sa_nodename);
998 /* Get report date */
999 set_report_date(localtime_r((const time_t *) &(svg_p->file_hdr->sa_ust_time), &rectime),
1000 cur_date, sizeof(cur_date));
1001 printf("<tspan x=\"%d\" y=\"%d\" "
1002 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
1003 "%s</tspan>\n</text>\n",
1004 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
1005 svg_colors[palette][SVG_COL_INFO_IDX],
1009 /* Translate to proper position for current graph within current activity */
1010 printf("<g transform=\"translate(%d,%d)\">\n",
1011 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
1014 if (g_type[i] == SVG_LINE_GRAPH) {
1015 /* For line graphs */
1017 /* If all values are zero then set current max value to 1 */
1023 /* Max value cannot be too small, else Y graduations will be meaningless */
1024 if (lmax < SVG_H_GRIDNR * 0.01) {
1025 lmax = SVG_H_GRIDNR * 0.01;
1027 ypos = ygrid(lmax, &dp);
1030 /* For bar graphs (used for %values) */
1031 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
1032 dp = 0; /* No decimals */
1034 /* Max should be always 100% except for percentage values greater than 100% */
1042 yfactor = (double) -SVG_G_YSIZE / lmax;
1044 /* Display horizontal lines and graduations */
1045 display_hgrid(ypos, yfactor, lmax, dp);
1047 /* Set number of vertical lines to 12 when option "oneday" is used */
1048 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1050 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1051 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1053 /* Display vertical lines and graduations */
1054 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1056 /* Print marker in debug mode */
1057 if (DISPLAY_DEBUG_MODE(flags)) {
1058 printf("<!-- Graphs -->\n");
1061 /* Draw current graphs set */
1062 for (j = 0; j < group[i]; j++) {
1063 out_p = *(out + pos + j);
1064 if (g_type[i] == SVG_LINE_GRAPH) {
1066 printf("<path d=\"%s\" "
1067 "style=\"vector-effect: non-scaling-stroke; "
1068 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1069 "transform=\"scale(%f,%f)\"/>\n",
1071 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK],
1073 yfactor * asfactor[j]);
1075 else if (*out_p) { /* Ignore flat bars */
1077 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1078 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1079 printf("%s\n", out_p);
1090 /* For next row of views */
1091 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1098 ***************************************************************************
1099 * Display CPU statistics in SVG.
1102 * @a Activity structure with statistics.
1103 * @curr Index in array for current sample statistics.
1104 * @action Action expected from current function.
1105 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1106 * flag indicating that a restart record has been previously
1107 * found (.@restart), and time used for the X axis origin
1109 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1111 * @record_hdr Pointer on record header of current stats sample.
1112 ***************************************************************************
1114 #define CPU_ARRAY_SZ 10
1115 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1116 unsigned long long itv, struct record_header *record_hdr)
1118 struct stats_cpu *scc, *scp;
1119 unsigned long long deltot_jiffies = 1;
1120 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1123 int g_type[] = {SVG_BAR_GRAPH};
1124 char *title[] = {"CPU utilization"};
1125 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1126 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1127 static double *spmin, *spmax;
1129 static int *outsize;
1134 if (action & F_BEGIN) {
1136 * Allocate arrays that will contain the graphs data
1137 * and the min/max values.
1139 out = allocate_graph_lines(CPU_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
1142 if (action & F_MAIN) {
1144 /* @nr[curr] cannot normally be greater than @nr_ini */
1145 if (a->nr[curr] > a->nr_ini) {
1146 a->nr_ini = a->nr[curr];
1150 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1151 * and look for offline CPU.
1153 if (a->nr_ini > 1) {
1154 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1155 flags, offline_cpu_bitmap);
1159 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1161 /* Should current CPU (including CPU "all") be displayed? */
1162 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1163 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1164 /* Don't display CPU */
1167 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1168 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1170 pos = i * CPU_ARRAY_SZ;
1174 /* This is CPU "all" */
1175 if (a->nr_ini == 1) {
1177 * This is a UP machine. In this case
1178 * interval has still not been calculated.
1180 deltot_jiffies = get_per_cpu_interval(scc, scp);
1182 if (!deltot_jiffies) {
1183 /* CPU "all" cannot be tickless */
1189 * Recalculate interval for current proc.
1190 * If result is 0 then current CPU is a tickless one.
1192 deltot_jiffies = get_per_cpu_interval(scc, scp);
1194 if (!deltot_jiffies) { /* Current CPU is tickless */
1196 val = 100.0; /* Tickless CPU: %idle = 100% */
1198 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1201 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1205 /* Check min/max values for %user, etc. */
1206 for (k = 0; k < j; k++) {
1207 if (0.0 < *(spmin + pos + k)) {
1208 *(spmin + pos + k) = 0.0;
1210 if (0.0 > *(spmax + pos + k)) {
1211 *(spmax + pos + k) = 0.0;
1216 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1218 out + pos + j, outsize + pos + j, svg_p->dt,
1219 spmin + pos + j, spmax + pos + j);
1224 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1226 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1227 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1228 out + pos, outsize + pos, svg_p->dt,
1229 spmin + pos, spmax + pos);
1233 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1235 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1237 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1238 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1239 out + pos, outsize + pos, svg_p->dt,
1240 spmin + pos, spmax + pos);
1243 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1245 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1246 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1247 out + pos + 1, outsize + pos + 1, svg_p->dt,
1248 spmin + pos + 1, spmax + pos + 1);
1252 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1254 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1256 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1257 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1258 out + pos + 1, outsize + pos + 1, svg_p->dt,
1259 spmin + pos + 1, spmax + pos + 1);
1262 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1264 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1266 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1267 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1269 out + pos + 2, outsize + pos + 2, svg_p->dt,
1270 spmin + pos + 2, spmax + pos + 2);
1274 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1275 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1276 out + pos + 2, outsize + pos + 2, svg_p->dt,
1277 spmin + pos + 2, spmax + pos + 2);
1281 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1282 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1283 out + pos + 3, outsize + pos + 3, svg_p->dt,
1284 spmin + pos + 3, spmax + pos + 3);
1286 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1287 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1288 out + pos + 4, outsize + pos + 4, svg_p->dt,
1289 spmin + pos + 4, spmax + pos + 4);
1291 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1293 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1294 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1295 out + pos + 5, outsize + pos + 5, svg_p->dt,
1296 spmin + pos + 5, spmax + pos + 5);
1298 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1299 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1300 out + pos + 6, outsize + pos + 6, svg_p->dt,
1301 spmin + pos + 6, spmax + pos + 6);
1303 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1304 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1305 out + pos + 7, outsize + pos + 7, svg_p->dt,
1306 spmin + pos + 7, spmax + pos + 7);
1308 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1309 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1310 out + pos + 8, outsize + pos + 8, svg_p->dt,
1311 spmin + pos + 8, spmax + pos + 8);
1320 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1322 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1323 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1324 out + pos + j, outsize + pos + j, svg_p->dt,
1325 spmin + pos + j, spmax + pos + j);
1329 if (action & F_END) {
1330 int xid = 0, displayed;
1332 if (DISPLAY_IDLE(flags)) {
1333 /* Include additional %idle field */
1338 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
1340 /* Should current CPU (including CPU "all") be displayed? */
1341 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1345 pos = i * CPU_ARRAY_SZ;
1347 /* This is CPU "all" */
1348 strcpy(item_name, "all");
1351 sprintf(item_name, "%d", i - 1);
1354 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1355 displayed = draw_activity_graphs(a->g_nr, g_type,
1356 title, g_title1, item_name, group1,
1357 spmin + pos, spmax + pos, out + pos, outsize + pos,
1358 svg_p, record_hdr, i, a, xid);
1361 displayed = draw_activity_graphs(a->g_nr, g_type,
1362 title, g_title2, item_name, group2,
1363 spmin + pos, spmax + pos, out + pos, outsize + pos,
1364 svg_p, record_hdr, i, a, xid);
1371 /* Free remaining structures */
1372 free_graphs(out, outsize, spmin, spmax);
1377 ***************************************************************************
1378 * Display task creation and context switch statistics in SVG.
1381 * @a Activity structure with statistics.
1382 * @curr Index in array for current sample statistics.
1383 * @action Action expected from current function.
1384 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1385 * flag indicating that a restart record has been previously
1386 * found (.@restart) and time used for the X axis origin
1388 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1389 * @record_hdr Pointer on record header of current stats sample.
1390 ***************************************************************************
1392 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1393 unsigned long long itv, struct record_header *record_hdr)
1396 *spc = (struct stats_pcsw *) a->buf[curr],
1397 *spp = (struct stats_pcsw *) a->buf[!curr];
1398 int group[] = {1, 1};
1399 int g_fields[] = {1, 0};
1400 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1401 char *title[] = {"Task creation", "Switching activity"};
1402 char *g_title[] = {"proc/s",
1404 static double *spmin, *spmax;
1406 static int *outsize;
1408 if (action & F_BEGIN) {
1410 * Allocate arrays that will contain the graphs data
1411 * and the min/max values.
1413 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1416 if (action & F_MAIN) {
1417 /* Check for min/max values */
1418 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1419 itv, spmin, spmax, g_fields);
1421 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1422 S_VALUE(spp->processes, spc->processes, itv),
1423 out, outsize, svg_p->restart);
1425 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1426 S_VALUE(spp->context_switch, spc->context_switch, itv),
1427 out + 1, outsize + 1, svg_p->restart);
1430 if (action & F_END) {
1431 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1432 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1434 /* Free remaining structures */
1435 free_graphs(out, outsize, spmin, spmax);
1440 ***************************************************************************
1441 * Display swap statistics in SVG.
1444 * @a Activity structure with statistics.
1445 * @curr Index in array for current sample statistics.
1446 * @action Action expected from current function.
1447 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1448 * flag indicating that a restart record has been previously
1449 * found (.@restart) and time used for the X axis origin
1451 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1452 * @record_hdr Pointer on record header of current stats sample.
1453 ***************************************************************************
1455 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1456 unsigned long long itv, struct record_header *record_hdr)
1459 *ssc = (struct stats_swap *) a->buf[curr],
1460 *ssp = (struct stats_swap *) a->buf[!curr];
1462 int g_type[] = {SVG_LINE_GRAPH};
1463 char *title[] = {"Swap activity"};
1464 char *g_title[] = {"pswpin/s", "pswpout/s" };
1465 int g_fields[] = {0, 1};
1466 static double *spmin, *spmax;
1468 static int *outsize;
1470 if (action & F_BEGIN) {
1472 * Allocate arrays that will contain the graphs data
1473 * and the min/max values.
1475 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1478 if (action & F_MAIN) {
1479 /* Check for min/max values */
1480 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1481 itv, spmin, spmax, g_fields);
1483 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1484 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1485 out, outsize, svg_p->restart);
1487 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1488 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1489 out + 1, outsize + 1, svg_p->restart);
1492 if (action & F_END) {
1493 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1494 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1496 /* Free remaining structures */
1497 free_graphs(out, outsize, spmin, spmax);
1502 ***************************************************************************
1503 * Display paging statistics in SVG.
1506 * @a Activity structure with statistics.
1507 * @curr Index in array for current sample statistics.
1508 * @action Action expected from current function.
1509 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1510 * flag indicating that a restart record has been previously
1511 * found (.@restart) and time used for the X axis origin
1513 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1514 * @record_hdr Pointer on record header of current stats sample.
1515 ***************************************************************************
1517 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1518 unsigned long long itv, struct record_header *record_hdr)
1521 *spc = (struct stats_paging *) a->buf[curr],
1522 *spp = (struct stats_paging *) a->buf[!curr];
1523 int group[] = {2, 2, 4};
1524 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1525 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1526 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1527 "fault/s", "majflt/s",
1528 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1529 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1530 static double *spmin, *spmax;
1532 static int *outsize;
1534 if (action & F_BEGIN) {
1536 * Allocate arrays that will contain the graphs data
1537 * and the min/max values.
1539 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1542 if (action & F_MAIN) {
1543 /* Check for min/max values */
1544 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1545 itv, spmin, spmax, g_fields);
1547 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1548 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1549 out, outsize, svg_p->restart);
1551 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1552 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1553 out + 1, outsize + 1, svg_p->restart);
1555 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1556 S_VALUE(spp->pgfault, spc->pgfault, itv),
1557 out + 2, outsize + 2, svg_p->restart);
1559 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1560 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1561 out + 3, outsize + 3, svg_p->restart);
1563 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1564 S_VALUE(spp->pgfree, spc->pgfree, itv),
1565 out + 4, outsize + 4, svg_p->restart);
1567 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1568 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1569 out + 5, outsize + 5, svg_p->restart);
1571 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1572 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1573 out + 6, outsize + 6, svg_p->restart);
1575 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1576 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1577 out + 7, outsize + 7, svg_p->restart);
1580 if (action & F_END) {
1581 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1582 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1584 /* Free remaining structures */
1585 free_graphs(out, outsize, spmin, spmax);
1590 ***************************************************************************
1591 * Display I/O and transfer rate statistics in SVG.
1594 * @a Activity structure with statistics.
1595 * @curr Index in array for current sample statistics.
1596 * @action Action expected from current function.
1597 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1598 * flag indicating that a restart record has been previously
1599 * found (.@restart) and time used for the X axis origin
1601 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1602 * @record_hdr Pointer on record header of current stats sample.
1603 ***************************************************************************
1605 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1606 unsigned long long itv, struct record_header *record_hdr)
1609 *sic = (struct stats_io *) a->buf[curr],
1610 *sip = (struct stats_io *) a->buf[!curr];
1611 int group[] = {4, 3};
1612 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1613 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1614 char *g_title[] = {"tps", "rtps", "wtps", "dtps",
1615 "bread/s", "bwrtn/s", "bdscd/s"};
1617 * tps:0, rtps:1, wtps:2, dtps:3, bread/s:4, bwrtn/s:5, bdscd/s:6
1627 int g_fields[] = {0, 1, 2, 4, 5, 3, 6};
1628 static double *spmin, *spmax;
1630 static int *outsize;
1632 if (action & F_BEGIN) {
1634 * Allocate arrays that will contain the graphs data
1635 * and the min/max values.
1637 out = allocate_graph_lines(7, &outsize, &spmin, &spmax);
1640 if (action & F_MAIN) {
1641 /* Check for min/max values */
1642 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1643 itv, spmin, spmax, g_fields);
1646 * If we get negative values, this is probably because
1647 * one or more devices/filesystems have been unmounted.
1648 * We display 0.0 in this case though we should rather tell
1649 * the user that the value cannot be calculated here.
1652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1653 sic->dk_drive < sip->dk_drive ? 0.0 :
1654 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1655 out, outsize, svg_p->restart);
1657 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1658 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1659 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1660 out + 1, outsize + 1, svg_p->restart);
1662 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1663 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1664 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1665 out + 2, outsize + 2, svg_p->restart);
1667 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1668 sic->dk_drive_dio < sip->dk_drive_dio ? 0.0 :
1669 S_VALUE(sip->dk_drive_dio, sic->dk_drive_dio, itv),
1670 out + 3, outsize + 3, svg_p->restart);
1672 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1673 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1674 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1675 out + 4, outsize + 4, svg_p->restart);
1677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1678 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1679 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1680 out + 5, outsize + 5, svg_p->restart);
1682 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1683 sic->dk_drive_dblk < sip->dk_drive_dblk ? 0.0 :
1684 S_VALUE(sip->dk_drive_dblk, sic->dk_drive_dblk, itv),
1685 out + 6, outsize + 6, svg_p->restart);
1688 if (action & F_END) {
1689 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1690 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1692 /* Free remaining structures */
1693 free_graphs(out, outsize, spmin, spmax);
1698 ***************************************************************************
1699 * Display memory statistics in SVG.
1702 * @a Activity structure with statistics.
1703 * @curr Index in array for current sample statistics.
1704 * @action Action expected from current function.
1705 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1706 * flag indicating that a restart record has been previously
1707 * found (.@restart) and time used for the X axis origin
1709 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1710 * @record_hdr Pointer on record header of current stats sample.
1711 ***************************************************************************
1713 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1714 unsigned long long itv, struct record_header *record_hdr)
1717 *smc = (struct stats_memory *) a->buf[curr];
1718 int group1[] = {3, 1, 3, 1, 3, 5};
1719 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1720 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1721 int group2[] = {3, 1, 1};
1722 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1723 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1724 "Memory utilization (3)", "Memory utilization (4)",
1725 "Memory utilization (5)", "Memory utilization (6)"};
1726 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1727 "Swap utilization (3)"};
1728 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1729 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1730 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1732 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1734 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1735 static double *spmin, *spmax;
1737 static int *outsize;
1741 unsigned long long nousedmem;
1743 if (action & F_BEGIN) {
1745 * Allocate arrays that will contain the graphs data
1746 * and the min/max values.
1748 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1751 if (action & F_MAIN) {
1752 /* Check for min/max values */
1753 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1754 itv, spmin, spmax, g_fields);
1755 /* Compute %memused min/max values */
1756 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1757 if (nousedmem > smc->tlmkb) {
1758 nousedmem = smc->tlmkb;
1760 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1761 if (tval > *(spmax + 3)) {
1762 *(spmax + 3) = tval;
1764 if (tval < *(spmin + 3)) {
1765 *(spmin + 3) = tval;
1767 /* Compute %commit min/max values */
1768 tval = (smc->tlmkb + smc->tlskb) ?
1769 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1770 if (tval > *(spmax + 7)) {
1771 *(spmax + 7) = tval;
1773 if (tval < *(spmin + 7)) {
1774 *(spmin + 7) = tval;
1776 /* Compute %swpused min/max values */
1778 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1779 if (tval > *(spmax + 19)) {
1780 *(spmax + 19) = tval;
1782 if (tval < *(spmin + 19)) {
1783 *(spmin + 19) = tval;
1785 /* Compute %swpcad min/max values */
1786 tval = (smc->tlskb - smc->frskb) ?
1787 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1788 if (tval > *(spmax + 20)) {
1789 *(spmax + 20) = tval;
1791 if (tval < *(spmin + 20)) {
1792 *(spmin + 20) = tval;
1794 /* Compute memused min/max values in MB */
1795 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1796 if (tval > *(spmax + 2)) {
1797 *(spmax + 2) = tval;
1799 if (tval < *(spmin + 2)) {
1800 *(spmin + 2) = tval;
1802 /* Compute swpused min/max values in MB */
1803 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1804 if (tval > *(spmax + 17)) {
1805 *(spmax + 17) = tval;
1807 if (tval < *(spmin + 17)) {
1808 *(spmin + 17) = tval;
1812 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1813 ((double) smc->frmkb) / 1024,
1814 out, outsize, svg_p->restart);
1816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1817 ((double) (smc->tlmkb - nousedmem)) / 1024,
1818 out + 2, outsize + 2, svg_p->restart);
1820 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1821 ((double) smc->availablekb) / 1024,
1822 out + 1, outsize + 1, svg_p->restart);
1824 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1825 ((double) smc->bufkb) / 1024,
1826 out + 4, outsize + 4, svg_p->restart);
1828 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1829 ((double) smc->camkb) / 1024,
1830 out + 5, outsize + 5, svg_p->restart);
1832 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1833 ((double) smc->frskb) / 1024,
1834 out + 16, outsize + 16, svg_p->restart);
1836 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1837 ((double) (smc->tlskb - smc->frskb)) / 1024,
1838 out + 17, outsize + 17, svg_p->restart);
1840 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1841 ((double) smc->caskb) / 1024,
1842 out + 18, outsize + 18, svg_p->restart);
1844 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1845 ((double) smc->comkb) / 1024,
1846 out + 6, outsize + 6, svg_p->restart);
1848 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1849 ((double) smc->activekb) / 1024,
1850 out + 8, outsize + 8, svg_p->restart);
1852 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1853 ((double) smc->inactkb) / 1024,
1854 out + 9, outsize + 9, svg_p->restart);
1856 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1857 ((double) smc->dirtykb) / 1024,
1858 out + 10, outsize + 10, svg_p->restart);
1860 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1861 ((double) smc->anonpgkb) / 1024,
1862 out + 11, outsize + 11, svg_p->restart);
1864 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1865 ((double) smc->slabkb) / 1024,
1866 out + 12, outsize + 12, svg_p->restart);
1868 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1869 ((double) smc->kstackkb) / 1024,
1870 out + 13, outsize + 13, svg_p->restart);
1872 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1873 ((double) smc->pgtblkb) / 1024,
1874 out + 14, outsize + 14, svg_p->restart);
1876 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1877 ((double) smc->vmusedkb) / 1024,
1878 out + 15, outsize + 15, svg_p->restart);
1880 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1883 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1884 out + 3, outsize + 3, svg_p->dt);
1886 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1888 (smc->tlmkb + smc->tlskb) ?
1889 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1890 out + 7, outsize + 7, svg_p->dt);
1892 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1895 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1896 out + 19, outsize + 19, svg_p->dt);
1898 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1900 (smc->tlskb - smc->frskb) ?
1901 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1902 out + 20, outsize + 20, svg_p->dt);
1905 if (action & F_END) {
1907 /* Conversion kB -> MB */
1908 for (i = 0; i < 17; i++) {
1909 *(spmin + g_fields[i]) /= 1024;
1910 *(spmax + g_fields[i]) /= 1024;
1913 if (DISPLAY_MEMORY(a->opt_flags)) {
1914 if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1915 g_type1, title1, g_title1, NULL, group1,
1916 spmin, spmax, out, outsize, svg_p, record_hdr,
1922 if (DISPLAY_SWAP(a->opt_flags)) {
1923 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1924 spmin + 16, spmax + 16, out + 16, outsize + 16,
1925 svg_p, record_hdr, FALSE, a, xid);
1928 /* Free remaining structures */
1929 free_graphs(out, outsize, spmin, spmax);
1934 ***************************************************************************
1935 * Display kernel tables statistics in SVG.
1938 * @a Activity structure with statistics.
1939 * @curr Index in array for current sample statistics.
1940 * @action Action expected from current function.
1941 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1942 * flag indicating that a restart record has been previously
1943 * found (.@restart) and time used for the X axis origin
1945 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1946 * @record_hdr Pointer on record header of current stats sample.
1947 ***************************************************************************
1949 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1950 unsigned long long itv, struct record_header *record_hdr)
1952 struct stats_ktables
1953 *skc = (struct stats_ktables *) a->buf[curr];
1954 int group[] = {3, 1};
1955 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1956 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1957 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1959 int g_fields[] = {1, 2, 0, 3};
1960 static double *spmin, *spmax;
1962 static int *outsize;
1964 if (action & F_BEGIN) {
1966 * Allocate arrays that will contain the graphs data
1967 * and the min/max values.
1969 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1972 if (action & F_MAIN) {
1973 /* Check for min/max values */
1974 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1975 itv, spmin, spmax, g_fields);
1977 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1978 (unsigned long long) skc->dentry_stat,
1979 out, outsize, svg_p->restart);
1981 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1982 (unsigned long long) skc->file_used,
1983 out + 1, outsize + 1, svg_p->restart);
1985 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1986 (unsigned long long) skc->inode_used,
1987 out + 2, outsize + 2, svg_p->restart);
1989 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1990 (unsigned long long) skc->pty_nr,
1991 out + 3, outsize + 3, svg_p->restart);
1994 if (action & F_END) {
1995 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1996 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1998 /* Free remaining structures */
1999 free_graphs(out, outsize, spmin, spmax);
2004 ***************************************************************************
2005 * Display queue and load statistics in SVG.
2008 * @a Activity structure with statistics.
2009 * @curr Index in array for current sample statistics.
2010 * @action Action expected from current function.
2011 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2012 * flag indicating that a restart record has been previously
2013 * found (.@restart) and time used for the X axis origin
2015 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2016 * @record_hdr Pointer on record header of current stats sample.
2017 ***************************************************************************
2019 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2020 unsigned long long itv, struct record_header *record_hdr)
2023 *sqc = (struct stats_queue *) a->buf[curr];
2024 int group[] = {2, 1, 3};
2025 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2026 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
2027 char *g_title[] = {"~runq-sz", "~blocked",
2029 "ldavg-1", "ldavg-5", "ldavg-15"};
2030 int g_fields[] = {0, 1, 2, 3, 4, 5};
2031 static double *spmin, *spmax;
2033 static int *outsize;
2035 if (action & F_BEGIN) {
2037 * Allocate arrays that will contain the graphs data
2038 * and the min/max values.
2040 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2043 if (action & F_MAIN) {
2044 /* Check for min/max values */
2045 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2046 itv, spmin, spmax, g_fields);
2048 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2049 (unsigned long long) sqc->nr_running,
2050 out, outsize, svg_p->restart);
2052 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2053 (unsigned long long) sqc->procs_blocked,
2054 out + 1, outsize + 1, svg_p->restart);
2056 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2057 (unsigned long long) sqc->nr_threads,
2058 out + 2, outsize + 2, svg_p->restart);
2060 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2061 (double) sqc->load_avg_1 / 100,
2062 out + 3, outsize + 3, svg_p->restart);
2064 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2065 (double) sqc->load_avg_5 / 100,
2066 out + 4, outsize + 4, svg_p->restart);
2068 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2069 (double) sqc->load_avg_15 / 100,
2070 out + 5, outsize + 5, svg_p->restart);
2073 if (action & F_END) {
2074 /* Fix min/max values for load average */
2075 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2076 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2077 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2079 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2080 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2082 /* Free remaining structures */
2083 free_graphs(out, outsize, spmin, spmax);
2088 ***************************************************************************
2089 * Display disk statistics in SVG.
2092 * @a Activity structure with statistics.
2093 * @curr Index in array for current sample statistics.
2094 * @action Action expected from current function.
2095 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2096 * flag indicating that a restart record has been previously
2097 * found (.@restart) and time used for the X axis origin
2099 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2100 * @record_hdr Pointer on record header of current stats sample.
2101 ***************************************************************************
2103 #define DISK_ARRAY_SZ 9
2104 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2105 unsigned long long itv, struct record_header *record_hdr)
2107 struct stats_disk *sdc, *sdp, sdpzero;
2108 struct ext_disk_stats xds;
2109 int group[] = {1, 3, 2, 1, 1};
2110 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2111 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2112 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2113 "Block devices statistics (3)", "Block devices statistics (4)",
2114 "Block devices statistics (5)"};
2115 char *g_title[] = {"tps",
2116 "rkB/s", "wkB/s", "dkB/s",
2117 "areq-sz", "aqu-sz",
2120 int g_fields[] = {0, 1, 2};
2121 unsigned int local_types_nr[] = {1, 0, 0};
2122 static double *spmin, *spmax;
2124 static int *outsize;
2125 char *dev_name, *item_name;
2126 double rkB, wkB, dkB, aqusz;
2127 int i, j, k, pos, restart, *unregistered;
2129 if (action & F_BEGIN) {
2131 * Allocate arrays (#0..7) that will contain the graphs data
2132 * and the min/max values.
2133 * Also allocate one additional array (#8) for each disk device:
2134 * out + 8 will contain the device name (WWN id, pretty name or devm-n),
2135 * outsize + 8 will contain a positive value (TRUE) if the device
2136 * has either still not been registered, or has been unregistered.
2138 out = allocate_graph_lines(DISK_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2141 if (action & F_MAIN) {
2142 memset(&sdpzero, 0, STATS_DISK_SIZE);
2144 * Mark previously registered devices as now
2145 * possibly unregistered for all graphs.
2147 for (k = 0; k < a->item_list_sz; k++) {
2148 unregistered = outsize + k * DISK_ARRAY_SZ + 8;
2149 if (*unregistered == FALSE) {
2150 *unregistered = MAYBE;
2154 /* For each device structure */
2155 for (i = 0; i < a->nr[curr]; i++) {
2156 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2157 restart = svg_p->restart;
2159 /* Get device name */
2160 dev_name = get_device_name(sdc->major, sdc->minor, sdc->wwn, sdc->part_nr,
2161 DISPLAY_PRETTY(flags), DISPLAY_PERSIST_NAME_S(flags),
2162 USE_STABLE_ID(flags), NULL);
2164 if (a->item_list != NULL) {
2165 /* A list of devices has been entered on the command line */
2166 if (!search_list_item(a->item_list, dev_name))
2167 /* Device not found */
2171 /* Look for corresponding graph */
2172 for (k = 0; k < a->item_list_sz; k++) {
2173 item_name = *(out + k * DISK_ARRAY_SZ + 8);
2174 if (!strcmp(dev_name, item_name))
2178 if (k == a->item_list_sz) {
2179 /* Graph not found: Look for first free entry */
2180 for (k = 0; k < a->item_list_sz; k++) {
2181 item_name = *(out + k * DISK_ARRAY_SZ + 8);
2182 if (!strcmp(item_name, ""))
2185 if (k == a->item_list_sz) {
2186 /* No free graph entry: Ignore it (should never happen) */
2188 fprintf(stderr, "%s: Name=%s major=%d minor=%d\n",
2189 __FUNCTION__, dev_name, sdc->major, sdc->minor);
2194 pos = k * DISK_ARRAY_SZ;
2195 unregistered = outsize + pos + 8;
2198 * If current device was marked as previously unregistered,
2199 * then set restart variable to TRUE so that the graph will be
2200 * discontinuous, and mark it as now registered.
2202 if (*unregistered == TRUE) {
2205 *unregistered = FALSE;
2207 item_name = *(out + pos + 8);
2208 if (!item_name[0]) {
2209 /* Save device name (WWN id or pretty name) if not already done */
2210 strncpy(item_name, dev_name, CHUNKSIZE);
2211 item_name[CHUNKSIZE - 1] = '\0';
2214 j = check_disk_reg(a, curr, !curr, i);
2216 /* This is a newly registered interface. Previous stats are zero */
2221 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2224 /* Check for min/max values */
2225 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2226 itv, spmin + pos, spmax + pos, g_fields);
2228 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2229 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2230 dkB = S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2;
2231 if (rkB < *(spmin + pos + 1)) {
2232 *(spmin + pos + 1) = rkB;
2234 if (rkB > *(spmax + pos + 1)) {
2235 *(spmax + pos + 1) = rkB;
2237 if (wkB < *(spmin + pos + 2)) {
2238 *(spmin + pos + 2) = wkB;
2240 if (wkB > *(spmax + pos + 2)) {
2241 *(spmax + pos + 2) = wkB;
2243 if (dkB < *(spmin + pos + 3)) {
2244 *(spmin + pos + 3) = dkB;
2246 if (dkB > *(spmax + pos + 3)) {
2247 *(spmax + pos + 3) = dkB;
2250 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2251 if ((xds.arqsz / 2) < *(spmin + pos + 4)) {
2252 *(spmin + pos + 4) = xds.arqsz / 2;
2254 if ((xds.arqsz / 2) > *(spmax + pos + 4)) {
2255 *(spmax + pos + 4) = xds.arqsz / 2;
2257 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2258 if (aqusz < *(spmin + pos + 5)) {
2259 *(spmin + pos + 5) = aqusz;
2261 if (aqusz > *(spmax + pos + 5)) {
2262 *(spmax + pos + 5) = aqusz;
2264 if (xds.await < *(spmin + pos + 6)) {
2265 *(spmin + pos + 6) = xds.await;
2267 if (xds.await > *(spmax + pos + 6)) {
2268 *(spmax + pos + 6) = xds.await;
2270 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2271 *(spmin + pos + 7) = xds.util / 10.0;
2273 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2274 *(spmax + pos + 7) = xds.util / 10.0;
2278 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2279 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2280 out + pos, outsize + pos, restart);
2282 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2283 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2284 out + pos + 1, outsize + pos + 1, restart);
2286 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2287 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2288 out + pos + 2, outsize + pos + 2, restart);
2290 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2291 S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2,
2292 out + pos + 3, outsize + pos + 3, restart);
2294 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2296 out + pos + 4, outsize + pos + 4, restart);
2298 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2300 out + pos + 5, outsize + pos + 5, restart);
2302 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2304 out + pos + 6, outsize + pos + 6, restart);
2306 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2307 0.0, xds.util / 10.0,
2308 out + pos + 7, outsize + pos + 7, svg_p->dt);
2311 /* Mark devices not seen here as now unregistered */
2312 for (k = 0; k < a->item_list_sz; k++) {
2313 unregistered = outsize + k * DISK_ARRAY_SZ + 8;
2314 if (*unregistered != FALSE) {
2315 *unregistered = TRUE;
2320 if (action & F_END) {
2323 for (i = 0; i < a->item_list_sz; i++) {
2324 /* Check if there is something to display */
2325 pos = i * DISK_ARRAY_SZ;
2329 item_name = *(out + pos + 8);
2330 if (draw_activity_graphs(a->g_nr, g_type,
2331 title, g_title, item_name, group,
2332 spmin + pos, spmax + pos, out + pos, outsize + pos,
2333 svg_p, record_hdr, FALSE, a, xid)) {
2338 /* Free remaining structures */
2339 free_graphs(out, outsize, spmin, spmax);
2344 ***************************************************************************
2345 * Display network interfaces statistics in SVG.
2348 * @a Activity structure with statistics.
2349 * @curr Index in array for current sample statistics.
2350 * @action Action expected from current function.
2351 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2352 * flag indicating that a restart record has been previously
2353 * found (.@restart) and time used for the X axis origin
2355 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2356 * @record_hdr Pointer on record header of current stats sample.
2357 ***************************************************************************
2359 #define NET_DEV_ARRAY_SZ 9
2360 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2361 unsigned long long itv, struct record_header *record_hdr)
2363 struct stats_net_dev *sndc, *sndp, sndzero;
2364 int group[] = {2, 2, 3, 1};
2365 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2367 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2368 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2369 char *g_title[] = {"rxpck/s", "txpck/s",
2371 "rxcmp/s", "txcmp/s", "rxmcst/s",
2373 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2374 unsigned int local_types_nr[] = {7, 0, 0};
2375 static double *spmin, *spmax;
2377 static int *outsize;
2379 double rxkb, txkb, ifutil;
2380 int i, j, k, pos, restart, *unregistered;
2382 if (action & F_BEGIN) {
2384 * Allocate arrays (#0..7) that will contain the graphs data
2385 * and the min/max values.
2386 * Also allocate one additional array (#8) for each interface:
2387 * out + 8 will contain the interface name,
2388 * outsize + 8 will contain a positive value (TRUE) if the interface
2389 * has either still not been registered, or has been unregistered.
2391 out = allocate_graph_lines(NET_DEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2394 if (action & F_MAIN) {
2395 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2397 * Mark previously registered interfaces as now
2398 * possibly unregistered for all graphs.
2400 for (k = 0; k < a->item_list_sz; k++) {
2401 unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
2402 if (*unregistered == FALSE) {
2403 *unregistered = MAYBE;
2407 /* For each network interfaces structure */
2408 for (i = 0; i < a->nr[curr]; i++) {
2409 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2410 restart = svg_p->restart;
2412 if (a->item_list != NULL) {
2413 /* A list of devices has been entered on the command line */
2414 if (!search_list_item(a->item_list, sndc->interface))
2415 /* Device not found */
2419 /* Look for corresponding graph */
2420 for (k = 0; k < a->item_list_sz; k++) {
2421 item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
2422 if (!strcmp(sndc->interface, item_name))
2426 if (k == a->item_list_sz) {
2427 /* Graph not found: Look for first free entry */
2428 for (k = 0; k < a->item_list_sz; k++) {
2429 item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
2430 if (!strcmp(item_name, ""))
2433 if (k == a->item_list_sz) {
2434 /* No free graph entry: Ignore it (should never happen) */
2436 fprintf(stderr, "%s: Name=%s\n",
2437 __FUNCTION__, sndc->interface);
2442 pos = k * NET_DEV_ARRAY_SZ;
2443 unregistered = outsize + pos + 8;
2445 j = check_net_dev_reg(a, curr, !curr, i);
2447 /* This is a newly registered interface. Previous stats are zero */
2452 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2456 * If current interface was marked as previously unregistered,
2457 * then set restart variable to TRUE so that the graph will be
2458 * discontinuous, and mark it as now registered.
2460 if (*unregistered == TRUE) {
2463 *unregistered = FALSE;
2465 item_name = *(out + pos + 8);
2466 if (!item_name[0]) {
2467 /* Save network interface name (if not already done) */
2468 strncpy(item_name, sndc->interface, CHUNKSIZE);
2469 item_name[CHUNKSIZE - 1] = '\0';
2472 /* Check for min/max values */
2473 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2474 itv, spmin + pos, spmax + pos, g_fields);
2476 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2477 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2478 ifutil = compute_ifutil(sndc, rxkb, txkb);
2479 if (ifutil < *(spmin + pos + 7)) {
2480 *(spmin + pos + 7) = ifutil;
2482 if (ifutil > *(spmax + pos + 7)) {
2483 *(spmax + pos + 7) = ifutil;
2487 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2488 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2489 out + pos, outsize + pos, restart);
2491 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2492 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2493 out + pos + 1, outsize + pos + 1, restart);
2495 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2497 out + pos + 2, outsize + pos + 2, restart);
2499 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2501 out + pos + 3, outsize + pos + 3, restart);
2503 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2504 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2505 out + pos + 4, outsize + pos + 4, restart);
2507 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2508 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2509 out + pos + 5, outsize + pos + 5, restart);
2511 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2512 S_VALUE(sndp->multicast, sndc->multicast, itv),
2513 out + pos + 6, outsize + pos + 6, restart);
2515 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2517 out + pos + 7, outsize + pos + 7, svg_p->dt);
2520 /* Mark interfaces not seen here as now unregistered */
2521 for (k = 0; k < a->item_list_sz; k++) {
2522 unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
2523 if (*unregistered != FALSE) {
2524 *unregistered = TRUE;
2529 if (action & F_END) {
2532 for (i = 0; i < a->item_list_sz; i++) {
2534 * Check if there is something to display.
2535 * Don't test sndc->interface because maybe the network
2536 * interface has been registered later.
2538 pos = i * NET_DEV_ARRAY_SZ;
2542 /* Recalculate min and max values in kB, not in B */
2543 *(spmin + pos + 2) /= 1024;
2544 *(spmax + pos + 2) /= 1024;
2545 *(spmin + pos + 3) /= 1024;
2546 *(spmax + pos + 3) /= 1024;
2548 item_name = *(out + pos + 8);
2549 if (draw_activity_graphs(a->g_nr, g_type,
2550 title, g_title, item_name, group,
2551 spmin + pos, spmax + pos, out + pos, outsize + pos,
2552 svg_p, record_hdr, FALSE, a, xid)) {
2557 /* Free remaining structures */
2558 free_graphs(out, outsize, spmin, spmax);
2563 ***************************************************************************
2564 * Display network interfaces errors statistics in SVG.
2567 * @a Activity structure with statistics.
2568 * @curr Index in array for current sample statistics.
2569 * @action Action expected from current function.
2570 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2571 * flag indicating that a restart record has been previously
2572 * found (.@restart) and time used for the X axis origin
2574 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2575 * @record_hdr Pointer on record header of current stats sample.
2576 ***************************************************************************
2578 #define NET_EDEV_ARRAY_SZ 10
2579 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2580 unsigned long long itv, struct record_header *record_hdr)
2582 struct stats_net_edev *snedc, *snedp, snedzero;
2583 int group[] = {2, 2, 2, 3};
2584 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2586 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2587 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2588 char *g_title[] = {"rxerr/s", "txerr/s",
2589 "rxdrop/s", "txdrop/s",
2590 "rxfifo/s", "txfifo/s",
2591 "coll/s", "txcarr/s", "rxfram/s"};
2592 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2593 static double *spmin, *spmax;
2595 static int *outsize;
2597 int i, j, k, pos, restart, *unregistered;
2599 if (action & F_BEGIN) {
2601 * Allocate arrays (#0..8) that will contain the graphs data
2602 * and the min/max values.
2603 * Also allocate one additional array (#9) for each interface:
2604 * out + 9 will contain the interface name,
2605 * outsize + 9 will contain a positive value (TRUE) if the interface
2606 * has either still not been registered, or has been unregistered.
2608 out = allocate_graph_lines(NET_EDEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2611 if (action & F_MAIN) {
2612 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2614 * Mark previously registered interfaces as now
2615 * possibly unregistered for all graphs.
2617 for (k = 0; k < a->item_list_sz; k++) {
2618 unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
2619 if (*unregistered == FALSE) {
2620 *unregistered = MAYBE;
2624 /* For each network interfaces structure */
2625 for (i = 0; i < a->nr[curr]; i++) {
2626 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2627 restart = svg_p->restart;
2629 if (a->item_list != NULL) {
2630 /* A list of devices has been entered on the command line */
2631 if (!search_list_item(a->item_list, snedc->interface))
2632 /* Device not found */
2636 /* Look for corresponding graph */
2637 for (k = 0; k < a->item_list_sz; k++) {
2638 item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
2639 if (!strcmp(snedc->interface, item_name))
2643 if (k == a->item_list_sz) {
2644 /* Graph not found: Look for first free entry */
2645 for (k = 0; k < a->item_list_sz; k++) {
2646 item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
2647 if (!strcmp(item_name, ""))
2650 if (k == a->item_list_sz) {
2651 /* No free graph entry: Ignore it (should never happen) */
2653 fprintf(stderr, "%s: Name=%s\n",
2654 __FUNCTION__, snedc->interface);
2660 pos = k * NET_EDEV_ARRAY_SZ;
2661 unregistered = outsize + pos + 9;
2663 j = check_net_edev_reg(a, curr, !curr, i);
2665 /* This is a newly registered interface. Previous stats are zero */
2670 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2674 * If current interface was marked as previously unregistered,
2675 * then set restart variable to TRUE so that the graph will be
2676 * discontinuous, and mark it as now registered.
2678 if (*unregistered == TRUE) {
2681 *unregistered = FALSE;
2683 item_name = *(out + pos + 9);
2684 if (!item_name[0]) {
2685 /* Save network interface name (if not already done) */
2686 strncpy(item_name, snedc->interface, CHUNKSIZE);
2687 item_name[CHUNKSIZE - 1] = '\0';
2690 /* Check for min/max values */
2691 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2692 itv, spmin + pos, spmax + pos, g_fields);
2695 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2696 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2697 out + pos, outsize + pos, restart);
2699 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2700 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2701 out + pos + 1, outsize + pos + 1, restart);
2703 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2704 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2705 out + pos + 2, outsize + pos + 2, restart);
2707 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2708 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2709 out + pos + 3, outsize + pos + 3, restart);
2711 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2712 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2713 out + pos + 4, outsize + pos + 4, restart);
2715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2716 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2717 out + pos + 5, outsize + pos + 5, restart);
2719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2720 S_VALUE(snedp->collisions, snedc->collisions, itv),
2721 out + pos + 6, outsize + pos + 6, restart);
2723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2724 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2725 out + pos + 7, outsize + pos + 7, restart);
2727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2728 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2729 out + pos + 8, outsize + pos + 8, restart);
2732 /* Mark interfaces not seen here as now unregistered */
2733 for (k = 0; k < a->item_list_sz; k++) {
2734 unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
2735 if (*unregistered != FALSE) {
2736 *unregistered = TRUE;
2741 if (action & F_END) {
2744 for (i = 0; i < a->item_list_sz; i++) {
2746 * Check if there is something to display.
2747 * Don't test snedc->interface because maybe the network
2748 * interface has been registered later.
2750 pos = i * NET_EDEV_ARRAY_SZ;
2754 item_name = *(out + pos + 9);
2755 if (draw_activity_graphs(a->g_nr, g_type,
2756 title, g_title, item_name, group,
2757 spmin + pos, spmax + pos, out + pos, outsize + pos,
2758 svg_p, record_hdr, FALSE, a, xid)) {
2763 /* Free remaining structures */
2764 free_graphs(out, outsize, spmin, spmax);
2769 ***************************************************************************
2770 * Display NFS client statistics in SVG.
2773 * @a Activity structure with statistics.
2774 * @curr Index in array for current sample statistics.
2775 * @action Action expected from current function.
2776 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2777 * flag indicating that a restart record has been previously
2778 * found (.@restart) and time used for the X axis origin
2780 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2781 * @record_hdr Pointer on record header of current stats sample.
2782 ***************************************************************************
2784 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2785 unsigned long long itv, struct record_header *record_hdr)
2787 struct stats_net_nfs
2788 *snnc = (struct stats_net_nfs *) a->buf[curr],
2789 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2790 int group[] = {2, 2, 2};
2791 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2792 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2793 "NFS client statistics (3)"};
2794 char *g_title[] = {"call/s", "retrans/s",
2795 "read/s", "write/s",
2796 "access/s", "getatt/s"};
2797 int g_fields[] = {0, 1, 2, 3, 4, 5};
2798 static double *spmin, *spmax;
2800 static int *outsize;
2802 if (action & F_BEGIN) {
2804 * Allocate arrays that will contain the graphs data
2805 * and the min/max values.
2807 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2810 if (action & F_MAIN) {
2811 /* Check for min/max values */
2812 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2813 itv, spmin, spmax, g_fields);
2816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2817 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2818 out, outsize, svg_p->restart);
2820 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2821 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2822 out + 1, outsize + 1, svg_p->restart);
2824 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2825 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2826 out + 2, outsize + 2, svg_p->restart);
2828 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2829 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2830 out + 3, outsize + 3, svg_p->restart);
2832 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2833 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2834 out + 4, outsize + 4, svg_p->restart);
2836 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2837 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2838 out + 5, outsize + 5, svg_p->restart);
2841 if (action & F_END) {
2842 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2843 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2845 /* Free remaining structures */
2846 free_graphs(out, outsize, spmin, spmax);
2851 ***************************************************************************
2852 * Display NFS server statistics in SVG.
2855 * @a Activity structure with statistics.
2856 * @curr Index in array for current sample statistics.
2857 * @action Action expected from current function.
2858 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2859 * flag indicating that a restart record has been previously
2860 * found (.@restart) and time used for the X axis origin
2862 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2863 * @record_hdr Pointer on record header of current stats sample.
2864 ***************************************************************************
2866 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2867 unsigned long long itv, struct record_header *record_hdr)
2869 struct stats_net_nfsd
2870 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2871 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2872 int group[] = {2, 3, 2, 2, 2};
2873 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2874 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2875 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2876 "NFS server statistics (3)", "NFS server statistics (4)",
2877 "NFS server statistics (5)"};
2878 char *g_title[] = {"scall/s", "badcall/s",
2879 "packet/s", "udp/s", "tcp/s",
2881 "sread/s", "swrite/s",
2882 "saccess/s", "sgetatt/s"};
2883 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2884 static double *spmin, *spmax;
2886 static int *outsize;
2888 if (action & F_BEGIN) {
2890 * Allocate arrays that will contain the graphs data
2891 * and the min/max values.
2893 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2896 if (action & F_MAIN) {
2897 /* Check for min/max values */
2898 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2899 itv, spmin, spmax, g_fields);
2902 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2903 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2904 out, outsize, svg_p->restart);
2906 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2907 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2908 out + 1, outsize + 1, svg_p->restart);
2910 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2911 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2912 out + 2, outsize + 2, svg_p->restart);
2914 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2915 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2916 out + 3, outsize + 3, svg_p->restart);
2918 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2919 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2920 out + 4, outsize + 4, svg_p->restart);
2922 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2923 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2924 out + 5, outsize + 5, svg_p->restart);
2926 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2927 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2928 out + 6, outsize + 6, svg_p->restart);
2930 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2931 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2932 out + 7, outsize + 7, svg_p->restart);
2934 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2935 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2936 out + 8, outsize + 8, svg_p->restart);
2938 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2939 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2940 out + 9, outsize + 9, svg_p->restart);
2942 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2943 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2944 out + 10, outsize + 10, svg_p->restart);
2947 if (action & F_END) {
2948 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2949 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2951 /* Free remaining structures */
2952 free_graphs(out, outsize, spmin, spmax);
2957 ***************************************************************************
2958 * Display socket statistics in SVG.
2961 * @a Activity structure with statistics.
2962 * @curr Index in array for current sample statistics.
2963 * @action Action expected from current function.
2964 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2965 * flag indicating that a restart record has been previously
2966 * found (.@restart) and time used for the X axis origin
2968 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2969 * @record_hdr Pointer on record header of current stats sample.
2970 ***************************************************************************
2972 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2973 unsigned long long itv, struct record_header *record_hdr)
2975 struct stats_net_sock
2976 *snsc = (struct stats_net_sock *) a->buf[curr];
2977 int group[] = {1, 5};
2978 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2979 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2980 char *g_title[] = {"~totsck",
2981 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2982 int g_fields[] = {0, 1, 5, 2, 3, 4};
2983 static double *spmin, *spmax;
2985 static int *outsize;
2987 if (action & F_BEGIN) {
2989 * Allocate arrays that will contain the graphs data
2990 * and the min/max values.
2992 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2995 if (action & F_MAIN) {
2996 /* Check for min/max values */
2997 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2998 itv, spmin, spmax, g_fields);
3000 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3001 (unsigned long long) snsc->sock_inuse,
3002 out, outsize, svg_p->restart);
3004 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3005 (unsigned long long) snsc->tcp_inuse,
3006 out + 1, outsize + 1, svg_p->restart);
3008 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3009 (unsigned long long) snsc->udp_inuse,
3010 out + 2, outsize + 2, svg_p->restart);
3012 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3013 (unsigned long long) snsc->raw_inuse,
3014 out + 3, outsize + 3, svg_p->restart);
3016 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3017 (unsigned long long) snsc->frag_inuse,
3018 out + 4, outsize + 4, svg_p->restart);
3020 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3021 (unsigned long long) snsc->tcp_tw,
3022 out + 5, outsize + 5, svg_p->restart);
3025 if (action & F_END) {
3026 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3027 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3029 /* Free remaining structures */
3030 free_graphs(out, outsize, spmin, spmax);
3035 ***************************************************************************
3036 * Display IPv4 traffic statistics in SVG.
3039 * @a Activity structure with statistics.
3040 * @curr Index in array for current sample statistics.
3041 * @action Action expected from current function.
3042 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3043 * flag indicating that a restart record has been previously
3044 * found (.@restart) and time used for the X axis origin
3046 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3047 * @record_hdr Pointer on record header of current stats sample.
3048 ***************************************************************************
3050 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3051 unsigned long long itv, struct record_header *record_hdr)
3054 *snic = (struct stats_net_ip *) a->buf[curr],
3055 *snip = (struct stats_net_ip *) a->buf[!curr];
3056 int group[] = {4, 2, 2};
3057 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3058 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
3059 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
3060 "asmrq/s", "asmok/s",
3061 "fragok/s", "fragcrt/s"};
3062 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3063 static double *spmin, *spmax;
3065 static int *outsize;
3067 if (action & F_BEGIN) {
3069 * Allocate arrays that will contain the graphs data
3070 * and the min/max values.
3072 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3075 if (action & F_MAIN) {
3076 /* Check for min/max values */
3077 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3078 itv, spmin, spmax, g_fields);
3081 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3082 S_VALUE(snip->InReceives, snic->InReceives, itv),
3083 out, outsize, svg_p->restart);
3085 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3086 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
3087 out + 1, outsize + 1, svg_p->restart);
3089 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3090 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
3091 out + 2, outsize + 2, svg_p->restart);
3093 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3094 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3095 out + 3, outsize + 3, svg_p->restart);
3097 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3098 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3099 out + 4, outsize + 4, svg_p->restart);
3101 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3102 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3103 out + 5, outsize + 5, svg_p->restart);
3105 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3106 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3107 out + 6, outsize + 6, svg_p->restart);
3109 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3110 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3111 out + 7, outsize + 7, svg_p->restart);
3114 if (action & F_END) {
3115 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3116 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3118 /* Free remaining structures */
3119 free_graphs(out, outsize, spmin, spmax);
3124 ***************************************************************************
3125 * Display IPv4 traffic errors statistics in SVG.
3128 * @a Activity structure with statistics.
3129 * @curr Index in array for current sample statistics.
3130 * @action Action expected from current function.
3131 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3132 * flag indicating that a restart record has been previously
3133 * found (.@restart) and time used for the X axis origin
3135 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3136 * @record_hdr Pointer on record header of current stats sample.
3137 ***************************************************************************
3139 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3140 unsigned long long itv, struct record_header *record_hdr)
3142 struct stats_net_eip
3143 *sneic = (struct stats_net_eip *) a->buf[curr],
3144 *sneip = (struct stats_net_eip *) a->buf[!curr];
3145 int group[] = {3, 2, 3};
3146 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3147 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3148 "IPv4 traffic errors statistics (3)"};
3149 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3150 "idisc/s", "odisc/s",
3151 "onort/s", "asmf/s", "fragf/s"};
3152 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3153 static double *spmin, *spmax;
3155 static int *outsize;
3157 if (action & F_BEGIN) {
3159 * Allocate arrays that will contain the graphs data
3160 * and the min/max values.
3162 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3165 if (action & F_MAIN) {
3166 /* Check for min/max values */
3167 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3168 itv, spmin, spmax, g_fields);
3171 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3172 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3173 out, outsize, svg_p->restart);
3175 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3176 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3177 out + 1, outsize + 1, svg_p->restart);
3179 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3180 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3181 out + 2, outsize + 2, svg_p->restart);
3183 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3184 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3185 out + 3, outsize + 3, svg_p->restart);
3187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3188 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3189 out + 4, outsize + 4, svg_p->restart);
3191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3192 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3193 out + 5, outsize + 5, svg_p->restart);
3195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3196 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3197 out + 6, outsize + 6, svg_p->restart);
3199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3200 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3201 out + 7, outsize + 7, svg_p->restart);
3204 if (action & F_END) {
3205 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3206 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3208 /* Free remaining structures */
3209 free_graphs(out, outsize, spmin, spmax);
3214 ***************************************************************************
3215 * Display ICMPv4 traffic statistics in SVG.
3218 * @a Activity structure with statistics.
3219 * @curr Index in array for current sample statistics.
3220 * @action Action expected from current function.
3221 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3222 * flag indicating that a restart record has been previously
3223 * found (.@restart) and time used for the X axis origin
3225 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3226 * @record_hdr Pointer on record header of current stats sample.
3227 ***************************************************************************
3229 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3230 unsigned long long itv, struct record_header *record_hdr)
3232 struct stats_net_icmp
3233 *snic = (struct stats_net_icmp *) a->buf[curr],
3234 *snip = (struct stats_net_icmp *) a->buf[!curr];
3235 int group[] = {2, 4, 4, 4};
3236 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3238 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3239 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3240 char *g_title[] = {"imsg/s", "omsg/s",
3241 "iech/s", "iechr/s", "oech/s", "oechr/s",
3242 "itm/s", "itmr/s", "otm/s", "otmr/s",
3243 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3244 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3245 static double *spmin, *spmax;
3247 static int *outsize;
3249 if (action & F_BEGIN) {
3251 * Allocate arrays that will contain the graphs data
3252 * and the min/max values.
3254 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3257 if (action & F_MAIN) {
3258 /* Check for min/max values */
3259 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3260 itv, spmin, spmax, g_fields);
3263 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3264 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3265 out, outsize, svg_p->restart);
3267 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3268 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3269 out + 1, outsize + 1, svg_p->restart);
3271 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3272 S_VALUE(snip->InEchos, snic->InEchos, itv),
3273 out + 2, outsize + 2, svg_p->restart);
3275 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3276 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3277 out + 3, outsize + 3, svg_p->restart);
3279 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3280 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3281 out + 4, outsize + 4, svg_p->restart);
3283 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3284 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3285 out + 5, outsize + 5, svg_p->restart);
3287 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3288 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3289 out + 6, outsize + 6, svg_p->restart);
3291 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3292 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3293 out + 7, outsize + 7, svg_p->restart);
3295 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3296 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3297 out + 8, outsize + 8, svg_p->restart);
3299 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3300 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3301 out + 9, outsize + 9, svg_p->restart);
3303 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3304 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3305 out + 10, outsize + 10, svg_p->restart);
3307 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3308 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3309 out + 11, outsize + 11, svg_p->restart);
3311 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3312 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3313 out + 12, outsize + 12, svg_p->restart);
3315 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3316 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3317 out + 13, outsize + 13, svg_p->restart);
3320 if (action & F_END) {
3321 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3322 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3324 /* Free remaining structures */
3325 free_graphs(out, outsize, spmin, spmax);
3330 ***************************************************************************
3331 * Display ICMPv4 traffic errors statistics in SVG.
3334 * @a Activity structure with statistics.
3335 * @curr Index in array for current sample statistics.
3336 * @action Action expected from current function.
3337 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3338 * flag indicating that a restart record has been previously
3339 * found (.@restart) and time used for the X axis origin
3341 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3342 * @record_hdr Pointer on record header of current stats sample.
3343 ***************************************************************************
3345 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3346 unsigned long long itv, struct record_header *record_hdr)
3348 struct stats_net_eicmp
3349 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3350 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3351 int group[] = {2, 2, 2, 2, 2, 2};
3352 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3353 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3354 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3355 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3356 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3357 char *g_title[] = {"ierr/s", "oerr/s",
3358 "idstunr/s", "odstunr/s",
3359 "itmex/s", "otmex/s",
3360 "iparmpb/s", "oparmpb/s",
3361 "isrcq/s", "osrcq/s",
3362 "iredir/s", "oredir/s"};
3363 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3364 static double *spmin, *spmax;
3366 static int *outsize;
3368 if (action & F_BEGIN) {
3370 * Allocate arrays that will contain the graphs data
3371 * and the min/max values.
3373 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3376 if (action & F_MAIN) {
3377 /* Check for min/max values */
3378 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3379 itv, spmin, spmax, g_fields);
3382 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3383 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3384 out, outsize, svg_p->restart);
3386 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3387 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3388 out + 1, outsize + 1, svg_p->restart);
3390 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3391 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3392 out + 2, outsize + 2, svg_p->restart);
3394 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3395 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3396 out + 3, outsize + 3, svg_p->restart);
3398 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3399 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3400 out + 4, outsize + 4, svg_p->restart);
3402 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3403 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3404 out + 5, outsize + 5, svg_p->restart);
3406 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3407 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3408 out + 6, outsize + 6, svg_p->restart);
3410 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3411 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3412 out + 7, outsize + 7, svg_p->restart);
3414 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3415 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3416 out + 8, outsize + 8, svg_p->restart);
3418 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3419 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3420 out + 9, outsize + 9, svg_p->restart);
3422 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3423 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3424 out + 10, outsize + 10, svg_p->restart);
3426 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3427 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3428 out + 11, outsize + 11, svg_p->restart);
3431 if (action & F_END) {
3432 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3433 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3435 /* Free remaining structures */
3436 free_graphs(out, outsize, spmin, spmax);
3441 ***************************************************************************
3442 * Display TCPv4 traffic statistics in SVG.
3445 * @a Activity structure with statistics.
3446 * @curr Index in array for current sample statistics.
3447 * @action Action expected from current function.
3448 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3449 * flag indicating that a restart record has been previously
3450 * found (.@restart) and time used for the X axis origin
3452 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3453 * @record_hdr Pointer on record header of current stats sample.
3454 ***************************************************************************
3456 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3457 unsigned long long itv, struct record_header *record_hdr)
3459 struct stats_net_tcp
3460 *sntc = (struct stats_net_tcp *) a->buf[curr],
3461 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3462 int group[] = {2, 2};
3463 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3464 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3465 char *g_title[] = {"active/s", "passive/s",
3466 "iseg/s", "oseg/s"};
3467 int g_fields[] = {0, 1, 2, 3};
3468 static double *spmin, *spmax;
3470 static int *outsize;
3472 if (action & F_BEGIN) {
3474 * Allocate arrays that will contain the graphs data
3475 * and the min/max values.
3477 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3480 if (action & F_MAIN) {
3481 /* Check for min/max values */
3482 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3483 itv, spmin, spmax, g_fields);
3486 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3487 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3488 out, outsize, svg_p->restart);
3490 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3491 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3492 out + 1, outsize + 1, svg_p->restart);
3494 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3495 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3496 out + 2, outsize + 2, svg_p->restart);
3498 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3499 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3500 out + 3, outsize + 3, svg_p->restart);
3503 if (action & F_END) {
3504 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3505 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3507 /* Free remaining structures */
3508 free_graphs(out, outsize, spmin, spmax);
3513 ***************************************************************************
3514 * Display TCPv4 traffic errors statistics in SVG.
3517 * @a Activity structure with statistics.
3518 * @curr Index in array for current sample statistics.
3519 * @action Action expected from current function.
3520 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3521 * flag indicating that a restart record has been previously
3522 * found (.@restart) and time used for the X axis origin
3524 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3525 * @record_hdr Pointer on record header of current stats sample.
3526 ***************************************************************************
3528 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3529 unsigned long long itv, struct record_header *record_hdr)
3531 struct stats_net_etcp
3532 *snetc = (struct stats_net_etcp *) a->buf[curr],
3533 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3534 int group[] = {2, 3};
3535 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3536 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3537 char *g_title[] = {"atmptf/s", "estres/s",
3538 "retrans/s", "isegerr/s", "orsts/s"};
3539 int g_fields[] = {0, 1, 2, 3, 4};
3540 static double *spmin, *spmax;
3542 static int *outsize;
3544 if (action & F_BEGIN) {
3546 * Allocate arrays that will contain the graphs data
3547 * and the min/max values.
3549 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3552 if (action & F_MAIN) {
3553 /* Check for min/max values */
3554 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3555 itv, spmin, spmax, g_fields);
3558 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3559 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3560 out, outsize, svg_p->restart);
3562 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3563 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3564 out + 1, outsize + 1, svg_p->restart);
3566 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3567 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3568 out + 2, outsize + 2, svg_p->restart);
3570 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3571 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3572 out + 3, outsize + 3, svg_p->restart);
3574 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3575 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3576 out + 4, outsize + 4, svg_p->restart);
3579 if (action & F_END) {
3580 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3581 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3583 /* Free remaining structures */
3584 free_graphs(out, outsize, spmin, spmax);
3589 ***************************************************************************
3590 * Display UDPv4 traffic statistics in SVG.
3593 * @a Activity structure with statistics.
3594 * @curr Index in array for current sample statistics.
3595 * @action Action expected from current function.
3596 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3597 * flag indicating that a restart record has been previously
3598 * found (.@restart) and time used for the X axis origin
3600 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3601 * @record_hdr Pointer on record header of current stats sample.
3602 ***************************************************************************
3604 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3605 unsigned long long itv, struct record_header *record_hdr)
3607 struct stats_net_udp
3608 *snuc = (struct stats_net_udp *) a->buf[curr],
3609 *snup = (struct stats_net_udp *) a->buf[!curr];
3610 int group[] = {2, 2};
3611 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3612 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3613 char *g_title[] = {"idgm/s", "odgm/s",
3614 "noport/s", "idgmerr/s"};
3615 int g_fields[] = {0, 1, 2, 3};
3616 static double *spmin, *spmax;
3618 static int *outsize;
3620 if (action & F_BEGIN) {
3622 * Allocate arrays that will contain the graphs data
3623 * and the min/max values.
3625 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3628 if (action & F_MAIN) {
3629 /* Check for min/max values */
3630 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3631 itv, spmin, spmax, g_fields);
3634 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3635 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3636 out, outsize, svg_p->restart);
3638 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3639 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3640 out + 1, outsize + 1, svg_p->restart);
3642 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3643 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3644 out + 2, outsize + 2, svg_p->restart);
3646 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3647 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3648 out + 3, outsize + 3, svg_p->restart);
3651 if (action & F_END) {
3652 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3653 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3655 /* Free remaining structures */
3656 free_graphs(out, outsize, spmin, spmax);
3661 ***************************************************************************
3662 * Display IPV6 socket statistics in SVG.
3665 * @a Activity structure with statistics.
3666 * @curr Index in array for current sample statistics.
3667 * @action Action expected from current function.
3668 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3669 * flag indicating that a restart record has been previously
3670 * found (.@restart) and time used for the X axis origin
3672 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3673 * @record_hdr Pointer on record header of current stats sample.
3674 ***************************************************************************
3676 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3677 unsigned long long itv, struct record_header *record_hdr)
3679 struct stats_net_sock6
3680 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3682 int g_type[] = {SVG_LINE_GRAPH};
3683 char *title[] = {"IPv6 sockets statistics"};
3684 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3685 int g_fields[] = {0, 1, 2, 3};
3686 static double *spmin, *spmax;
3688 static int *outsize;
3690 if (action & F_BEGIN) {
3692 * Allocate arrays that will contain the graphs data
3693 * and the min/max values.
3695 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3698 if (action & F_MAIN) {
3699 /* Check for min/max values */
3700 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3701 itv, spmin, spmax, g_fields);
3703 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3704 (unsigned long long) snsc->tcp6_inuse,
3705 out, outsize, svg_p->restart);
3707 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3708 (unsigned long long) snsc->udp6_inuse,
3709 out + 1, outsize + 1, svg_p->restart);
3711 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3712 (unsigned long long) snsc->raw6_inuse,
3713 out + 2, outsize + 2, svg_p->restart);
3715 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3716 (unsigned long long) snsc->frag6_inuse,
3717 out + 3, outsize + 3, svg_p->restart);
3720 if (action & F_END) {
3721 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3722 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3724 /* Free remaining structures */
3725 free_graphs(out, outsize, spmin, spmax);
3730 ***************************************************************************
3731 * Display IPv6 traffic statistics in SVG.
3734 * @a Activity structure with statistics.
3735 * @curr Index in array for current sample statistics.
3736 * @action Action expected from current function.
3737 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3738 * flag indicating that a restart record has been previously
3739 * found (.@restart) and time used for the X axis origin
3741 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3742 * @record_hdr Pointer on record header of current stats sample.
3743 ***************************************************************************
3745 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3746 unsigned long long itv, struct record_header *record_hdr)
3748 struct stats_net_ip6
3749 *snic = (struct stats_net_ip6 *) a->buf[curr],
3750 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3751 int group[] = {4, 2, 2, 2};
3752 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3754 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3755 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3756 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3757 "asmrq6/s", "asmok6/s",
3758 "imcpck6/s", "omcpck6/s",
3759 "fragok6/s", "fragcr6/s"};
3760 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3761 static double *spmin, *spmax;
3763 static int *outsize;
3765 if (action & F_BEGIN) {
3767 * Allocate arrays that will contain the graphs data
3768 * and the min/max values.
3770 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3773 if (action & F_MAIN) {
3774 /* Check for min/max values */
3775 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3776 itv, spmin, spmax, g_fields);
3779 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3780 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3781 out, outsize, svg_p->restart);
3783 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3784 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3785 out + 1, outsize + 1, svg_p->restart);
3787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3788 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3789 out + 2, outsize + 2, svg_p->restart);
3791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3792 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3793 out + 3, outsize + 3, svg_p->restart);
3795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3796 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3797 out + 4, outsize + 4, svg_p->restart);
3799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3800 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3801 out + 5, outsize + 5, svg_p->restart);
3803 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3804 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3805 out + 6, outsize + 6, svg_p->restart);
3807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3808 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3809 out + 7, outsize + 7, svg_p->restart);
3811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3812 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3813 out + 8, outsize + 8, svg_p->restart);
3815 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3816 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3817 out + 9, outsize + 9, svg_p->restart);
3820 if (action & F_END) {
3821 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3822 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3824 /* Free remaining structures */
3825 free_graphs(out, outsize, spmin, spmax);
3830 ***************************************************************************
3831 * Display IPv6 traffic errors statistics in SVG.
3834 * @a Activity structure with statistics.
3835 * @curr Index in array for current sample statistics.
3836 * @action Action expected from current function.
3837 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3838 * flag indicating that a restart record has been previously
3839 * found (.@restart) and time used for the X axis origin
3841 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3842 * @record_hdr Pointer on record header of current stats sample.
3843 ***************************************************************************
3845 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3846 unsigned long long itv, struct record_header *record_hdr)
3848 struct stats_net_eip6
3849 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3850 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3851 int group[] = {4, 2, 2, 3};
3852 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3854 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3855 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3856 "IPv6 traffic errors statistics (5)"};
3857 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3858 "idisc6/s", "odisc6/s",
3859 "inort6/s", "onort6/s",
3860 "asmf6/s", "fragf6/s", "itrpck6/s"};
3861 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3862 static double *spmin, *spmax;
3864 static int *outsize;
3866 if (action & F_BEGIN) {
3868 * Allocate arrays that will contain the graphs data
3869 * and the min/max values.
3871 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3874 if (action & F_MAIN) {
3875 /* Check for min/max values */
3876 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3877 itv, spmin, spmax, g_fields);
3880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3881 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3882 out, outsize, svg_p->restart);
3884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3885 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3886 out + 1, outsize + 1, svg_p->restart);
3888 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3889 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3890 out + 2, outsize + 2, svg_p->restart);
3892 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3893 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3894 out + 3, outsize + 3, svg_p->restart);
3896 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3897 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3898 out + 4, outsize + 4, svg_p->restart);
3900 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3901 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3902 out + 5, outsize + 5, svg_p->restart);
3904 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3905 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3906 out + 6, outsize + 6, svg_p->restart);
3908 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3909 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3910 out + 7, outsize + 7, svg_p->restart);
3912 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3913 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3914 out + 8, outsize + 8, svg_p->restart);
3916 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3917 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3918 out + 9, outsize + 9, svg_p->restart);
3920 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3921 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3922 out + 10, outsize + 10, svg_p->restart);
3925 if (action & F_END) {
3926 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3927 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3929 /* Free remaining structures */
3930 free_graphs(out, outsize, spmin, spmax);
3935 ***************************************************************************
3936 * Display ICMPv6 traffic statistics in SVG.
3939 * @a Activity structure with statistics.
3940 * @curr Index in array for current sample statistics.
3941 * @action Action expected from current function.
3942 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3943 * flag indicating that a restart record has been previously
3944 * found (.@restart) and time used for the X axis origin
3946 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3947 * @record_hdr Pointer on record header of current stats sample.
3948 ***************************************************************************
3950 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3951 unsigned long long itv, struct record_header *record_hdr)
3953 struct stats_net_icmp6
3954 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3955 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3956 int group[] = {2, 3, 5, 3, 4};
3957 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3958 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3959 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3960 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3961 "ICMPv6 traffic statistics (5)"};
3962 char *g_title[] = {"imsg6/s", "omsg6/s",
3963 "iech6/s", "iechr6/s", "oechr6/s",
3964 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3965 "irtsol6/s", "ortsol6/s", "irtad6/s",
3966 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3967 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3968 static double *spmin, *spmax;
3970 static int *outsize;
3972 if (action & F_BEGIN) {
3974 * Allocate arrays that will contain the graphs data
3975 * and the min/max values.
3977 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3980 if (action & F_MAIN) {
3981 /* Check for min/max values */
3982 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3983 itv, spmin, spmax, g_fields);
3986 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3987 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3988 out, outsize, svg_p->restart);
3990 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3991 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3992 out + 1, outsize + 1, svg_p->restart);
3994 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3995 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3996 out + 2, outsize + 2, svg_p->restart);
3998 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3999 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
4000 out + 3, outsize + 3, svg_p->restart);
4002 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4003 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
4004 out + 4, outsize + 4, svg_p->restart);
4006 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4007 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
4008 out + 5, outsize + 5, svg_p->restart);
4010 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4011 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
4012 out + 6, outsize + 6, svg_p->restart);
4014 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4015 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
4016 out + 7, outsize + 7, svg_p->restart);
4018 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4019 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
4020 out + 8, outsize + 8, svg_p->restart);
4022 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4023 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
4024 out + 9, outsize + 9, svg_p->restart);
4026 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4027 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
4028 out + 10, outsize + 10, svg_p->restart);
4030 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4031 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
4032 out + 11, outsize + 11, svg_p->restart);
4034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4035 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
4036 out + 12, outsize + 12, svg_p->restart);
4038 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4039 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
4040 out + 13, outsize + 13, svg_p->restart);
4042 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4043 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
4044 out + 14, outsize + 14, svg_p->restart);
4046 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4047 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
4048 out + 15, outsize + 15, svg_p->restart);
4050 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4051 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
4052 out + 16, outsize + 16, svg_p->restart);
4055 if (action & F_END) {
4056 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4057 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4059 /* Free remaining structures */
4060 free_graphs(out, outsize, spmin, spmax);
4065 ***************************************************************************
4066 * Display ICMPv6 traffic errors statistics in SVG.
4069 * @a Activity structure with statistics.
4070 * @curr Index in array for current sample statistics.
4071 * @action Action expected from current function.
4072 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4073 * flag indicating that a restart record has been previously
4074 * found (.@restart) and time used for the X axis origin
4076 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4077 * @record_hdr Pointer on record header of current stats sample.
4078 ***************************************************************************
4080 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4081 unsigned long long itv, struct record_header *record_hdr)
4083 struct stats_net_eicmp6
4084 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
4085 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
4086 int group[] = {1, 2, 2, 2, 2, 2};
4087 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4088 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4089 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
4090 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
4091 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
4092 char *g_title[] = {"ierr6/s",
4093 "idtunr6/s", "odtunr6/s",
4094 "itmex6/s", "otmex6/s",
4095 "iprmpb6/s", "oprmpb6/s",
4096 "iredir6/s", "oredir6/s",
4097 "ipck2b6/s", "opck2b6/s"};
4098 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4099 static double *spmin, *spmax;
4101 static int *outsize;
4103 if (action & F_BEGIN) {
4105 * Allocate arrays that will contain the graphs data
4106 * and the min/max values.
4108 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4111 if (action & F_MAIN) {
4112 /* Check for min/max values */
4113 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4114 itv, spmin, spmax, g_fields);
4117 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4118 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4119 out, outsize, svg_p->restart);
4121 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4122 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4123 out + 1, outsize + 1, svg_p->restart);
4125 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4126 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4127 out + 2, outsize + 2, svg_p->restart);
4129 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4130 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4131 out + 3, outsize + 3, svg_p->restart);
4133 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4134 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4135 out + 4, outsize + 4, svg_p->restart);
4137 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4138 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4139 out + 5, outsize + 5, svg_p->restart);
4141 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4142 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4143 out + 6, outsize + 6, svg_p->restart);
4145 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4146 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4147 out + 7, outsize + 7, svg_p->restart);
4149 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4150 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4151 out + 8, outsize + 8, svg_p->restart);
4153 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4154 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4155 out + 9, outsize + 9, svg_p->restart);
4157 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4158 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4159 out + 10, outsize + 10, svg_p->restart);
4162 if (action & F_END) {
4163 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4164 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4166 /* Free remaining structures */
4167 free_graphs(out, outsize, spmin, spmax);
4172 ***************************************************************************
4173 * Display UDPv6 traffic statistics in SVG.
4176 * @a Activity structure with statistics.
4177 * @curr Index in array for current sample statistics.
4178 * @action Action expected from current function.
4179 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4180 * flag indicating that a restart record has been previously
4181 * found (.@restart) and time used for the X axis origin
4183 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4184 * @record_hdr Pointer on record header of current stats sample.
4185 ***************************************************************************
4187 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4188 unsigned long long itv, struct record_header *record_hdr)
4190 struct stats_net_udp6
4191 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4192 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4193 int group[] = {2, 2};
4194 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4195 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4196 char *g_title[] = {"idgm6/s", "odgm6/s",
4197 "noport6/s", "idgmer6/s"};
4198 int g_fields[] = {0, 1, 2, 3};
4199 static double *spmin, *spmax;
4201 static int *outsize;
4203 if (action & F_BEGIN) {
4205 * Allocate arrays that will contain the graphs data
4206 * and the min/max values.
4208 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4211 if (action & F_MAIN) {
4212 /* Check for min/max values */
4213 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4214 itv, spmin, spmax, g_fields);
4217 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4218 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4219 out, outsize, svg_p->restart);
4221 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4222 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4223 out + 1, outsize + 1, svg_p->restart);
4225 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4226 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4227 out + 2, outsize + 2, svg_p->restart);
4229 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4230 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4231 out + 3, outsize + 3, svg_p->restart);
4234 if (action & F_END) {
4235 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4236 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4238 /* Free remaining structures */
4239 free_graphs(out, outsize, spmin, spmax);
4244 ***************************************************************************
4245 * Display CPU frequency statistics in SVG.
4248 * @a Activity structure with statistics.
4249 * @curr Index in array for current sample statistics.
4250 * @action Action expected from current function.
4251 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4252 * flag indicating that a restart record has been previously
4253 * found (.@restart) and time used for the X axis origin
4255 * @itv Interval of time in 1/100th of a second (unused here).
4256 * @record_hdr Pointer on record header of current stats sample.
4257 ***************************************************************************
4259 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4260 unsigned long long itv, struct record_header *record_hdr)
4262 struct stats_pwr_cpufreq *spc, *spp;
4264 int g_type[] = {SVG_LINE_GRAPH};
4265 char *title[] = {"CPU clock frequency"};
4266 char *g_title[] = {"MHz"};
4267 static double *spmin, *spmax;
4269 static int *outsize;
4273 if (action & F_BEGIN) {
4275 * Allocate arrays that will contain the graphs data
4276 * and the min/max values.
4278 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4281 if (action & F_MAIN) {
4283 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4285 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4286 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4288 /* Should current CPU (including CPU "all") be displayed? */
4289 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4294 * Note: Don't skip offline CPU here as it is needed
4295 * to make the graph go though 0.
4299 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4300 ((double) spp->cpufreq) / 100,
4301 ((double) spc->cpufreq) / 100,
4302 out + i, outsize + i, svg_p->restart, svg_p->dt,
4303 spmin + i, spmax + i);
4307 if (action & F_END) {
4310 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
4312 /* Should current CPU (including CPU "all") be displayed? */
4313 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4318 /* This is CPU "all" */
4319 strcpy(item_name, "all");
4323 * If the maximum frequency reached by the CPU is 0, then
4324 * the CPU has been offline on the whole period.
4325 * => Don't display it.
4327 if (*(spmax + i) == 0)
4330 sprintf(item_name, "%d", i - 1);
4333 if (draw_activity_graphs(a->g_nr, g_type,
4334 title, g_title, item_name, group,
4335 spmin + i, spmax + i, out + i, outsize + i,
4336 svg_p, record_hdr, i, a, xid)) {
4341 /* Free remaining structures */
4342 free_graphs(out, outsize, spmin, spmax);
4347 ***************************************************************************
4348 * Display fan statistics in SVG.
4351 * @a Activity structure with statistics.
4352 * @curr Index in array for current sample statistics.
4353 * @action Action expected from current function.
4354 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4355 * flag indicating that a restart record has been previously
4356 * found (.@restart) and time used for the X axis origin
4358 * @itv Interval of time in 1/100th of a second (unused here).
4359 * @record_hdr Pointer on record header of current stats sample.
4360 ***************************************************************************
4362 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4363 unsigned long long itv, struct record_header *record_hdr)
4365 struct stats_pwr_fan *spc, *spp;
4367 int g_type[] = {SVG_LINE_GRAPH};
4368 char *title[] = {"Fans speed"};
4369 char *g_title[] = {"~rpm"};
4370 static double *spmin, *spmax;
4372 static int *outsize;
4373 char item_name[MAX_SENSORS_DEV_LEN + 16];
4376 if (action & F_BEGIN) {
4378 * Allocate arrays that will contain the graphs data
4379 * and the min/max values.
4381 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4384 if (action & F_MAIN) {
4386 for (i = 0; i < a->nr[curr]; i++) {
4388 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4389 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4392 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4395 out + i, outsize + i, svg_p->restart, svg_p->dt,
4396 spmin + i, spmax + i);
4400 if (action & F_END) {
4403 for (i = 0; i < a->item_list_sz; i++) {
4405 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4407 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4408 item_name[sizeof(item_name) - 1] = '\0';
4410 if (draw_activity_graphs(a->g_nr, g_type,
4411 title, g_title, item_name, group,
4412 spmin + i, spmax + i, out + i, outsize + i,
4413 svg_p, record_hdr, FALSE, a, xid)) {
4418 /* Free remaining structures */
4419 free_graphs(out, outsize, spmin, spmax);
4424 ***************************************************************************
4425 * Display temperature statistics in SVG.
4428 * @a Activity structure with statistics.
4429 * @curr Index in array for current sample statistics.
4430 * @action Action expected from current function.
4431 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4432 * flag indicating that a restart record has been previously
4433 * found (.@restart) and time used for the X axis origin
4435 * @itv Interval of time in 1/100th of a second (unused here).
4436 * @record_hdr Pointer on record header of current stats sample.
4437 ***************************************************************************
4439 #define TEMP_ARRAY_SZ 2
4440 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4441 unsigned long long itv, struct record_header *record_hdr)
4443 struct stats_pwr_temp *spc;
4444 int group[] = {1, 1};
4445 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4446 char *title[] = {"Devices temperature (1)",
4447 "Devices temperature (2)"};
4448 char *g_title[] = {"~degC",
4450 static double *spmin, *spmax;
4452 static int *outsize;
4453 char item_name[MAX_SENSORS_DEV_LEN + 16];
4457 if (action & F_BEGIN) {
4459 * Allocate arrays that will contain the graphs data
4460 * and the min/max values.
4462 out = allocate_graph_lines(TEMP_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4465 if (action & F_MAIN) {
4466 /* For each temperature sensor */
4467 for (i = 0; i < a->nr[curr]; i++) {
4469 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4471 /* Look for min/max values */
4472 if (spc->temp < *(spmin + TEMP_ARRAY_SZ * i)) {
4473 *(spmin + TEMP_ARRAY_SZ * i) = spc->temp;
4475 if (spc->temp > *(spmax + TEMP_ARRAY_SZ * i)) {
4476 *(spmax + TEMP_ARRAY_SZ * i) = spc->temp;
4478 tval = (spc->temp_max - spc->temp_min) ?
4479 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4481 if (tval < *(spmin + TEMP_ARRAY_SZ * i + 1)) {
4482 *(spmin + TEMP_ARRAY_SZ * i + 1) = tval;
4484 if (tval > *(spmax + TEMP_ARRAY_SZ * i + 1)) {
4485 *(spmax + TEMP_ARRAY_SZ * i + 1) = tval;
4489 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4491 out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i, svg_p->restart);
4493 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4495 out + TEMP_ARRAY_SZ * i + 1, outsize + TEMP_ARRAY_SZ * i + 1, svg_p->dt);
4499 if (action & F_END) {
4502 for (i = 0; i < a->item_list_sz; i++) {
4504 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4506 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4507 item_name[sizeof(item_name) - 1] = '\0';
4509 if (draw_activity_graphs(a->g_nr, g_type,
4510 title, g_title, item_name, group,
4511 spmin + TEMP_ARRAY_SZ * i, spmax + TEMP_ARRAY_SZ * i,
4512 out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i,
4513 svg_p, record_hdr, FALSE, a, xid)) {
4518 /* Free remaining structures */
4519 free_graphs(out, outsize, spmin, spmax);
4524 ***************************************************************************
4525 * Display voltage inputs statistics in SVG.
4528 * @a Activity structure with statistics.
4529 * @curr Index in array for current sample statistics.
4530 * @action Action expected from current function.
4531 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4532 * flag indicating that a restart record has been previously
4533 * found (.@restart) and time used for the X axis origin
4535 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4536 * @record_hdr Pointer on record header of current stats sample.
4537 ***************************************************************************
4539 #define IN_ARRAY_SZ 2
4540 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4541 unsigned long long itv, struct record_header *record_hdr)
4543 struct stats_pwr_in *spc;
4544 int group[] = {1, 1};
4545 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4546 char *title[] = {"Voltage inputs statistics (1)",
4547 "Voltage inputs statistics (2)"};
4548 char *g_title[] = {"inV",
4550 static double *spmin, *spmax;
4552 static int *outsize;
4553 char item_name[MAX_SENSORS_DEV_LEN + 16];
4557 if (action & F_BEGIN) {
4559 * Allocate arrays that will contain the graphs data
4560 * and the min/max values.
4562 out = allocate_graph_lines(IN_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4565 if (action & F_MAIN) {
4566 /* For each voltage input sensor */
4567 for (i = 0; i < a->nr[curr]; i++) {
4569 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4571 /* Look for min/max values */
4572 if (spc->in < *(spmin + IN_ARRAY_SZ * i)) {
4573 *(spmin + IN_ARRAY_SZ * i) = spc->in;
4575 if (spc->in > *(spmax + IN_ARRAY_SZ * i)) {
4576 *(spmax + IN_ARRAY_SZ * i) = spc->in;
4578 tval = (spc->in_max - spc->in_min) ?
4579 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4581 if (tval < *(spmin + IN_ARRAY_SZ * i + 1)) {
4582 *(spmin + IN_ARRAY_SZ * i + 1) = tval;
4584 if (tval > *(spmax + IN_ARRAY_SZ * i + 1)) {
4585 *(spmax + IN_ARRAY_SZ * i + 1) = tval;
4589 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4591 out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i, svg_p->restart);
4593 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4595 out + IN_ARRAY_SZ * i + 1, outsize + IN_ARRAY_SZ * i + 1, svg_p->dt);
4599 if (action & F_END) {
4602 for (i = 0; i < a->item_list_sz; i++) {
4604 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4606 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4607 item_name[sizeof(item_name) - 1] = '\0';
4609 if (draw_activity_graphs(a->g_nr, g_type,
4610 title, g_title, item_name, group,
4611 spmin + IN_ARRAY_SZ * i, spmax + IN_ARRAY_SZ * i,
4612 out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i,
4613 svg_p, record_hdr, FALSE, a, xid)) {
4618 /* Free remaining structures */
4619 free_graphs(out, outsize, spmin, spmax);
4624 ***************************************************************************
4625 * Display huge pages statistics in SVG.
4628 * @a Activity structure with statistics.
4629 * @curr Index in array for current sample statistics.
4630 * @action Action expected from current function.
4631 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4632 * flag indicating that a restart record has been previously
4633 * found (.@restart) and time used for the X axis origin
4635 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4636 * @record_hdr Pointer on record header of current stats sample.
4637 ***************************************************************************
4639 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4640 unsigned long long itv, struct record_header *record_hdr)
4643 *smc = (struct stats_huge *) a->buf[curr];
4644 int group[] = {4, 1};
4645 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4646 char *title[] = {"Huge pages utilization (1)",
4647 "Huge pages utilization (2)"};
4648 char *g_title[] = {"~kbhugfree", "~kbhugused", "~kbhugrsvd", "~kbhugsurp",
4650 int g_fields[] = {0, 5, 2, 3};
4651 static double *spmin, *spmax;
4653 static int *outsize;
4656 if (action & F_BEGIN) {
4658 * Allocate arrays that will contain the graphs data
4659 * and the min/max values.
4660 * Allocate one additional array (#5) to save min/max
4661 * values for tlhkb (unused).
4663 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
4666 if (action & F_MAIN) {
4667 /* Check for min/max values */
4668 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
4669 itv, spmin, spmax, g_fields);
4671 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4672 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4674 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4675 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4677 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4678 if (tval < *(spmin + 4)) {
4679 *(spmin + 4) = tval;
4681 if (tval > *(spmax + 4)) {
4682 *(spmax + 4) = tval;
4686 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4687 (unsigned long long) smc->frhkb,
4688 out, outsize, svg_p->restart);
4690 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4691 (unsigned long long) smc->tlhkb - smc->frhkb,
4692 out + 1, outsize + 1, svg_p->restart);
4694 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4695 (unsigned long long) smc->rsvdhkb,
4696 out + 2, outsize + 2, svg_p->restart);
4698 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4699 (unsigned long long) smc->surphkb,
4700 out + 3, outsize + 3, svg_p->restart);
4702 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4704 out + 4, outsize + 4, svg_p->dt);
4707 if (action & F_END) {
4708 draw_activity_graphs(a->g_nr, g_type,
4709 title, g_title, NULL, group,
4710 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4712 /* Free remaining structures */
4713 free_graphs(out, outsize, spmin, spmax);
4718 ***************************************************************************
4719 * Display filesystem statistics in SVG.
4722 * @a Activity structure with statistics.
4723 * @curr Index in array for current sample statistics.
4724 * @action Action expected from current function.
4725 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4726 * flag indicating that a restart record has been previously
4727 * found (.@restart) and time used for the X axis origin
4729 * @itv Interval of time in 1/100th of a second (unused here).
4730 * @record_hdr Pointer on record header of current stats sample.
4731 ***************************************************************************
4733 #define FS_ARRAY_SZ 8
4734 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4735 unsigned long long itv, struct record_header *record_hdr)
4737 struct stats_filesystem *sfc, *sfp;
4738 int group[] = {2, 2, 2, 1};
4739 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4740 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4741 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4742 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4743 char *g_title[] = {"~MBfsfree", "~MBfsused",
4744 "%ufsused", "%fsused",
4745 "Ifree/1000", "Iused/1000",
4747 static double *spmin, *spmax;
4749 static int *outsize;
4750 char *dev_name, *item_name;
4752 int i, k, pos, restart;
4754 if (action & F_BEGIN) {
4756 * Allocate arrays (#0..6) that will contain the graphs data
4757 * and the min/max values.
4758 * Also allocate an additional arrays (#7) for each filesystem:
4759 * out + 7 will contain the persistent or standard fs name, or mount point.
4761 out = allocate_graph_lines(FS_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4764 if (action & F_MAIN) {
4765 /* For each filesystem structure */
4766 for (i = 0; i < a->nr[curr]; i++) {
4767 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4769 /* Get name to display (persistent or standard fs name, or mount point) */
4770 dev_name = get_fs_name_to_display(a, flags, sfc);
4772 if (a->item_list != NULL) {
4773 /* A list of devices has been entered on the command line */
4774 if (!search_list_item(a->item_list, dev_name))
4775 /* Device not found */
4779 /* Look for corresponding graph */
4780 for (k = 0; k < a->item_list_sz; k++) {
4781 item_name = *(out + k * FS_ARRAY_SZ + 7);
4782 if (!strcmp(dev_name, item_name))
4787 if (k == a->item_list_sz) {
4788 /* Graph not found: Look for first free entry */
4789 for (k = 0; k < a->item_list_sz; k++) {
4790 item_name = *(out + k * FS_ARRAY_SZ + 7);
4791 if (!strcmp(item_name, ""))
4794 if (k == a->item_list_sz) {
4795 /* No free graph entry: Ignore it (should never happen) */
4797 fprintf(stderr, "%s: Name=%s\n",
4798 __FUNCTION__, sfc->fs_name);
4804 pos = k * FS_ARRAY_SZ;
4806 item_name = *(out + pos + 7);
4807 if (!item_name[0]) {
4808 /* Save filesystem name and mount point (if not already done) */
4809 strncpy(item_name, dev_name, CHUNKSIZE);
4810 item_name[CHUNKSIZE - 1] = '\0';
4814 for (k = 0; k < a->nr[!curr]; k++) {
4815 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4816 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4817 /* Filesystem found in previous sample */
4818 restart = svg_p->restart;
4822 /* Check for min/max values */
4824 /* Compute fsfree min/max values */
4825 tval = (double) sfc->f_bfree;
4826 if (tval > *(spmax + pos)) {
4827 *(spmax + pos) = tval;
4829 if (tval < *(spmin + pos)) {
4830 *(spmin + pos) = tval;
4832 /* Compute fsused min/max values */
4833 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4834 if (tval > *(spmax + pos + 1)) {
4835 *(spmax + pos + 1) = tval;
4837 if (tval < *(spmin + pos + 1)) {
4838 *(spmin + pos + 1) = tval;
4840 /* Compute %ufsused min/max values */
4841 tval = sfc->f_blocks ?
4842 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4843 if (tval > *(spmax + pos + 2)) {
4844 *(spmax + pos + 2) = tval;
4846 if (tval < *(spmin + pos + 2)) {
4847 *(spmin + pos + 2) = tval;
4849 /* Compute %fsused min/max values */
4850 tval = sfc->f_blocks ?
4851 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4852 if (tval > *(spmax + pos + 3)) {
4853 *(spmax + pos + 3) = tval;
4855 if (tval < *(spmin + pos + 3)) {
4856 *(spmin + pos + 3) = tval;
4858 /* Compute Ifree min/max values */
4859 tval = (double) sfc->f_ffree;
4860 if (tval > *(spmax + pos + 4)) {
4861 *(spmax + pos + 4) = tval;
4863 if (tval < *(spmin + pos + 4)) {
4864 *(spmin + pos + 4) = tval;
4866 /* Compute Iused min/max values */
4867 tval = (double) (sfc->f_files - sfc->f_ffree);
4868 if (tval > *(spmax + pos + 5)) {
4869 *(spmax + pos + 5) = tval;
4871 if (tval < *(spmin + pos + 5)) {
4872 *(spmin + pos + 5) = tval;
4874 /* Compute %Iused min/max values */
4875 tval = sfc->f_files ?
4876 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4877 if (tval > *(spmax + pos + 6)) {
4878 *(spmax + pos + 6) = tval;
4880 if (tval < *(spmin + pos + 6)) {
4881 *(spmin + pos + 6) = tval;
4885 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4886 (double) sfc->f_bfree / 1024 / 1024,
4887 out + pos, outsize + pos, restart);
4889 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4890 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4891 out + pos + 1, outsize + pos + 1, restart);
4893 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4896 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4897 out + pos + 2, outsize + pos + 2, svg_p->dt);
4899 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4902 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4903 out + pos + 3, outsize + pos + 3, svg_p->dt);
4905 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4906 ((double) sfc->f_ffree) / 1000,
4907 out + pos + 4, outsize + pos + 4, restart);
4909 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4910 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4911 out + pos + 5, outsize + pos + 5, restart);
4913 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4916 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4917 out + pos + 6, outsize + pos + 6, svg_p->dt);
4921 if (action & F_END) {
4924 for (i = 0; i < a->item_list_sz; i++) {
4926 /* Check if there is something to display */
4927 pos = i * FS_ARRAY_SZ;
4931 /* Conversion B -> MiB and inodes/1000 */
4932 for (k = 0; k < 2; k++) {
4933 *(spmin + pos + k) /= (1024 * 1024);
4934 *(spmax + pos + k) /= (1024 * 1024);
4935 *(spmin + pos + 4 + k) /= 1000;
4936 *(spmax + pos + 4 + k) /= 1000;
4939 item_name = *(out + pos + 7);
4941 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4942 spmin + pos, spmax + pos, out + pos, outsize + pos,
4943 svg_p, record_hdr, FALSE, a, xid)) {
4948 /* Free remaining structures */
4949 free_graphs(out, outsize, spmin, spmax);
4954 ***************************************************************************
4955 * Display Fibre Channel HBA statistics in SVG.
4958 * @a Activity structure with statistics.
4959 * @curr Index in array for current sample statistics.
4960 * @action Action expected from current function.
4961 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4962 * flag indicating that a restart record has been previously
4963 * found (.@restart) and time used for the X axis origin
4965 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4966 * @record_hdr Pointer on record header of current stats sample.
4967 ***************************************************************************
4969 #define FC_ARRAY_SZ 5
4970 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4971 unsigned long long itv, struct record_header *record_hdr)
4973 struct stats_fchost *sfcc, *sfcp, sfczero;
4974 int group[] = {2, 2};
4975 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4976 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4977 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4978 "fch_rxw/s", "fch_txw/s"};
4979 int g_fields[] = {0, 1, 2, 3};
4980 static double *spmin, *spmax;
4982 static int *outsize;
4984 int i, j, j0, k, found, pos, restart, *unregistered;
4986 if (action & F_BEGIN) {
4988 * Allocate arrays (#0..3) that will contain the graphs data
4989 * and the min/max values.
4990 * Also allocate one additional array (#4) that will contain
4991 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4992 * has either still not been registered, or has been unregistered
4995 out = allocate_graph_lines(FC_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4998 if (action & F_MAIN) {
4999 memset(&sfczero, 0, sizeof(struct stats_fchost));
5001 * Mark previously registered interfaces as now
5002 * possibly unregistered for all graphs.
5004 for (k = 0; k < a->item_list_sz; k++) {
5005 unregistered = outsize + k * FC_ARRAY_SZ + 4;
5006 if (*unregistered == FALSE) {
5007 *unregistered = MAYBE;
5011 /* For each FC HBA */
5012 for (i = 0; i < a->nr[curr]; i++) {
5015 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
5016 restart = svg_p->restart;
5018 /* Look for corresponding graph */
5019 for (k = 0; k < a->item_list_sz; k++) {
5020 item_name = *(out + k * FC_ARRAY_SZ + 4);
5021 if (!strcmp(sfcc->fchost_name, item_name))
5025 if (k == a->item_list_sz) {
5026 /* Graph not found: Look for first free entry */
5027 for (k = 0; k < a->item_list_sz; k++) {
5028 item_name = *(out + k * FC_ARRAY_SZ + 4);
5029 if (!strcmp(item_name, ""))
5032 if (k == a->item_list_sz) {
5033 /* No free graph entry: Ignore it (should never happen) */
5035 fprintf(stderr, "%s: Name=%s\n",
5036 __FUNCTION__, sfcc->fchost_name);
5042 pos = k * FC_ARRAY_SZ;
5043 unregistered = outsize + pos + 4;
5045 if (a->nr[!curr] > 0) {
5046 /* Look for corresponding structure in previous iteration */
5049 if (j >= a->nr[!curr]) {
5050 j = a->nr[!curr] - 1;
5056 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
5057 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
5061 if (++j >= a->nr[!curr]) {
5069 /* This is a newly registered host */
5075 * If current interface was marked as previously unregistered,
5076 * then set restart variable to TRUE so that the graph will be
5077 * discontinuous, and mark it as now registered.
5079 if (*unregistered == TRUE) {
5082 *unregistered = FALSE;
5084 item_name = *(out + pos + 4);
5085 if (!item_name[0]) {
5086 /* Save FC HBA name */
5087 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
5088 item_name[CHUNKSIZE - 1] = '\0';
5091 /* Look for min/max values */
5092 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
5093 itv, spmin + pos, spmax + pos, g_fields);
5096 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5097 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5098 out + pos, outsize + pos, restart);
5100 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5101 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5102 out + pos + 1, outsize + pos + 1, restart);
5104 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5105 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5106 out + pos + 2, outsize + pos + 2, restart);
5108 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5109 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5110 out + pos + 3, outsize + pos + 3, restart);
5113 /* Mark interfaces not seen here as now unregistered */
5114 for (k = 0; k < a->item_list_sz; k++) {
5115 unregistered = outsize + k * FC_ARRAY_SZ + 4;
5116 if (*unregistered != FALSE) {
5117 *unregistered = TRUE;
5122 if (action & F_END) {
5123 for (i = 0; i < a->item_list_sz; i++) {
5125 /* Check if there is something to display */
5126 pos = i * FC_ARRAY_SZ;
5130 item_name = *(out + pos + 4);
5131 draw_activity_graphs(a->g_nr, g_type,
5132 title, g_title, item_name, group,
5133 spmin + pos, spmax + pos, out + pos, outsize + pos,
5134 svg_p, record_hdr, FALSE, a, i);
5137 /* Free remaining structures */
5138 free_graphs(out, outsize, spmin, spmax);
5143 ***************************************************************************
5144 * Display softnet statistics in SVG.
5147 * @a Activity structure with statistics.
5148 * @curr Index in array for current sample statistics.
5149 * @action Action expected from current function.
5150 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5151 * flag indicating that a restart record has been previously
5152 * found (.@restart) and time used for the X axis origin
5154 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5155 * @record_hdr Pointer on record header of current stats sample.
5156 ***************************************************************************
5158 #define SOFT_ARRAY_SZ 5
5159 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5160 unsigned long long itv, struct record_header *record_hdr)
5162 struct stats_softnet *ssnc, *ssnp, ssnczero;
5163 int group[] = {2, 3};
5164 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5165 char *title[] = {"Software-based network processing statistics (1)",
5166 "Software-based network processing statistics (2)"};
5167 char *g_title[] = {"total/s", "dropd/s",
5168 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5169 int g_fields[] = {0, 1, 2, 3, 4};
5170 static double *spmin, *spmax;
5172 static int *outsize;
5174 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5175 int i, pos, restart;
5177 if (action & F_BEGIN) {
5179 * Allocate arrays that will contain the graphs data
5180 * and the min/max values.
5182 out = allocate_graph_lines(SOFT_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
5185 if (action & F_MAIN) {
5186 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5188 /* @nr[curr] cannot normally be greater than @nr_ini */
5189 if (a->nr[curr] > a->nr_ini) {
5190 a->nr_ini = a->nr[curr];
5193 /* Compute statistics for CPU "all" */
5194 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5197 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5198 restart = svg_p->restart;
5200 /* Should current CPU (including CPU "all") be displayed? */
5201 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5205 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5206 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5208 /* Is current CPU marked offline? */
5209 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5211 * Yes and it doesn't follow a RESTART record.
5212 * To add a discontinuity in graph, we simulate
5216 if (svg_p->restart) {
5218 * CPU is offline and it follows a real
5219 * RESTART record. Ignore its current value
5220 * (no previous sample).
5225 pos = i * SOFT_ARRAY_SZ;
5227 /* Check for min/max values */
5228 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5229 itv, spmin + pos, spmax + pos, g_fields);
5232 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5233 S_VALUE(ssnp->processed, ssnc->processed, itv),
5234 out + pos, outsize + pos, restart);
5236 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5237 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5238 out + pos + 1, outsize + pos + 1, restart);
5240 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5241 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5242 out + pos + 2, outsize + pos + 2, restart);
5244 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5245 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5246 out + pos + 3, outsize + pos + 3, restart);
5248 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5249 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5250 out + pos + 4, outsize + pos + 4, restart);
5254 if (action & F_END) {
5255 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
5257 /* Should current CPU (including CPU "all") be displayed? */
5258 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5262 pos = i * SOFT_ARRAY_SZ;
5265 /* This is CPU "all" */
5266 strcpy(item_name, "all");
5269 sprintf(item_name, "%d", i - 1);
5272 draw_activity_graphs(a->g_nr, g_type,
5273 title, g_title, item_name, group,
5274 spmin + pos, spmax + pos, out + pos, outsize + pos,
5275 svg_p, record_hdr, FALSE, a, i);
5278 /* Free remaining structures */
5279 free_graphs(out, outsize, spmin, spmax);
5284 ***************************************************************************
5285 * Display pressure-stall CPU statistics in SVG.
5288 * @a Activity structure with statistics.
5289 * @curr Index in array for current sample statistics.
5290 * @action Action expected from current function.
5291 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5292 * flag indicating that a restart record has been previously
5293 * found (.@restart) and time used for the X axis origin
5295 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5296 * @record_hdr Pointer on record header of current stats sample.
5297 ***************************************************************************
5299 __print_funct_t svg_print_psicpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5300 unsigned long long itv, struct record_header *record_hdr)
5302 struct stats_psi_cpu
5303 *psic = (struct stats_psi_cpu *) a->buf[curr],
5304 *psip = (struct stats_psi_cpu *) a->buf[!curr];
5305 int group[] = {3, 1};
5306 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5307 char *title[] = {"CPU pressure trends (some tasks)", "CPU stall time (some tasks)"};
5308 char *g_title[] = {"%scpu-10", "%scpu-60", "%scpu-300",
5310 static double *spmin, *spmax;
5312 static int *outsize;
5315 if (action & F_BEGIN) {
5317 * Allocate arrays that will contain the graphs data
5318 * and the min/max values.
5320 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
5323 if (action & F_MAIN) {
5324 /* Check for min/max values */
5325 if (psic->some_acpu_10 > *spmax) {
5326 *spmax = psic->some_acpu_10;
5328 if (psic->some_acpu_10 < *spmin) {
5329 *spmin = psic->some_acpu_10;
5331 if (psic->some_acpu_60 > *(spmax + 1)) {
5332 *(spmax + 1) = psic->some_acpu_60;
5334 if (psic->some_acpu_60 < *(spmin + 1)) {
5335 *(spmin + 1) = psic->some_acpu_60;
5337 if (psic->some_acpu_300 > *(spmax + 2)) {
5338 *(spmax + 2) = psic->some_acpu_300;
5340 if (psic->some_acpu_300 < *(spmin + 2)) {
5341 *(spmin + 2) = psic->some_acpu_300;
5343 tval = ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv);
5344 if (tval > *(spmax + 3)) {
5345 *(spmax + 3) = tval;
5347 if (tval < *(spmin + 3)) {
5348 *(spmin + 3) = tval;
5352 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5353 (double) psic->some_acpu_10 / 100,
5354 out, outsize, svg_p->restart);
5356 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5357 (double) psic->some_acpu_60 / 100,
5358 out + 1, outsize + 1, svg_p->restart);
5360 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5361 (double) psic->some_acpu_300 / 100,
5362 out + 2, outsize + 2, svg_p->restart);
5364 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5366 ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv),
5367 out + 3, outsize + 3, svg_p->dt);
5370 if (action & F_END) {
5371 /* Fix min/max values for pressure ratios */
5372 *spmin /= 100; *spmax /= 100;
5373 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5374 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5376 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5377 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5379 /* Free remaining structures */
5380 free_graphs(out, outsize, spmin, spmax);
5385 ***************************************************************************
5386 * Display pressure-stall I/O statistics in SVG.
5389 * @a Activity structure with statistics.
5390 * @curr Index in array for current sample statistics.
5391 * @action Action expected from current function.
5392 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5393 * flag indicating that a restart record has been previously
5394 * found (.@restart) and time used for the X axis origin
5396 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5397 * @record_hdr Pointer on record header of current stats sample.
5398 ***************************************************************************
5400 __print_funct_t svg_print_psiio_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5401 unsigned long long itv, struct record_header *record_hdr)
5404 *psic = (struct stats_psi_io *) a->buf[curr],
5405 *psip = (struct stats_psi_io *) a->buf[!curr];
5406 int group[] = {3, 1, 3, 1};
5407 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5408 char *title[] = {"I/O pressure trends (some tasks)", "I/O stall time (some tasks)",
5409 "I/O pressure trends (full)", "I/O stall time (full)"};
5410 char *g_title[] = {"%sio-10", "%sio-60", "%sio-300",
5412 "%fio-10", "%fio-60", "%fio-300",
5414 static double *spmin, *spmax;
5416 static int *outsize;
5419 if (action & F_BEGIN) {
5421 * Allocate arrays that will contain the graphs data
5422 * and the min/max values.
5424 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5427 if (action & F_MAIN) {
5428 /* Check for min/max values */
5429 if (psic->some_aio_10 > *spmax) {
5430 *spmax = psic->some_aio_10;
5432 if (psic->some_aio_10 < *spmin) {
5433 *spmin = psic->some_aio_10;
5435 if (psic->some_aio_60 > *(spmax + 1)) {
5436 *(spmax + 1) = psic->some_aio_60;
5438 if (psic->some_aio_60 < *(spmin + 1)) {
5439 *(spmin + 1) = psic->some_aio_60;
5441 if (psic->some_aio_300 > *(spmax + 2)) {
5442 *(spmax + 2) = psic->some_aio_300;
5444 if (psic->some_aio_300 < *(spmin + 2)) {
5445 *(spmin + 2) = psic->some_aio_300;
5447 tval = ((double) psic->some_io_total - psip->some_io_total) / (100 * itv);
5448 if (tval > *(spmax + 3)) {
5449 *(spmax + 3) = tval;
5451 if (tval < *(spmin + 3)) {
5452 *(spmin + 3) = tval;
5455 if (psic->full_aio_10 > *(spmax + 4)) {
5456 *(spmax + 4) = psic->full_aio_10;
5458 if (psic->full_aio_10 < *(spmin + 4)) {
5459 *(spmin + 4) = psic->full_aio_10;
5461 if (psic->full_aio_60 > *(spmax + 5)) {
5462 *(spmax + 5) = psic->full_aio_60;
5464 if (psic->full_aio_60 < *(spmin + 5)) {
5465 *(spmin + 5) = psic->full_aio_60;
5467 if (psic->full_aio_300 > *(spmax + 6)) {
5468 *(spmax + 6) = psic->full_aio_300;
5470 if (psic->full_aio_300 < *(spmin + 6)) {
5471 *(spmin + 6) = psic->full_aio_300;
5473 tval = ((double) psic->full_io_total - psip->full_io_total) / (100 * itv);
5474 if (tval > *(spmax + 7)) {
5475 *(spmax + 7) = tval;
5477 if (tval < *(spmin + 7)) {
5478 *(spmin + 7) = tval;
5482 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5483 (double) psic->some_aio_10 / 100,
5484 out, outsize, svg_p->restart);
5486 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5487 (double) psic->some_aio_60 / 100,
5488 out + 1, outsize + 1, svg_p->restart);
5490 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5491 (double) psic->some_aio_300 / 100,
5492 out + 2, outsize + 2, svg_p->restart);
5494 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5496 ((double) psic->some_io_total - psip->some_io_total) / (100 * itv),
5497 out + 3, outsize + 3, svg_p->dt);
5500 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5501 (double) psic->full_aio_10 / 100,
5502 out + 4, outsize + 4, svg_p->restart);
5504 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5505 (double) psic->full_aio_60 / 100,
5506 out + 5, outsize + 5, svg_p->restart);
5508 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5509 (double) psic->full_aio_300 / 100,
5510 out + 6, outsize + 6, svg_p->restart);
5512 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5514 ((double) psic->full_io_total - psip->full_io_total) / (100 * itv),
5515 out + 7, outsize + 7, svg_p->dt);
5518 if (action & F_END) {
5519 /* Fix min/max values for pressure ratios */
5520 *spmin /= 100; *spmax /= 100;
5521 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5522 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5524 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5525 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5526 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5528 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5529 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5531 /* Free remaining structures */
5532 free_graphs(out, outsize, spmin, spmax);
5537 ***************************************************************************
5538 * Display pressure-stall memory statistics in SVG.
5541 * @a Activity structure with statistics.
5542 * @curr Index in array for current sample statistics.
5543 * @action Action expected from current function.
5544 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5545 * flag indicating that a restart record has been previously
5546 * found (.@restart) and time used for the X axis origin
5548 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5549 * @record_hdr Pointer on record header of current stats sample.
5550 ***************************************************************************
5552 __print_funct_t svg_print_psimem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5553 unsigned long long itv, struct record_header *record_hdr)
5555 struct stats_psi_mem
5556 *psic = (struct stats_psi_mem *) a->buf[curr],
5557 *psip = (struct stats_psi_mem *) a->buf[!curr];
5558 int group[] = {3, 1, 3, 1};
5559 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5560 char *title[] = {"Memory pressure trends (some tasks)", "Memory stall time (some tasks)",
5561 "Memory pressure trends (full)", "Memory stall time (full)"};
5562 char *g_title[] = {"%smem-10", "%smem-60", "%smem-300",
5564 "%fmem-10", "%fmem-60", "%fmem-300",
5566 static double *spmin, *spmax;
5568 static int *outsize;
5571 if (action & F_BEGIN) {
5573 * Allocate arrays that will contain the graphs data
5574 * and the min/max values.
5576 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5579 if (action & F_MAIN) {
5580 /* Check for min/max values */
5581 if (psic->some_amem_10 > *spmax) {
5582 *spmax = psic->some_amem_10;
5584 if (psic->some_amem_10 < *spmin) {
5585 *spmin = psic->some_amem_10;
5587 if (psic->some_amem_60 > *(spmax + 1)) {
5588 *(spmax + 1) = psic->some_amem_60;
5590 if (psic->some_amem_60 < *(spmin + 1)) {
5591 *(spmin + 1) = psic->some_amem_60;
5593 if (psic->some_amem_300 > *(spmax + 2)) {
5594 *(spmax + 2) = psic->some_amem_300;
5596 if (psic->some_amem_300 < *(spmin + 2)) {
5597 *(spmin + 2) = psic->some_amem_300;
5599 tval = ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv);
5600 if (tval > *(spmax + 3)) {
5601 *(spmax + 3) = tval;
5603 if (tval < *(spmin + 3)) {
5604 *(spmin + 3) = tval;
5607 if (psic->full_amem_10 > *(spmax + 4)) {
5608 *(spmax + 4) = psic->full_amem_10;
5610 if (psic->full_amem_10 < *(spmin + 4)) {
5611 *(spmin + 4) = psic->full_amem_10;
5613 if (psic->full_amem_60 > *(spmax + 5)) {
5614 *(spmax + 5) = psic->full_amem_60;
5616 if (psic->full_amem_60 < *(spmin + 5)) {
5617 *(spmin + 5) = psic->full_amem_60;
5619 if (psic->full_amem_300 > *(spmax + 6)) {
5620 *(spmax + 6) = psic->full_amem_300;
5622 if (psic->full_amem_300 < *(spmin + 6)) {
5623 *(spmin + 6) = psic->full_amem_300;
5625 tval = ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv);
5626 if (tval > *(spmax + 7)) {
5627 *(spmax + 7) = tval;
5629 if (tval < *(spmin + 7)) {
5630 *(spmin + 7) = tval;
5634 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5635 (double) psic->some_amem_10 / 100,
5636 out, outsize, svg_p->restart);
5638 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5639 (double) psic->some_amem_60 / 100,
5640 out + 1, outsize + 1, svg_p->restart);
5642 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5643 (double) psic->some_amem_300 / 100,
5644 out + 2, outsize + 2, svg_p->restart);
5646 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5648 ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv),
5649 out + 3, outsize + 3, svg_p->dt);
5652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5653 (double) psic->full_amem_10 / 100,
5654 out + 4, outsize + 4, svg_p->restart);
5656 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5657 (double) psic->full_amem_60 / 100,
5658 out + 5, outsize + 5, svg_p->restart);
5660 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5661 (double) psic->full_amem_300 / 100,
5662 out + 6, outsize + 6, svg_p->restart);
5664 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5666 ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv),
5667 out + 7, outsize + 7, svg_p->dt);
5670 if (action & F_END) {
5671 /* Fix min/max values for pressure ratios */
5672 *spmin /= 100; *spmax /= 100;
5673 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5674 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5676 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5677 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5678 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5680 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5681 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5683 /* Free remaining structures */
5684 free_graphs(out, outsize, spmin, spmax);