2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016-2020 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 containg the possible new min values for current activity.
90 * @spmax Array containg 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 sa_get_record_timestamp_struct(flags, &stamp, &rectime);
674 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
675 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
676 "stroke: #%06x\" transform=\"scale(%f,1)\"/>\n",
677 xpos * j, xpos * j, -SVG_G_YSIZE,
678 svg_colors[palette][SVG_COL_GRID_IDX],
681 * Display graduations.
682 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
683 * In this case, we should rather display the exact time instead of only the hour.
685 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
686 printf("<text x=\"%ld\" y=\"15\" style=\"fill: #%06x; stroke: none; font-size: 14px; "
687 "text-anchor: start\">%2d:00</text>\n",
688 (long) (xpos * j * xfactor) - 15,
689 svg_colors[palette][SVG_COL_AXIS_IDX],
693 printf("<text x=\"%ld\" y=\"10\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
694 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
695 (long) (xpos * j * xfactor),
696 svg_colors[palette][SVG_COL_AXIS_IDX],
697 (long) (xpos * j * xfactor), cur_time);
699 stamp.ust_time += xpos;
702 if (!PRINT_LOCAL_TIME(flags)) {
703 printf("<text x=\"-10\" y=\"30\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
704 "text-anchor: end\">UTC</text>\n",
705 svg_colors[palette][SVG_COL_INFO_IDX]);
710 ***************************************************************************
711 * Calculate the value on the Y axis between two horizontal lines that will
712 * make the graph background grid.
715 * @lmax Max value reached for this graph.
718 * @dp Number of decimal places for Y graduations.
721 * Value between two horizontal lines.
722 ***************************************************************************
724 double ygrid(double lmax, int *dp)
735 n = (long) (lmax / SVG_H_GRIDNR);
738 return (lmax / SVG_H_GRIDNR);
740 snprintf(val, 32, "%ld", n);
747 return ((double) (((long) (n / e)) * e));
751 ***************************************************************************
752 * Calculate the value on the X axis between two vertical lines that will
753 * make the graph background grid.
756 * @timestart First data timestamp (X coordinate of the first data point).
757 * @timeend Last data timestamp (X coordinate of the last data point).
758 * @v_gridnr Number of vertical lines to display. Its value is normally
759 * SVG_V_GRIDNR, except when option "oneday" is used, in which
760 * case it is set to 12.
763 * Value between two vertical lines.
764 ***************************************************************************
766 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
768 if ((timeend - timestart) <= v_gridnr)
771 return ((timeend - timestart) / v_gridnr);
775 ***************************************************************************
776 * Free global graphs structures.
779 * @out Pointer on array of chars for each graph definition.
780 * @outsize Size of array of chars for each graph definition.
781 * @spmin Array containing min values for graphs.
782 * @spmax Array containing max values for graphs.
783 ***************************************************************************
785 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
802 ***************************************************************************
803 * Skip current view where all graphs have only zero values. This function
804 * is called when option "skipempty" has been used, or when "No data" have
805 * been found for current view.
808 * @out Pointer on array of chars for each graph definition.
809 * @pos Position of current view in the array of graphs definitions.
810 * @group Number of graphs in current view.
813 * @pos Position of next view in the array of graphs definitions.
814 ***************************************************************************
816 void skip_current_view(char **out, int *pos, int group)
821 for (j = 0; j < group; j++) {
822 out_p = *(out + *pos + j);
824 /* Even if not displayed, current graph data have to be freed */
832 ***************************************************************************
833 * Display all graphs for current activity.
836 * @g_nr Number of views to display.
837 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
838 * @title Titles for each set of graphs.
839 * @g_title Titles for each graph.
840 * @item_name Item (network interface, etc.) name.
841 * @group Indicate how graphs are grouped together to make sets.
842 * @spmin Array containing min values for graphs.
843 * @spmax Array containing max values for graphs.
844 * @out Pointer on array of chars for each graph definition.
845 * @outsize Size of array of chars for each graph definition.
846 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
847 * time for the first sample of stats (.@ust_time_first), and
848 * times used as start and end values on the X axis
849 * (.@ust_time_ref and .@ust_time_end).
850 * @record_hdr Pointer on record header of current stats sample.
851 * @skip_void Set to <> 0 if graphs with no data should be skipped.
852 * This is typicallly used to not display CPU offline on the
854 * @a Current activity structure.
855 * @xid Current activity extra id number.
858 * TRUE if at least one graph has been displayed.
859 ***************************************************************************
861 int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
862 int group[], double *spmin, double *spmax, char **out, int *outsize,
863 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
864 struct activity *a, unsigned int xid)
867 int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE, palpos;
868 int v_gridnr, xv, yv;
869 unsigned int asfactor[16];
871 double lmax, xfactor, yfactor, ypos, gmin, gmax;
872 char val[32], cur_date[TIMESTAMP_LEN];
875 /* Print activity name in debug mode */
876 if (DISPLAY_DEBUG_MODE(flags)) {
877 printf("<!-- Name: %s -->\n", a->name);
880 /* For each view which is part of current activity */
881 for (i = 0; i < g_nr; i++) {
883 /* Print view number in debug mode */
884 if (DISPLAY_DEBUG_MODE(flags)) {
885 printf("<!-- View %d -->\n", i + 1);
888 /* Used as index in color palette */
889 palpos = (palette == SVG_BW_COL_PALETTE ? 0 : pos);
891 /* Get global min and max value for current view */
892 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
894 /* Don't display empty views if requested */
895 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
896 skip_current_view(out, &pos, group[i]);
899 /* Skip void graphs */
900 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
904 /* Translate to proper position for current activity */
905 printf("<g id=\"g%d-%d\" transform=\"translate(0,%d)\">\n",
908 SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
909 SVG_T_YSIZE * svg_p->graph_no);
913 /* Increment number of views actually displayed */
916 /* Compute top left position of view */
917 if (PACK_VIEWS(flags)) {
918 xv = (views_nr - 1) * SVG_T_XSIZE;
923 yv = (views_nr - 1) * SVG_T_YSIZE;
926 /* Graph background */
927 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\" fill=\"#%06x\"/>\n",
928 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE,
929 svg_colors[palette][SVG_COL_BCKGRD_IDX]);
932 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">%s",
934 svg_colors[palette][SVG_COL_TITLE_IDX],
937 printf(" [%s]", item_name);
940 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
941 "(Min, Max values)</tspan>\n</text>\n",
942 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25,
943 svg_colors[palette][SVG_COL_INFO_IDX]);
946 * At least two samples are needed.
947 * And a min and max value should have been found.
949 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
950 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
952 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">No data</text>\n",
953 xv, yv + SVG_M_YSIZE,
954 svg_colors[palette][SVG_COL_ERROR_IDX]);
955 skip_current_view(out, &pos, group[i]);
960 printf("<polyline points=\"%d,%d %d,%d %d,%d\" style=\"fill: #%06x; stroke: #%06x; stroke-width: 2\"/>\n",
961 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
962 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
963 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
964 svg_colors[palette][SVG_COL_BCKGRD_IDX],
965 svg_colors[palette][SVG_COL_AXIS_IDX]);
967 /* Autoscaling graphs if needed */
968 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
971 for (j = 0; j < group[i]; j++) {
972 /* Set dp to TRUE (1) if current metric is based on integer values */
973 dp = (g_title[pos + j][0] == '~');
974 snprintf(val, 32, "x%u ", asfactor[j]);
975 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
976 "%s %s(%.*f, %.*f)</text>\n",
977 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
978 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
979 asfactor[j] == 1 ? "" : val,
980 !dp * 2, *(spmin + pos + j) * asfactor[j],
981 !dp * 2, *(spmax + pos + j) * asfactor[j]);
984 if (DISPLAY_INFO(flags)) {
985 /* Display additional info (hostname, date) */
986 printf("<text x=\"%d\" y=\"%d\" "
987 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
989 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
990 svg_colors[palette][SVG_COL_INFO_IDX],
991 svg_p->file_hdr->sa_nodename);
993 /* Get report date */
994 set_report_date(localtime_r((const time_t *) &(svg_p->file_hdr->sa_ust_time), &rectime),
995 cur_date, sizeof(cur_date));
996 printf("<tspan x=\"%d\" y=\"%d\" "
997 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
998 "%s</tspan>\n</text>\n",
999 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
1000 svg_colors[palette][SVG_COL_INFO_IDX],
1004 /* Translate to proper position for current graph within current activity */
1005 printf("<g transform=\"translate(%d,%d)\">\n",
1006 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
1009 if (g_type[i] == SVG_LINE_GRAPH) {
1010 /* For line graphs */
1012 /* If all values are zero then set current max value to 1 */
1018 /* Max value cannot be too small, else Y graduations will be meaningless */
1019 if (lmax < SVG_H_GRIDNR * 0.01) {
1020 lmax = SVG_H_GRIDNR * 0.01;
1022 ypos = ygrid(lmax, &dp);
1025 /* For bar graphs (used for %values) */
1026 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
1027 dp = 0; /* No decimals */
1029 /* Max should be always 100% except for percentage values greater than 100% */
1037 yfactor = (double) -SVG_G_YSIZE / lmax;
1039 /* Display horizontal lines and graduations */
1040 display_hgrid(ypos, yfactor, lmax, dp);
1042 /* Set number of vertical lines to 12 when option "oneday" is used */
1043 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1045 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1046 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1048 /* Display vertical lines and graduations */
1049 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1051 /* Print marker in debug mode */
1052 if (DISPLAY_DEBUG_MODE(flags)) {
1053 printf("<!-- Graphs -->\n");
1056 /* Draw current graphs set */
1057 for (j = 0; j < group[i]; j++) {
1058 out_p = *(out + pos + j);
1059 if (g_type[i] == SVG_LINE_GRAPH) {
1061 printf("<path d=\"%s\" "
1062 "style=\"vector-effect: non-scaling-stroke; "
1063 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1064 "transform=\"scale(%f,%f)\"/>\n",
1066 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK],
1068 yfactor * asfactor[j]);
1070 else if (*out_p) { /* Ignore flat bars */
1072 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1073 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1074 printf("%s\n", out_p);
1085 /* For next row of views */
1086 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1093 ***************************************************************************
1094 * Display CPU statistics in SVG.
1097 * @a Activity structure with statistics.
1098 * @curr Index in array for current sample statistics.
1099 * @action Action expected from current function.
1100 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1101 * flag indicating that a restart record has been previously
1102 * found (.@restart), and time used for the X axis origin
1104 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1106 * @record_hdr Pointer on record header of current stats sample.
1107 ***************************************************************************
1109 #define CPU_ARRAY_SZ 10
1110 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1111 unsigned long long itv, struct record_header *record_hdr)
1113 struct stats_cpu *scc, *scp;
1114 unsigned long long deltot_jiffies = 1;
1115 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1118 int g_type[] = {SVG_BAR_GRAPH};
1119 char *title[] = {"CPU utilization"};
1120 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1121 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1122 static double *spmin, *spmax;
1124 static int *outsize;
1129 if (action & F_BEGIN) {
1131 * Allocate arrays that will contain the graphs data
1132 * and the min/max values.
1134 out = allocate_graph_lines(CPU_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
1137 if (action & F_MAIN) {
1139 /* @nr[curr] cannot normally be greater than @nr_ini */
1140 if (a->nr[curr] > a->nr_ini) {
1141 a->nr_ini = a->nr[curr];
1145 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1146 * and look for offline CPU.
1148 if (a->nr_ini > 1) {
1149 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1150 flags, offline_cpu_bitmap);
1154 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1156 /* Should current CPU (including CPU "all") be displayed? */
1157 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1158 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1159 /* Don't display CPU */
1162 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1163 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1165 pos = i * CPU_ARRAY_SZ;
1169 /* This is CPU "all" */
1170 if (a->nr_ini == 1) {
1172 * This is a UP machine. In this case
1173 * interval has still not been calculated.
1175 deltot_jiffies = get_per_cpu_interval(scc, scp);
1177 if (!deltot_jiffies) {
1178 /* CPU "all" cannot be tickless */
1184 * Recalculate interval for current proc.
1185 * If result is 0 then current CPU is a tickless one.
1187 deltot_jiffies = get_per_cpu_interval(scc, scp);
1189 if (!deltot_jiffies) { /* Current CPU is tickless */
1191 val = 100.0; /* Tickless CPU: %idle = 100% */
1193 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1196 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1200 /* Check min/max values for %user, etc. */
1201 for (k = 0; k < j; k++) {
1202 if (0.0 < *(spmin + pos + k)) {
1203 *(spmin + pos + k) = 0.0;
1205 if (0.0 > *(spmax + pos + k)) {
1206 *(spmax + pos + k) = 0.0;
1211 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1213 out + pos + j, outsize + pos + j, svg_p->dt,
1214 spmin + pos + j, spmax + pos + j);
1219 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1221 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1222 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1223 out + pos, outsize + pos, svg_p->dt,
1224 spmin + pos, spmax + pos);
1228 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1230 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1232 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1233 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1234 out + pos, outsize + pos, svg_p->dt,
1235 spmin + pos, spmax + pos);
1238 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1240 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1241 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1242 out + pos + 1, outsize + pos + 1, svg_p->dt,
1243 spmin + pos + 1, spmax + pos + 1);
1247 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1249 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1251 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1252 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1253 out + pos + 1, outsize + pos + 1, svg_p->dt,
1254 spmin + pos + 1, spmax + pos + 1);
1257 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1259 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1261 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1262 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1264 out + pos + 2, outsize + pos + 2, svg_p->dt,
1265 spmin + pos + 2, spmax + pos + 2);
1269 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1270 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1271 out + pos + 2, outsize + pos + 2, svg_p->dt,
1272 spmin + pos + 2, spmax + pos + 2);
1276 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1277 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1278 out + pos + 3, outsize + pos + 3, svg_p->dt,
1279 spmin + pos + 3, spmax + pos + 3);
1281 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1282 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1283 out + pos + 4, outsize + pos + 4, svg_p->dt,
1284 spmin + pos + 4, spmax + pos + 4);
1286 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1288 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1289 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1290 out + pos + 5, outsize + pos + 5, svg_p->dt,
1291 spmin + pos + 5, spmax + pos + 5);
1293 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1294 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1295 out + pos + 6, outsize + pos + 6, svg_p->dt,
1296 spmin + pos + 6, spmax + pos + 6);
1298 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1299 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1300 out + pos + 7, outsize + pos + 7, svg_p->dt,
1301 spmin + pos + 7, spmax + pos + 7);
1303 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1304 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1305 out + pos + 8, outsize + pos + 8, svg_p->dt,
1306 spmin + pos + 8, spmax + pos + 8);
1315 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1317 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1318 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1319 out + pos + j, outsize + pos + j, svg_p->dt,
1320 spmin + pos + j, spmax + pos + j);
1324 if (action & F_END) {
1325 int xid = 0, displayed;
1327 if (DISPLAY_IDLE(flags)) {
1328 /* Include additional %idle field */
1333 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
1335 /* Should current CPU (including CPU "all") be displayed? */
1336 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1340 pos = i * CPU_ARRAY_SZ;
1342 /* This is CPU "all" */
1343 strcpy(item_name, "all");
1346 sprintf(item_name, "%d", i - 1);
1349 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1350 displayed = draw_activity_graphs(a->g_nr, g_type,
1351 title, g_title1, item_name, group1,
1352 spmin + pos, spmax + pos, out + pos, outsize + pos,
1353 svg_p, record_hdr, i, a, xid);
1356 displayed = draw_activity_graphs(a->g_nr, g_type,
1357 title, g_title2, item_name, group2,
1358 spmin + pos, spmax + pos, out + pos, outsize + pos,
1359 svg_p, record_hdr, i, a, xid);
1366 /* Free remaining structures */
1367 free_graphs(out, outsize, spmin, spmax);
1372 ***************************************************************************
1373 * Display task creation and context switch statistics in SVG.
1376 * @a Activity structure with statistics.
1377 * @curr Index in array for current sample statistics.
1378 * @action Action expected from current function.
1379 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1380 * flag indicating that a restart record has been previously
1381 * found (.@restart) and time used for the X axis origin
1383 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1384 * @record_hdr Pointer on record header of current stats sample.
1385 ***************************************************************************
1387 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1388 unsigned long long itv, struct record_header *record_hdr)
1391 *spc = (struct stats_pcsw *) a->buf[curr],
1392 *spp = (struct stats_pcsw *) a->buf[!curr];
1393 int group[] = {1, 1};
1394 int g_fields[] = {1, 0};
1395 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1396 char *title[] = {"Task creation", "Switching activity"};
1397 char *g_title[] = {"proc/s",
1399 static double *spmin, *spmax;
1401 static int *outsize;
1403 if (action & F_BEGIN) {
1405 * Allocate arrays that will contain the graphs data
1406 * and the min/max values.
1408 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1411 if (action & F_MAIN) {
1412 /* Check for min/max values */
1413 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1414 itv, spmin, spmax, g_fields);
1416 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1417 S_VALUE(spp->processes, spc->processes, itv),
1418 out, outsize, svg_p->restart);
1420 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1421 S_VALUE(spp->context_switch, spc->context_switch, itv),
1422 out + 1, outsize + 1, svg_p->restart);
1425 if (action & F_END) {
1426 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1427 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1429 /* Free remaining structures */
1430 free_graphs(out, outsize, spmin, spmax);
1435 ***************************************************************************
1436 * Display swap statistics in SVG.
1439 * @a Activity structure with statistics.
1440 * @curr Index in array for current sample statistics.
1441 * @action Action expected from current function.
1442 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1443 * flag indicating that a restart record has been previously
1444 * found (.@restart) and time used for the X axis origin
1446 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1447 * @record_hdr Pointer on record header of current stats sample.
1448 ***************************************************************************
1450 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1451 unsigned long long itv, struct record_header *record_hdr)
1454 *ssc = (struct stats_swap *) a->buf[curr],
1455 *ssp = (struct stats_swap *) a->buf[!curr];
1457 int g_type[] = {SVG_LINE_GRAPH};
1458 char *title[] = {"Swap activity"};
1459 char *g_title[] = {"pswpin/s", "pswpout/s" };
1460 int g_fields[] = {0, 1};
1461 static double *spmin, *spmax;
1463 static int *outsize;
1465 if (action & F_BEGIN) {
1467 * Allocate arrays that will contain the graphs data
1468 * and the min/max values.
1470 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1473 if (action & F_MAIN) {
1474 /* Check for min/max values */
1475 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1476 itv, spmin, spmax, g_fields);
1478 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1479 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1480 out, outsize, svg_p->restart);
1482 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1483 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1484 out + 1, outsize + 1, svg_p->restart);
1487 if (action & F_END) {
1488 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1489 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1491 /* Free remaining structures */
1492 free_graphs(out, outsize, spmin, spmax);
1497 ***************************************************************************
1498 * Display paging statistics in SVG.
1501 * @a Activity structure with statistics.
1502 * @curr Index in array for current sample statistics.
1503 * @action Action expected from current function.
1504 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1505 * flag indicating that a restart record has been previously
1506 * found (.@restart) and time used for the X axis origin
1508 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1509 * @record_hdr Pointer on record header of current stats sample.
1510 ***************************************************************************
1512 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1513 unsigned long long itv, struct record_header *record_hdr)
1516 *spc = (struct stats_paging *) a->buf[curr],
1517 *spp = (struct stats_paging *) a->buf[!curr];
1518 int group[] = {2, 2, 4};
1519 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1520 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1521 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1522 "fault/s", "majflt/s",
1523 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1524 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1525 static double *spmin, *spmax;
1527 static int *outsize;
1529 if (action & F_BEGIN) {
1531 * Allocate arrays that will contain the graphs data
1532 * and the min/max values.
1534 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1537 if (action & F_MAIN) {
1538 /* Check for min/max values */
1539 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1540 itv, spmin, spmax, g_fields);
1542 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1543 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1544 out, outsize, svg_p->restart);
1546 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1547 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1548 out + 1, outsize + 1, svg_p->restart);
1550 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1551 S_VALUE(spp->pgfault, spc->pgfault, itv),
1552 out + 2, outsize + 2, svg_p->restart);
1554 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1555 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1556 out + 3, outsize + 3, svg_p->restart);
1558 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1559 S_VALUE(spp->pgfree, spc->pgfree, itv),
1560 out + 4, outsize + 4, svg_p->restart);
1562 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1563 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1564 out + 5, outsize + 5, svg_p->restart);
1566 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1567 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1568 out + 6, outsize + 6, svg_p->restart);
1570 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1571 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1572 out + 7, outsize + 7, svg_p->restart);
1575 if (action & F_END) {
1576 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1577 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1579 /* Free remaining structures */
1580 free_graphs(out, outsize, spmin, spmax);
1585 ***************************************************************************
1586 * Display I/O and transfer rate statistics in SVG.
1589 * @a Activity structure with statistics.
1590 * @curr Index in array for current sample statistics.
1591 * @action Action expected from current function.
1592 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1593 * flag indicating that a restart record has been previously
1594 * found (.@restart) and time used for the X axis origin
1596 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1597 * @record_hdr Pointer on record header of current stats sample.
1598 ***************************************************************************
1600 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1601 unsigned long long itv, struct record_header *record_hdr)
1604 *sic = (struct stats_io *) a->buf[curr],
1605 *sip = (struct stats_io *) a->buf[!curr];
1606 int group[] = {4, 3};
1607 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1608 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1609 char *g_title[] = {"tps", "rtps", "wtps", "dtps",
1610 "bread/s", "bwrtn/s", "bdscd/s"};
1612 * tps:0, rtps:1, wtps:2, dtps:3, bread/s:4, bwrtn/s:5, bdscd/s:6
1622 int g_fields[] = {0, 1, 2, 4, 5, 3, 6};
1623 static double *spmin, *spmax;
1625 static int *outsize;
1627 if (action & F_BEGIN) {
1629 * Allocate arrays that will contain the graphs data
1630 * and the min/max values.
1632 out = allocate_graph_lines(7, &outsize, &spmin, &spmax);
1635 if (action & F_MAIN) {
1636 /* Check for min/max values */
1637 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1638 itv, spmin, spmax, g_fields);
1641 * If we get negative values, this is probably because
1642 * one or more devices/filesystems have been unmounted.
1643 * We display 0.0 in this case though we should rather tell
1644 * the user that the value cannot be calculated here.
1647 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1648 sic->dk_drive < sip->dk_drive ? 0.0 :
1649 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1650 out, outsize, svg_p->restart);
1652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1653 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1654 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1655 out + 1, outsize + 1, svg_p->restart);
1657 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1658 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1659 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1660 out + 2, outsize + 2, svg_p->restart);
1662 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1663 sic->dk_drive_dio < sip->dk_drive_dio ? 0.0 :
1664 S_VALUE(sip->dk_drive_dio, sic->dk_drive_dio, itv),
1665 out + 3, outsize + 3, svg_p->restart);
1667 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1668 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1669 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1670 out + 4, outsize + 4, svg_p->restart);
1672 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1673 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1674 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1675 out + 5, outsize + 5, svg_p->restart);
1677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1678 sic->dk_drive_dblk < sip->dk_drive_dblk ? 0.0 :
1679 S_VALUE(sip->dk_drive_dblk, sic->dk_drive_dblk, itv),
1680 out + 6, outsize + 6, svg_p->restart);
1683 if (action & F_END) {
1684 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1685 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1687 /* Free remaining structures */
1688 free_graphs(out, outsize, spmin, spmax);
1693 ***************************************************************************
1694 * Display memory statistics in SVG.
1697 * @a Activity structure with statistics.
1698 * @curr Index in array for current sample statistics.
1699 * @action Action expected from current function.
1700 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1701 * flag indicating that a restart record has been previously
1702 * found (.@restart) and time used for the X axis origin
1704 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1705 * @record_hdr Pointer on record header of current stats sample.
1706 ***************************************************************************
1708 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1709 unsigned long long itv, struct record_header *record_hdr)
1712 *smc = (struct stats_memory *) a->buf[curr];
1713 int group1[] = {3, 1, 3, 1, 3, 5};
1714 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1715 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1716 int group2[] = {3, 1, 1};
1717 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1718 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1719 "Memory utilization (3)", "Memory utilization (4)",
1720 "Memory utilization (5)", "Memory utilization (6)"};
1721 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1722 "Swap utilization (3)"};
1723 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1724 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1725 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1727 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1729 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1730 static double *spmin, *spmax;
1732 static int *outsize;
1736 unsigned long long nousedmem;
1738 if (action & F_BEGIN) {
1740 * Allocate arrays that will contain the graphs data
1741 * and the min/max values.
1743 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1746 if (action & F_MAIN) {
1747 /* Check for min/max values */
1748 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1749 itv, spmin, spmax, g_fields);
1750 /* Compute %memused min/max values */
1751 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1752 if (nousedmem > smc->tlmkb) {
1753 nousedmem = smc->tlmkb;
1755 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1756 if (tval > *(spmax + 3)) {
1757 *(spmax + 3) = tval;
1759 if (tval < *(spmin + 3)) {
1760 *(spmin + 3) = tval;
1762 /* Compute %commit min/max values */
1763 tval = (smc->tlmkb + smc->tlskb) ?
1764 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1765 if (tval > *(spmax + 7)) {
1766 *(spmax + 7) = tval;
1768 if (tval < *(spmin + 7)) {
1769 *(spmin + 7) = tval;
1771 /* Compute %swpused min/max values */
1773 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1774 if (tval > *(spmax + 19)) {
1775 *(spmax + 19) = tval;
1777 if (tval < *(spmin + 19)) {
1778 *(spmin + 19) = tval;
1780 /* Compute %swpcad min/max values */
1781 tval = (smc->tlskb - smc->frskb) ?
1782 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1783 if (tval > *(spmax + 20)) {
1784 *(spmax + 20) = tval;
1786 if (tval < *(spmin + 20)) {
1787 *(spmin + 20) = tval;
1789 /* Compute memused min/max values in MB */
1790 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1791 if (tval > *(spmax + 2)) {
1792 *(spmax + 2) = tval;
1794 if (tval < *(spmin + 2)) {
1795 *(spmin + 2) = tval;
1797 /* Compute swpused min/max values in MB */
1798 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1799 if (tval > *(spmax + 17)) {
1800 *(spmax + 17) = tval;
1802 if (tval < *(spmin + 17)) {
1803 *(spmin + 17) = tval;
1807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1808 ((double) smc->frmkb) / 1024,
1809 out, outsize, svg_p->restart);
1811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1812 ((double) (smc->tlmkb - nousedmem)) / 1024,
1813 out + 2, outsize + 2, svg_p->restart);
1815 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1816 ((double) smc->availablekb) / 1024,
1817 out + 1, outsize + 1, svg_p->restart);
1819 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1820 ((double) smc->bufkb) / 1024,
1821 out + 4, outsize + 4, svg_p->restart);
1823 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1824 ((double) smc->camkb) / 1024,
1825 out + 5, outsize + 5, svg_p->restart);
1827 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1828 ((double) smc->frskb) / 1024,
1829 out + 16, outsize + 16, svg_p->restart);
1831 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1832 ((double) (smc->tlskb - smc->frskb)) / 1024,
1833 out + 17, outsize + 17, svg_p->restart);
1835 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1836 ((double) smc->caskb) / 1024,
1837 out + 18, outsize + 18, svg_p->restart);
1839 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1840 ((double) smc->comkb) / 1024,
1841 out + 6, outsize + 6, svg_p->restart);
1843 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1844 ((double) smc->activekb) / 1024,
1845 out + 8, outsize + 8, svg_p->restart);
1847 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1848 ((double) smc->inactkb) / 1024,
1849 out + 9, outsize + 9, svg_p->restart);
1851 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1852 ((double) smc->dirtykb) / 1024,
1853 out + 10, outsize + 10, svg_p->restart);
1855 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1856 ((double) smc->anonpgkb) / 1024,
1857 out + 11, outsize + 11, svg_p->restart);
1859 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1860 ((double) smc->slabkb) / 1024,
1861 out + 12, outsize + 12, svg_p->restart);
1863 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1864 ((double) smc->kstackkb) / 1024,
1865 out + 13, outsize + 13, svg_p->restart);
1867 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1868 ((double) smc->pgtblkb) / 1024,
1869 out + 14, outsize + 14, svg_p->restart);
1871 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1872 ((double) smc->vmusedkb) / 1024,
1873 out + 15, outsize + 15, svg_p->restart);
1875 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1878 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1879 out + 3, outsize + 3, svg_p->dt);
1881 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1883 (smc->tlmkb + smc->tlskb) ?
1884 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1885 out + 7, outsize + 7, svg_p->dt);
1887 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1890 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1891 out + 19, outsize + 19, svg_p->dt);
1893 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1895 (smc->tlskb - smc->frskb) ?
1896 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1897 out + 20, outsize + 20, svg_p->dt);
1900 if (action & F_END) {
1902 /* Conversion kB -> MB */
1903 for (i = 0; i < 17; i++) {
1904 *(spmin + g_fields[i]) /= 1024;
1905 *(spmax + g_fields[i]) /= 1024;
1908 if (DISPLAY_MEMORY(a->opt_flags)) {
1909 if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1910 g_type1, title1, g_title1, NULL, group1,
1911 spmin, spmax, out, outsize, svg_p, record_hdr,
1917 if (DISPLAY_SWAP(a->opt_flags)) {
1918 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1919 spmin + 16, spmax + 16, out + 16, outsize + 16,
1920 svg_p, record_hdr, FALSE, a, xid);
1923 /* Free remaining structures */
1924 free_graphs(out, outsize, spmin, spmax);
1929 ***************************************************************************
1930 * Display kernel tables statistics in SVG.
1933 * @a Activity structure with statistics.
1934 * @curr Index in array for current sample statistics.
1935 * @action Action expected from current function.
1936 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1937 * flag indicating that a restart record has been previously
1938 * found (.@restart) and time used for the X axis origin
1940 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1941 * @record_hdr Pointer on record header of current stats sample.
1942 ***************************************************************************
1944 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1945 unsigned long long itv, struct record_header *record_hdr)
1947 struct stats_ktables
1948 *skc = (struct stats_ktables *) a->buf[curr];
1949 int group[] = {3, 1};
1950 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1951 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1952 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1954 int g_fields[] = {1, 2, 0, 3};
1955 static double *spmin, *spmax;
1957 static int *outsize;
1959 if (action & F_BEGIN) {
1961 * Allocate arrays that will contain the graphs data
1962 * and the min/max values.
1964 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1967 if (action & F_MAIN) {
1968 /* Check for min/max values */
1969 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1970 itv, spmin, spmax, g_fields);
1972 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1973 (unsigned long long) skc->dentry_stat,
1974 out, outsize, svg_p->restart);
1976 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1977 (unsigned long long) skc->file_used,
1978 out + 1, outsize + 1, svg_p->restart);
1980 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1981 (unsigned long long) skc->inode_used,
1982 out + 2, outsize + 2, svg_p->restart);
1984 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1985 (unsigned long long) skc->pty_nr,
1986 out + 3, outsize + 3, svg_p->restart);
1989 if (action & F_END) {
1990 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1991 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1993 /* Free remaining structures */
1994 free_graphs(out, outsize, spmin, spmax);
1999 ***************************************************************************
2000 * Display queue and load statistics in SVG.
2003 * @a Activity structure with statistics.
2004 * @curr Index in array for current sample statistics.
2005 * @action Action expected from current function.
2006 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2007 * flag indicating that a restart record has been previously
2008 * found (.@restart) and time used for the X axis origin
2010 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2011 * @record_hdr Pointer on record header of current stats sample.
2012 ***************************************************************************
2014 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2015 unsigned long long itv, struct record_header *record_hdr)
2018 *sqc = (struct stats_queue *) a->buf[curr];
2019 int group[] = {2, 1, 3};
2020 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2021 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
2022 char *g_title[] = {"~runq-sz", "~blocked",
2024 "ldavg-1", "ldavg-5", "ldavg-15"};
2025 int g_fields[] = {0, 1, 2, 3, 4, 5};
2026 static double *spmin, *spmax;
2028 static int *outsize;
2030 if (action & F_BEGIN) {
2032 * Allocate arrays that will contain the graphs data
2033 * and the min/max values.
2035 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2038 if (action & F_MAIN) {
2039 /* Check for min/max values */
2040 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2041 itv, spmin, spmax, g_fields);
2043 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2044 (unsigned long long) sqc->nr_running,
2045 out, outsize, svg_p->restart);
2047 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2048 (unsigned long long) sqc->procs_blocked,
2049 out + 1, outsize + 1, svg_p->restart);
2051 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2052 (unsigned long long) sqc->nr_threads,
2053 out + 2, outsize + 2, svg_p->restart);
2055 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2056 (double) sqc->load_avg_1 / 100,
2057 out + 3, outsize + 3, svg_p->restart);
2059 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2060 (double) sqc->load_avg_5 / 100,
2061 out + 4, outsize + 4, svg_p->restart);
2063 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2064 (double) sqc->load_avg_15 / 100,
2065 out + 5, outsize + 5, svg_p->restart);
2068 if (action & F_END) {
2069 /* Fix min/max values for load average */
2070 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2071 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2072 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2074 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2075 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2077 /* Free remaining structures */
2078 free_graphs(out, outsize, spmin, spmax);
2083 ***************************************************************************
2084 * Display disk statistics in SVG.
2087 * @a Activity structure with statistics.
2088 * @curr Index in array for current sample statistics.
2089 * @action Action expected from current function.
2090 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2091 * flag indicating that a restart record has been previously
2092 * found (.@restart) and time used for the X axis origin
2094 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2095 * @record_hdr Pointer on record header of current stats sample.
2096 ***************************************************************************
2098 #define DISK_ARRAY_SZ 9
2099 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2100 unsigned long long itv, struct record_header *record_hdr)
2102 struct stats_disk *sdc, *sdp, sdpzero;
2103 struct ext_disk_stats xds;
2104 int group[] = {1, 3, 2, 1, 1};
2105 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2106 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2107 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2108 "Block devices statistics (3)", "Block devices statistics (4)",
2109 "Block devices statistics (5)"};
2110 char *g_title[] = {"tps",
2111 "rkB/s", "wkB/s", "dkB/s",
2112 "areq-sz", "aqu-sz",
2115 int g_fields[] = {0, 1, 2};
2116 unsigned int local_types_nr[] = {1, 0, 0};
2117 static double *spmin, *spmax;
2119 static int *outsize;
2120 char *dev_name, *item_name;
2121 double rkB, wkB, dkB, aqusz;
2122 int i, j, k, pos, restart, *unregistered;
2124 if (action & F_BEGIN) {
2126 * Allocate arrays (#0..7) that will contain the graphs data
2127 * and the min/max values.
2128 * Also allocate one additional array (#8) for each disk device:
2129 * out + 8 will contain the device name (WWN id, pretty name or devm-n),
2130 * outsize + 8 will contain a positive value (TRUE) if the device
2131 * has either still not been registered, or has been unregistered.
2133 out = allocate_graph_lines(DISK_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2136 if (action & F_MAIN) {
2137 memset(&sdpzero, 0, STATS_DISK_SIZE);
2139 * Mark previously registered devices as now
2140 * possibly unregistered for all graphs.
2142 for (k = 0; k < a->item_list_sz; k++) {
2143 unregistered = outsize + k * DISK_ARRAY_SZ + 8;
2144 if (*unregistered == FALSE) {
2145 *unregistered = MAYBE;
2149 /* For each device structure */
2150 for (i = 0; i < a->nr[curr]; i++) {
2151 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2152 restart = svg_p->restart;
2154 /* Get device name */
2155 dev_name = get_device_name(sdc->major, sdc->minor, sdc->wwn, sdc->part_nr,
2156 DISPLAY_PRETTY(flags), DISPLAY_PERSIST_NAME_S(flags),
2157 USE_STABLE_ID(flags), NULL);
2159 if (a->item_list != NULL) {
2160 /* A list of devices has been entered on the command line */
2161 if (!search_list_item(a->item_list, dev_name))
2162 /* Device not found */
2166 /* Look for corresponding graph */
2167 for (k = 0; k < a->item_list_sz; k++) {
2168 item_name = *(out + k * DISK_ARRAY_SZ + 8);
2169 if (!strcmp(dev_name, item_name))
2173 if (k == a->item_list_sz) {
2174 /* Graph not found: Look for first free entry */
2175 for (k = 0; k < a->item_list_sz; k++) {
2176 item_name = *(out + k * DISK_ARRAY_SZ + 8);
2177 if (!strcmp(item_name, ""))
2180 if (k == a->item_list_sz) {
2181 /* No free graph entry: Ignore it (should never happen) */
2183 fprintf(stderr, "%s: Name=%s major=%d minor=%d\n",
2184 __FUNCTION__, dev_name, sdc->major, sdc->minor);
2189 pos = k * DISK_ARRAY_SZ;
2190 unregistered = outsize + pos + 8;
2193 * If current device was marked as previously unregistered,
2194 * then set restart variable to TRUE so that the graph will be
2195 * discontinuous, and mark it as now registered.
2197 if (*unregistered == TRUE) {
2200 *unregistered = FALSE;
2202 item_name = *(out + pos + 8);
2203 if (!item_name[0]) {
2204 /* Save device name (WWN id or pretty name) if not already done */
2205 strncpy(item_name, dev_name, CHUNKSIZE);
2206 item_name[CHUNKSIZE - 1] = '\0';
2209 j = check_disk_reg(a, curr, !curr, i);
2211 /* This is a newly registered interface. Previous stats are zero */
2216 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2219 /* Check for min/max values */
2220 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2221 itv, spmin + pos, spmax + pos, g_fields);
2223 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2224 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2225 dkB = S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2;
2226 if (rkB < *(spmin + pos + 1)) {
2227 *(spmin + pos + 1) = rkB;
2229 if (rkB > *(spmax + pos + 1)) {
2230 *(spmax + pos + 1) = rkB;
2232 if (wkB < *(spmin + pos + 2)) {
2233 *(spmin + pos + 2) = wkB;
2235 if (wkB > *(spmax + pos + 2)) {
2236 *(spmax + pos + 2) = wkB;
2238 if (dkB < *(spmin + pos + 3)) {
2239 *(spmin + pos + 3) = dkB;
2241 if (dkB > *(spmax + pos + 3)) {
2242 *(spmax + pos + 3) = dkB;
2245 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2246 if ((xds.arqsz / 2) < *(spmin + pos + 4)) {
2247 *(spmin + pos + 4) = xds.arqsz / 2;
2249 if ((xds.arqsz / 2) > *(spmax + pos + 4)) {
2250 *(spmax + pos + 4) = xds.arqsz / 2;
2252 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2253 if (aqusz < *(spmin + pos + 5)) {
2254 *(spmin + pos + 5) = aqusz;
2256 if (aqusz > *(spmax + pos + 5)) {
2257 *(spmax + pos + 5) = aqusz;
2259 if (xds.await < *(spmin + pos + 6)) {
2260 *(spmin + pos + 6) = xds.await;
2262 if (xds.await > *(spmax + pos + 6)) {
2263 *(spmax + pos + 6) = xds.await;
2265 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2266 *(spmin + pos + 7) = xds.util / 10.0;
2268 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2269 *(spmax + pos + 7) = xds.util / 10.0;
2273 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2274 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2275 out + pos, outsize + pos, restart);
2277 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2278 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2279 out + pos + 1, outsize + pos + 1, restart);
2281 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2282 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2283 out + pos + 2, outsize + pos + 2, restart);
2285 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2286 S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2,
2287 out + pos + 3, outsize + pos + 3, restart);
2289 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2291 out + pos + 4, outsize + pos + 4, restart);
2293 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2295 out + pos + 5, outsize + pos + 5, restart);
2297 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2299 out + pos + 6, outsize + pos + 6, restart);
2301 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2302 0.0, xds.util / 10.0,
2303 out + pos + 7, outsize + pos + 7, svg_p->dt);
2306 /* Mark devices not seen here as now unregistered */
2307 for (k = 0; k < a->item_list_sz; k++) {
2308 unregistered = outsize + k * DISK_ARRAY_SZ + 8;
2309 if (*unregistered != FALSE) {
2310 *unregistered = TRUE;
2315 if (action & F_END) {
2318 for (i = 0; i < a->item_list_sz; i++) {
2319 /* Check if there is something to display */
2320 pos = i * DISK_ARRAY_SZ;
2324 item_name = *(out + pos + 8);
2325 if (draw_activity_graphs(a->g_nr, g_type,
2326 title, g_title, item_name, group,
2327 spmin + pos, spmax + pos, out + pos, outsize + pos,
2328 svg_p, record_hdr, FALSE, a, xid)) {
2333 /* Free remaining structures */
2334 free_graphs(out, outsize, spmin, spmax);
2339 ***************************************************************************
2340 * Display network interfaces statistics in SVG.
2343 * @a Activity structure with statistics.
2344 * @curr Index in array for current sample statistics.
2345 * @action Action expected from current function.
2346 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2347 * flag indicating that a restart record has been previously
2348 * found (.@restart) and time used for the X axis origin
2350 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2351 * @record_hdr Pointer on record header of current stats sample.
2352 ***************************************************************************
2354 #define NET_DEV_ARRAY_SZ 9
2355 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2356 unsigned long long itv, struct record_header *record_hdr)
2358 struct stats_net_dev *sndc, *sndp, sndzero;
2359 int group[] = {2, 2, 3, 1};
2360 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2362 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2363 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2364 char *g_title[] = {"rxpck/s", "txpck/s",
2366 "rxcmp/s", "txcmp/s", "rxmcst/s",
2368 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2369 unsigned int local_types_nr[] = {7, 0, 0};
2370 static double *spmin, *spmax;
2372 static int *outsize;
2374 double rxkb, txkb, ifutil;
2375 int i, j, k, pos, restart, *unregistered;
2377 if (action & F_BEGIN) {
2379 * Allocate arrays (#0..7) that will contain the graphs data
2380 * and the min/max values.
2381 * Also allocate one additional array (#8) for each interface:
2382 * out + 8 will contain the interface name,
2383 * outsize + 8 will contain a positive value (TRUE) if the interface
2384 * has either still not been registered, or has been unregistered.
2386 out = allocate_graph_lines(NET_DEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2389 if (action & F_MAIN) {
2390 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2392 * Mark previously registered interfaces as now
2393 * possibly unregistered for all graphs.
2395 for (k = 0; k < a->item_list_sz; k++) {
2396 unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
2397 if (*unregistered == FALSE) {
2398 *unregistered = MAYBE;
2402 /* For each network interfaces structure */
2403 for (i = 0; i < a->nr[curr]; i++) {
2404 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2405 restart = svg_p->restart;
2407 if (a->item_list != NULL) {
2408 /* A list of devices has been entered on the command line */
2409 if (!search_list_item(a->item_list, sndc->interface))
2410 /* Device not found */
2414 /* Look for corresponding graph */
2415 for (k = 0; k < a->item_list_sz; k++) {
2416 item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
2417 if (!strcmp(sndc->interface, item_name))
2421 if (k == a->item_list_sz) {
2422 /* Graph not found: Look for first free entry */
2423 for (k = 0; k < a->item_list_sz; k++) {
2424 item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
2425 if (!strcmp(item_name, ""))
2428 if (k == a->item_list_sz) {
2429 /* No free graph entry: Ignore it (should never happen) */
2431 fprintf(stderr, "%s: Name=%s\n",
2432 __FUNCTION__, sndc->interface);
2437 pos = k * NET_DEV_ARRAY_SZ;
2438 unregistered = outsize + pos + 8;
2440 j = check_net_dev_reg(a, curr, !curr, i);
2442 /* This is a newly registered interface. Previous stats are zero */
2447 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2451 * If current interface was marked as previously unregistered,
2452 * then set restart variable to TRUE so that the graph will be
2453 * discontinuous, and mark it as now registered.
2455 if (*unregistered == TRUE) {
2458 *unregistered = FALSE;
2460 item_name = *(out + pos + 8);
2461 if (!item_name[0]) {
2462 /* Save network interface name (if not already done) */
2463 strncpy(item_name, sndc->interface, CHUNKSIZE);
2464 item_name[CHUNKSIZE - 1] = '\0';
2467 /* Check for min/max values */
2468 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2469 itv, spmin + pos, spmax + pos, g_fields);
2471 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2472 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2473 ifutil = compute_ifutil(sndc, rxkb, txkb);
2474 if (ifutil < *(spmin + pos + 7)) {
2475 *(spmin + pos + 7) = ifutil;
2477 if (ifutil > *(spmax + pos + 7)) {
2478 *(spmax + pos + 7) = ifutil;
2482 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2483 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2484 out + pos, outsize + pos, restart);
2486 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2487 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2488 out + pos + 1, outsize + pos + 1, restart);
2490 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2492 out + pos + 2, outsize + pos + 2, restart);
2494 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2496 out + pos + 3, outsize + pos + 3, restart);
2498 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2499 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2500 out + pos + 4, outsize + pos + 4, restart);
2502 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2503 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2504 out + pos + 5, outsize + pos + 5, restart);
2506 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2507 S_VALUE(sndp->multicast, sndc->multicast, itv),
2508 out + pos + 6, outsize + pos + 6, restart);
2510 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2512 out + pos + 7, outsize + pos + 7, svg_p->dt);
2515 /* Mark interfaces not seen here as now unregistered */
2516 for (k = 0; k < a->item_list_sz; k++) {
2517 unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
2518 if (*unregistered != FALSE) {
2519 *unregistered = TRUE;
2524 if (action & F_END) {
2527 for (i = 0; i < a->item_list_sz; i++) {
2529 * Check if there is something to display.
2530 * Don't test sndc->interface because maybe the network
2531 * interface has been registered later.
2533 pos = i * NET_DEV_ARRAY_SZ;
2537 /* Recalculate min and max values in kB, not in B */
2538 *(spmin + pos + 2) /= 1024;
2539 *(spmax + pos + 2) /= 1024;
2540 *(spmin + pos + 3) /= 1024;
2541 *(spmax + pos + 3) /= 1024;
2543 item_name = *(out + pos + 8);
2544 if (draw_activity_graphs(a->g_nr, g_type,
2545 title, g_title, item_name, group,
2546 spmin + pos, spmax + pos, out + pos, outsize + pos,
2547 svg_p, record_hdr, FALSE, a, xid)) {
2552 /* Free remaining structures */
2553 free_graphs(out, outsize, spmin, spmax);
2558 ***************************************************************************
2559 * Display network interfaces errors statistics in SVG.
2562 * @a Activity structure with statistics.
2563 * @curr Index in array for current sample statistics.
2564 * @action Action expected from current function.
2565 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2566 * flag indicating that a restart record has been previously
2567 * found (.@restart) and time used for the X axis origin
2569 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2570 * @record_hdr Pointer on record header of current stats sample.
2571 ***************************************************************************
2573 #define NET_EDEV_ARRAY_SZ 10
2574 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2575 unsigned long long itv, struct record_header *record_hdr)
2577 struct stats_net_edev *snedc, *snedp, snedzero;
2578 int group[] = {2, 2, 2, 3};
2579 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2581 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2582 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2583 char *g_title[] = {"rxerr/s", "txerr/s",
2584 "rxdrop/s", "txdrop/s",
2585 "rxfifo/s", "txfifo/s",
2586 "coll/s", "txcarr/s", "rxfram/s"};
2587 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2588 static double *spmin, *spmax;
2590 static int *outsize;
2592 int i, j, k, pos, restart, *unregistered;
2594 if (action & F_BEGIN) {
2596 * Allocate arrays (#0..8) that will contain the graphs data
2597 * and the min/max values.
2598 * Also allocate one additional array (#9) for each interface:
2599 * out + 9 will contain the interface name,
2600 * outsize + 9 will contain a positive value (TRUE) if the interface
2601 * has either still not been registered, or has been unregistered.
2603 out = allocate_graph_lines(NET_EDEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2606 if (action & F_MAIN) {
2607 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2609 * Mark previously registered interfaces as now
2610 * possibly unregistered for all graphs.
2612 for (k = 0; k < a->item_list_sz; k++) {
2613 unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
2614 if (*unregistered == FALSE) {
2615 *unregistered = MAYBE;
2619 /* For each network interfaces structure */
2620 for (i = 0; i < a->nr[curr]; i++) {
2621 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2622 restart = svg_p->restart;
2624 if (a->item_list != NULL) {
2625 /* A list of devices has been entered on the command line */
2626 if (!search_list_item(a->item_list, snedc->interface))
2627 /* Device not found */
2631 /* Look for corresponding graph */
2632 for (k = 0; k < a->item_list_sz; k++) {
2633 item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
2634 if (!strcmp(snedc->interface, item_name))
2638 if (k == a->item_list_sz) {
2639 /* Graph not found: Look for first free entry */
2640 for (k = 0; k < a->item_list_sz; k++) {
2641 item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
2642 if (!strcmp(item_name, ""))
2645 if (k == a->item_list_sz) {
2646 /* No free graph entry: Ignore it (should never happen) */
2648 fprintf(stderr, "%s: Name=%s\n",
2649 __FUNCTION__, snedc->interface);
2655 pos = k * NET_EDEV_ARRAY_SZ;
2656 unregistered = outsize + pos + 9;
2658 j = check_net_edev_reg(a, curr, !curr, i);
2660 /* This is a newly registered interface. Previous stats are zero */
2665 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2669 * If current interface was marked as previously unregistered,
2670 * then set restart variable to TRUE so that the graph will be
2671 * discontinuous, and mark it as now registered.
2673 if (*unregistered == TRUE) {
2676 *unregistered = FALSE;
2678 item_name = *(out + pos + 9);
2679 if (!item_name[0]) {
2680 /* Save network interface name (if not already done) */
2681 strncpy(item_name, snedc->interface, CHUNKSIZE);
2682 item_name[CHUNKSIZE - 1] = '\0';
2685 /* Check for min/max values */
2686 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2687 itv, spmin + pos, spmax + pos, g_fields);
2690 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2691 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2692 out + pos, outsize + pos, restart);
2694 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2695 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2696 out + pos + 1, outsize + pos + 1, restart);
2698 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2699 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2700 out + pos + 2, outsize + pos + 2, restart);
2702 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2703 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2704 out + pos + 3, outsize + pos + 3, restart);
2706 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2707 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2708 out + pos + 4, outsize + pos + 4, restart);
2710 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2711 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2712 out + pos + 5, outsize + pos + 5, restart);
2714 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2715 S_VALUE(snedp->collisions, snedc->collisions, itv),
2716 out + pos + 6, outsize + pos + 6, restart);
2718 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2719 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2720 out + pos + 7, outsize + pos + 7, restart);
2722 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2723 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2724 out + pos + 8, outsize + pos + 8, restart);
2727 /* Mark interfaces not seen here as now unregistered */
2728 for (k = 0; k < a->item_list_sz; k++) {
2729 unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
2730 if (*unregistered != FALSE) {
2731 *unregistered = TRUE;
2736 if (action & F_END) {
2739 for (i = 0; i < a->item_list_sz; i++) {
2741 * Check if there is something to display.
2742 * Don't test snedc->interface because maybe the network
2743 * interface has been registered later.
2745 pos = i * NET_EDEV_ARRAY_SZ;
2749 item_name = *(out + pos + 9);
2750 if (draw_activity_graphs(a->g_nr, g_type,
2751 title, g_title, item_name, group,
2752 spmin + pos, spmax + pos, out + pos, outsize + pos,
2753 svg_p, record_hdr, FALSE, a, xid)) {
2758 /* Free remaining structures */
2759 free_graphs(out, outsize, spmin, spmax);
2764 ***************************************************************************
2765 * Display NFS client statistics in SVG.
2768 * @a Activity structure with statistics.
2769 * @curr Index in array for current sample statistics.
2770 * @action Action expected from current function.
2771 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2772 * flag indicating that a restart record has been previously
2773 * found (.@restart) and time used for the X axis origin
2775 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2776 * @record_hdr Pointer on record header of current stats sample.
2777 ***************************************************************************
2779 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2780 unsigned long long itv, struct record_header *record_hdr)
2782 struct stats_net_nfs
2783 *snnc = (struct stats_net_nfs *) a->buf[curr],
2784 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2785 int group[] = {2, 2, 2};
2786 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2787 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2788 "NFS client statistics (3)"};
2789 char *g_title[] = {"call/s", "retrans/s",
2790 "read/s", "write/s",
2791 "access/s", "getatt/s"};
2792 int g_fields[] = {0, 1, 2, 3, 4, 5};
2793 static double *spmin, *spmax;
2795 static int *outsize;
2797 if (action & F_BEGIN) {
2799 * Allocate arrays that will contain the graphs data
2800 * and the min/max values.
2802 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2805 if (action & F_MAIN) {
2806 /* Check for min/max values */
2807 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2808 itv, spmin, spmax, g_fields);
2811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2812 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2813 out, outsize, svg_p->restart);
2815 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2816 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2817 out + 1, outsize + 1, svg_p->restart);
2819 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2820 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2821 out + 2, outsize + 2, svg_p->restart);
2823 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2824 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2825 out + 3, outsize + 3, svg_p->restart);
2827 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2828 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2829 out + 4, outsize + 4, svg_p->restart);
2831 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2832 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2833 out + 5, outsize + 5, svg_p->restart);
2836 if (action & F_END) {
2837 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2838 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2840 /* Free remaining structures */
2841 free_graphs(out, outsize, spmin, spmax);
2846 ***************************************************************************
2847 * Display NFS server statistics in SVG.
2850 * @a Activity structure with statistics.
2851 * @curr Index in array for current sample statistics.
2852 * @action Action expected from current function.
2853 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2854 * flag indicating that a restart record has been previously
2855 * found (.@restart) and time used for the X axis origin
2857 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2858 * @record_hdr Pointer on record header of current stats sample.
2859 ***************************************************************************
2861 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2862 unsigned long long itv, struct record_header *record_hdr)
2864 struct stats_net_nfsd
2865 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2866 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2867 int group[] = {2, 3, 2, 2, 2};
2868 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2869 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2870 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2871 "NFS server statistics (3)", "NFS server statistics (4)",
2872 "NFS server statistics (5)"};
2873 char *g_title[] = {"scall/s", "badcall/s",
2874 "packet/s", "udp/s", "tcp/s",
2876 "sread/s", "swrite/s",
2877 "saccess/s", "sgetatt/s"};
2878 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2879 static double *spmin, *spmax;
2881 static int *outsize;
2883 if (action & F_BEGIN) {
2885 * Allocate arrays that will contain the graphs data
2886 * and the min/max values.
2888 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2891 if (action & F_MAIN) {
2892 /* Check for min/max values */
2893 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2894 itv, spmin, spmax, g_fields);
2897 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2898 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2899 out, outsize, svg_p->restart);
2901 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2902 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2903 out + 1, outsize + 1, svg_p->restart);
2905 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2906 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2907 out + 2, outsize + 2, svg_p->restart);
2909 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2910 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2911 out + 3, outsize + 3, svg_p->restart);
2913 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2914 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2915 out + 4, outsize + 4, svg_p->restart);
2917 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2918 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2919 out + 5, outsize + 5, svg_p->restart);
2921 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2922 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2923 out + 6, outsize + 6, svg_p->restart);
2925 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2926 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2927 out + 7, outsize + 7, svg_p->restart);
2929 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2930 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2931 out + 8, outsize + 8, svg_p->restart);
2933 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2934 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2935 out + 9, outsize + 9, svg_p->restart);
2937 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2938 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2939 out + 10, outsize + 10, svg_p->restart);
2942 if (action & F_END) {
2943 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2944 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2946 /* Free remaining structures */
2947 free_graphs(out, outsize, spmin, spmax);
2952 ***************************************************************************
2953 * Display socket statistics in SVG.
2956 * @a Activity structure with statistics.
2957 * @curr Index in array for current sample statistics.
2958 * @action Action expected from current function.
2959 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2960 * flag indicating that a restart record has been previously
2961 * found (.@restart) and time used for the X axis origin
2963 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2964 * @record_hdr Pointer on record header of current stats sample.
2965 ***************************************************************************
2967 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2968 unsigned long long itv, struct record_header *record_hdr)
2970 struct stats_net_sock
2971 *snsc = (struct stats_net_sock *) a->buf[curr];
2972 int group[] = {1, 5};
2973 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2974 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2975 char *g_title[] = {"~totsck",
2976 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2977 int g_fields[] = {0, 1, 5, 2, 3, 4};
2978 static double *spmin, *spmax;
2980 static int *outsize;
2982 if (action & F_BEGIN) {
2984 * Allocate arrays that will contain the graphs data
2985 * and the min/max values.
2987 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2990 if (action & F_MAIN) {
2991 /* Check for min/max values */
2992 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2993 itv, spmin, spmax, g_fields);
2995 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2996 (unsigned long long) snsc->sock_inuse,
2997 out, outsize, svg_p->restart);
2999 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3000 (unsigned long long) snsc->tcp_inuse,
3001 out + 1, outsize + 1, svg_p->restart);
3003 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3004 (unsigned long long) snsc->udp_inuse,
3005 out + 2, outsize + 2, svg_p->restart);
3007 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3008 (unsigned long long) snsc->raw_inuse,
3009 out + 3, outsize + 3, svg_p->restart);
3011 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3012 (unsigned long long) snsc->frag_inuse,
3013 out + 4, outsize + 4, svg_p->restart);
3015 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3016 (unsigned long long) snsc->tcp_tw,
3017 out + 5, outsize + 5, svg_p->restart);
3020 if (action & F_END) {
3021 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3022 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3024 /* Free remaining structures */
3025 free_graphs(out, outsize, spmin, spmax);
3030 ***************************************************************************
3031 * Display IPv4 traffic statistics in SVG.
3034 * @a Activity structure with statistics.
3035 * @curr Index in array for current sample statistics.
3036 * @action Action expected from current function.
3037 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3038 * flag indicating that a restart record has been previously
3039 * found (.@restart) and time used for the X axis origin
3041 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3042 * @record_hdr Pointer on record header of current stats sample.
3043 ***************************************************************************
3045 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3046 unsigned long long itv, struct record_header *record_hdr)
3049 *snic = (struct stats_net_ip *) a->buf[curr],
3050 *snip = (struct stats_net_ip *) a->buf[!curr];
3051 int group[] = {4, 2, 2};
3052 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3053 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
3054 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
3055 "asmrq/s", "asmok/s",
3056 "fragok/s", "fragcrt/s"};
3057 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3058 static double *spmin, *spmax;
3060 static int *outsize;
3062 if (action & F_BEGIN) {
3064 * Allocate arrays that will contain the graphs data
3065 * and the min/max values.
3067 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3070 if (action & F_MAIN) {
3071 /* Check for min/max values */
3072 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3073 itv, spmin, spmax, g_fields);
3076 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3077 S_VALUE(snip->InReceives, snic->InReceives, itv),
3078 out, outsize, svg_p->restart);
3080 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3081 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
3082 out + 1, outsize + 1, svg_p->restart);
3084 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3085 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
3086 out + 2, outsize + 2, svg_p->restart);
3088 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3089 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3090 out + 3, outsize + 3, svg_p->restart);
3092 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3093 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3094 out + 4, outsize + 4, svg_p->restart);
3096 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3097 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3098 out + 5, outsize + 5, svg_p->restart);
3100 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3101 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3102 out + 6, outsize + 6, svg_p->restart);
3104 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3105 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3106 out + 7, outsize + 7, svg_p->restart);
3109 if (action & F_END) {
3110 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3111 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3113 /* Free remaining structures */
3114 free_graphs(out, outsize, spmin, spmax);
3119 ***************************************************************************
3120 * Display IPv4 traffic errors statistics in SVG.
3123 * @a Activity structure with statistics.
3124 * @curr Index in array for current sample statistics.
3125 * @action Action expected from current function.
3126 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3127 * flag indicating that a restart record has been previously
3128 * found (.@restart) and time used for the X axis origin
3130 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3131 * @record_hdr Pointer on record header of current stats sample.
3132 ***************************************************************************
3134 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3135 unsigned long long itv, struct record_header *record_hdr)
3137 struct stats_net_eip
3138 *sneic = (struct stats_net_eip *) a->buf[curr],
3139 *sneip = (struct stats_net_eip *) a->buf[!curr];
3140 int group[] = {3, 2, 3};
3141 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3142 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3143 "IPv4 traffic errors statistics (3)"};
3144 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3145 "idisc/s", "odisc/s",
3146 "onort/s", "asmf/s", "fragf/s"};
3147 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3148 static double *spmin, *spmax;
3150 static int *outsize;
3152 if (action & F_BEGIN) {
3154 * Allocate arrays that will contain the graphs data
3155 * and the min/max values.
3157 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3160 if (action & F_MAIN) {
3161 /* Check for min/max values */
3162 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3163 itv, spmin, spmax, g_fields);
3166 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3167 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3168 out, outsize, svg_p->restart);
3170 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3171 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3172 out + 1, outsize + 1, svg_p->restart);
3174 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3175 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3176 out + 2, outsize + 2, svg_p->restart);
3178 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3179 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3180 out + 3, outsize + 3, svg_p->restart);
3182 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3183 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3184 out + 4, outsize + 4, svg_p->restart);
3186 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3187 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3188 out + 5, outsize + 5, svg_p->restart);
3190 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3191 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3192 out + 6, outsize + 6, svg_p->restart);
3194 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3195 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3196 out + 7, outsize + 7, svg_p->restart);
3199 if (action & F_END) {
3200 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3201 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3203 /* Free remaining structures */
3204 free_graphs(out, outsize, spmin, spmax);
3209 ***************************************************************************
3210 * Display ICMPv4 traffic statistics in SVG.
3213 * @a Activity structure with statistics.
3214 * @curr Index in array for current sample statistics.
3215 * @action Action expected from current function.
3216 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3217 * flag indicating that a restart record has been previously
3218 * found (.@restart) and time used for the X axis origin
3220 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3221 * @record_hdr Pointer on record header of current stats sample.
3222 ***************************************************************************
3224 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3225 unsigned long long itv, struct record_header *record_hdr)
3227 struct stats_net_icmp
3228 *snic = (struct stats_net_icmp *) a->buf[curr],
3229 *snip = (struct stats_net_icmp *) a->buf[!curr];
3230 int group[] = {2, 4, 4, 4};
3231 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3233 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3234 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3235 char *g_title[] = {"imsg/s", "omsg/s",
3236 "iech/s", "iechr/s", "oech/s", "oechr/s",
3237 "itm/s", "itmr/s", "otm/s", "otmr/s",
3238 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3239 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3240 static double *spmin, *spmax;
3242 static int *outsize;
3244 if (action & F_BEGIN) {
3246 * Allocate arrays that will contain the graphs data
3247 * and the min/max values.
3249 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3252 if (action & F_MAIN) {
3253 /* Check for min/max values */
3254 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3255 itv, spmin, spmax, g_fields);
3258 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3259 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3260 out, outsize, svg_p->restart);
3262 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3263 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3264 out + 1, outsize + 1, svg_p->restart);
3266 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3267 S_VALUE(snip->InEchos, snic->InEchos, itv),
3268 out + 2, outsize + 2, svg_p->restart);
3270 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3271 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3272 out + 3, outsize + 3, svg_p->restart);
3274 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3275 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3276 out + 4, outsize + 4, svg_p->restart);
3278 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3279 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3280 out + 5, outsize + 5, svg_p->restart);
3282 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3283 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3284 out + 6, outsize + 6, svg_p->restart);
3286 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3287 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3288 out + 7, outsize + 7, svg_p->restart);
3290 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3291 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3292 out + 8, outsize + 8, svg_p->restart);
3294 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3295 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3296 out + 9, outsize + 9, svg_p->restart);
3298 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3299 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3300 out + 10, outsize + 10, svg_p->restart);
3302 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3303 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3304 out + 11, outsize + 11, svg_p->restart);
3306 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3307 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3308 out + 12, outsize + 12, svg_p->restart);
3310 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3311 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3312 out + 13, outsize + 13, svg_p->restart);
3315 if (action & F_END) {
3316 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3317 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3319 /* Free remaining structures */
3320 free_graphs(out, outsize, spmin, spmax);
3325 ***************************************************************************
3326 * Display ICMPv4 traffic errors statistics in SVG.
3329 * @a Activity structure with statistics.
3330 * @curr Index in array for current sample statistics.
3331 * @action Action expected from current function.
3332 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3333 * flag indicating that a restart record has been previously
3334 * found (.@restart) and time used for the X axis origin
3336 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3337 * @record_hdr Pointer on record header of current stats sample.
3338 ***************************************************************************
3340 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3341 unsigned long long itv, struct record_header *record_hdr)
3343 struct stats_net_eicmp
3344 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3345 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3346 int group[] = {2, 2, 2, 2, 2, 2};
3347 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3348 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3349 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3350 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3351 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3352 char *g_title[] = {"ierr/s", "oerr/s",
3353 "idstunr/s", "odstunr/s",
3354 "itmex/s", "otmex/s",
3355 "iparmpb/s", "oparmpb/s",
3356 "isrcq/s", "osrcq/s",
3357 "iredir/s", "oredir/s"};
3358 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3359 static double *spmin, *spmax;
3361 static int *outsize;
3363 if (action & F_BEGIN) {
3365 * Allocate arrays that will contain the graphs data
3366 * and the min/max values.
3368 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3371 if (action & F_MAIN) {
3372 /* Check for min/max values */
3373 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3374 itv, spmin, spmax, g_fields);
3377 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3378 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3379 out, outsize, svg_p->restart);
3381 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3382 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3383 out + 1, outsize + 1, svg_p->restart);
3385 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3386 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3387 out + 2, outsize + 2, svg_p->restart);
3389 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3390 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3391 out + 3, outsize + 3, svg_p->restart);
3393 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3394 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3395 out + 4, outsize + 4, svg_p->restart);
3397 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3398 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3399 out + 5, outsize + 5, svg_p->restart);
3401 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3402 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3403 out + 6, outsize + 6, svg_p->restart);
3405 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3406 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3407 out + 7, outsize + 7, svg_p->restart);
3409 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3410 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3411 out + 8, outsize + 8, svg_p->restart);
3413 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3414 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3415 out + 9, outsize + 9, svg_p->restart);
3417 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3418 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3419 out + 10, outsize + 10, svg_p->restart);
3421 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3422 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3423 out + 11, outsize + 11, svg_p->restart);
3426 if (action & F_END) {
3427 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3428 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3430 /* Free remaining structures */
3431 free_graphs(out, outsize, spmin, spmax);
3436 ***************************************************************************
3437 * Display TCPv4 traffic statistics in SVG.
3440 * @a Activity structure with statistics.
3441 * @curr Index in array for current sample statistics.
3442 * @action Action expected from current function.
3443 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3444 * flag indicating that a restart record has been previously
3445 * found (.@restart) and time used for the X axis origin
3447 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3448 * @record_hdr Pointer on record header of current stats sample.
3449 ***************************************************************************
3451 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3452 unsigned long long itv, struct record_header *record_hdr)
3454 struct stats_net_tcp
3455 *sntc = (struct stats_net_tcp *) a->buf[curr],
3456 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3457 int group[] = {2, 2};
3458 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3459 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3460 char *g_title[] = {"active/s", "passive/s",
3461 "iseg/s", "oseg/s"};
3462 int g_fields[] = {0, 1, 2, 3};
3463 static double *spmin, *spmax;
3465 static int *outsize;
3467 if (action & F_BEGIN) {
3469 * Allocate arrays that will contain the graphs data
3470 * and the min/max values.
3472 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3475 if (action & F_MAIN) {
3476 /* Check for min/max values */
3477 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3478 itv, spmin, spmax, g_fields);
3481 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3482 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3483 out, outsize, svg_p->restart);
3485 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3486 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3487 out + 1, outsize + 1, svg_p->restart);
3489 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3490 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3491 out + 2, outsize + 2, svg_p->restart);
3493 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3494 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3495 out + 3, outsize + 3, svg_p->restart);
3498 if (action & F_END) {
3499 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3500 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3502 /* Free remaining structures */
3503 free_graphs(out, outsize, spmin, spmax);
3508 ***************************************************************************
3509 * Display TCPv4 traffic errors statistics in SVG.
3512 * @a Activity structure with statistics.
3513 * @curr Index in array for current sample statistics.
3514 * @action Action expected from current function.
3515 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3516 * flag indicating that a restart record has been previously
3517 * found (.@restart) and time used for the X axis origin
3519 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3520 * @record_hdr Pointer on record header of current stats sample.
3521 ***************************************************************************
3523 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3524 unsigned long long itv, struct record_header *record_hdr)
3526 struct stats_net_etcp
3527 *snetc = (struct stats_net_etcp *) a->buf[curr],
3528 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3529 int group[] = {2, 3};
3530 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3531 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3532 char *g_title[] = {"atmptf/s", "estres/s",
3533 "retrans/s", "isegerr/s", "orsts/s"};
3534 int g_fields[] = {0, 1, 2, 3, 4};
3535 static double *spmin, *spmax;
3537 static int *outsize;
3539 if (action & F_BEGIN) {
3541 * Allocate arrays that will contain the graphs data
3542 * and the min/max values.
3544 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3547 if (action & F_MAIN) {
3548 /* Check for min/max values */
3549 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3550 itv, spmin, spmax, g_fields);
3553 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3554 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3555 out, outsize, svg_p->restart);
3557 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3558 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3559 out + 1, outsize + 1, svg_p->restart);
3561 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3562 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3563 out + 2, outsize + 2, svg_p->restart);
3565 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3566 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3567 out + 3, outsize + 3, svg_p->restart);
3569 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3570 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3571 out + 4, outsize + 4, svg_p->restart);
3574 if (action & F_END) {
3575 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3576 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3578 /* Free remaining structures */
3579 free_graphs(out, outsize, spmin, spmax);
3584 ***************************************************************************
3585 * Display UDPv4 traffic statistics in SVG.
3588 * @a Activity structure with statistics.
3589 * @curr Index in array for current sample statistics.
3590 * @action Action expected from current function.
3591 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3592 * flag indicating that a restart record has been previously
3593 * found (.@restart) and time used for the X axis origin
3595 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3596 * @record_hdr Pointer on record header of current stats sample.
3597 ***************************************************************************
3599 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3600 unsigned long long itv, struct record_header *record_hdr)
3602 struct stats_net_udp
3603 *snuc = (struct stats_net_udp *) a->buf[curr],
3604 *snup = (struct stats_net_udp *) a->buf[!curr];
3605 int group[] = {2, 2};
3606 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3607 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3608 char *g_title[] = {"idgm/s", "odgm/s",
3609 "noport/s", "idgmerr/s"};
3610 int g_fields[] = {0, 1, 2, 3};
3611 static double *spmin, *spmax;
3613 static int *outsize;
3615 if (action & F_BEGIN) {
3617 * Allocate arrays that will contain the graphs data
3618 * and the min/max values.
3620 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3623 if (action & F_MAIN) {
3624 /* Check for min/max values */
3625 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3626 itv, spmin, spmax, g_fields);
3629 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3630 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3631 out, outsize, svg_p->restart);
3633 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3634 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3635 out + 1, outsize + 1, svg_p->restart);
3637 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3638 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3639 out + 2, outsize + 2, svg_p->restart);
3641 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3642 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3643 out + 3, outsize + 3, svg_p->restart);
3646 if (action & F_END) {
3647 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3648 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3650 /* Free remaining structures */
3651 free_graphs(out, outsize, spmin, spmax);
3656 ***************************************************************************
3657 * Display IPV6 socket statistics in SVG.
3660 * @a Activity structure with statistics.
3661 * @curr Index in array for current sample statistics.
3662 * @action Action expected from current function.
3663 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3664 * flag indicating that a restart record has been previously
3665 * found (.@restart) and time used for the X axis origin
3667 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3668 * @record_hdr Pointer on record header of current stats sample.
3669 ***************************************************************************
3671 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3672 unsigned long long itv, struct record_header *record_hdr)
3674 struct stats_net_sock6
3675 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3677 int g_type[] = {SVG_LINE_GRAPH};
3678 char *title[] = {"IPv6 sockets statistics"};
3679 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3680 int g_fields[] = {0, 1, 2, 3};
3681 static double *spmin, *spmax;
3683 static int *outsize;
3685 if (action & F_BEGIN) {
3687 * Allocate arrays that will contain the graphs data
3688 * and the min/max values.
3690 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3693 if (action & F_MAIN) {
3694 /* Check for min/max values */
3695 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3696 itv, spmin, spmax, g_fields);
3698 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3699 (unsigned long long) snsc->tcp6_inuse,
3700 out, outsize, svg_p->restart);
3702 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3703 (unsigned long long) snsc->udp6_inuse,
3704 out + 1, outsize + 1, svg_p->restart);
3706 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3707 (unsigned long long) snsc->raw6_inuse,
3708 out + 2, outsize + 2, svg_p->restart);
3710 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3711 (unsigned long long) snsc->frag6_inuse,
3712 out + 3, outsize + 3, svg_p->restart);
3715 if (action & F_END) {
3716 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3717 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3719 /* Free remaining structures */
3720 free_graphs(out, outsize, spmin, spmax);
3725 ***************************************************************************
3726 * Display IPv6 traffic statistics in SVG.
3729 * @a Activity structure with statistics.
3730 * @curr Index in array for current sample statistics.
3731 * @action Action expected from current function.
3732 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3733 * flag indicating that a restart record has been previously
3734 * found (.@restart) and time used for the X axis origin
3736 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3737 * @record_hdr Pointer on record header of current stats sample.
3738 ***************************************************************************
3740 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3741 unsigned long long itv, struct record_header *record_hdr)
3743 struct stats_net_ip6
3744 *snic = (struct stats_net_ip6 *) a->buf[curr],
3745 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3746 int group[] = {4, 2, 2, 2};
3747 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3749 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3750 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3751 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3752 "asmrq6/s", "asmok6/s",
3753 "imcpck6/s", "omcpck6/s",
3754 "fragok6/s", "fragcr6/s"};
3755 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3756 static double *spmin, *spmax;
3758 static int *outsize;
3760 if (action & F_BEGIN) {
3762 * Allocate arrays that will contain the graphs data
3763 * and the min/max values.
3765 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3768 if (action & F_MAIN) {
3769 /* Check for min/max values */
3770 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3771 itv, spmin, spmax, g_fields);
3774 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3775 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3776 out, outsize, svg_p->restart);
3778 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3779 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3780 out + 1, outsize + 1, svg_p->restart);
3782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3783 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3784 out + 2, outsize + 2, svg_p->restart);
3786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3787 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3788 out + 3, outsize + 3, svg_p->restart);
3790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3791 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3792 out + 4, outsize + 4, svg_p->restart);
3794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3795 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3796 out + 5, outsize + 5, svg_p->restart);
3798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3799 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3800 out + 6, outsize + 6, svg_p->restart);
3802 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3803 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3804 out + 7, outsize + 7, svg_p->restart);
3806 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3807 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3808 out + 8, outsize + 8, svg_p->restart);
3810 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3811 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3812 out + 9, outsize + 9, svg_p->restart);
3815 if (action & F_END) {
3816 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3817 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3819 /* Free remaining structures */
3820 free_graphs(out, outsize, spmin, spmax);
3825 ***************************************************************************
3826 * Display IPv6 traffic errors statistics in SVG.
3829 * @a Activity structure with statistics.
3830 * @curr Index in array for current sample statistics.
3831 * @action Action expected from current function.
3832 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3833 * flag indicating that a restart record has been previously
3834 * found (.@restart) and time used for the X axis origin
3836 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3837 * @record_hdr Pointer on record header of current stats sample.
3838 ***************************************************************************
3840 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3841 unsigned long long itv, struct record_header *record_hdr)
3843 struct stats_net_eip6
3844 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3845 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3846 int group[] = {4, 2, 2, 3};
3847 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3849 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3850 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3851 "IPv6 traffic errors statistics (5)"};
3852 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3853 "idisc6/s", "odisc6/s",
3854 "inort6/s", "onort6/s",
3855 "asmf6/s", "fragf6/s", "itrpck6/s"};
3856 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3857 static double *spmin, *spmax;
3859 static int *outsize;
3861 if (action & F_BEGIN) {
3863 * Allocate arrays that will contain the graphs data
3864 * and the min/max values.
3866 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3869 if (action & F_MAIN) {
3870 /* Check for min/max values */
3871 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3872 itv, spmin, spmax, g_fields);
3875 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3876 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3877 out, outsize, svg_p->restart);
3879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3880 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3881 out + 1, outsize + 1, svg_p->restart);
3883 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3884 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3885 out + 2, outsize + 2, svg_p->restart);
3887 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3888 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3889 out + 3, outsize + 3, svg_p->restart);
3891 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3892 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3893 out + 4, outsize + 4, svg_p->restart);
3895 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3896 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3897 out + 5, outsize + 5, svg_p->restart);
3899 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3900 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3901 out + 6, outsize + 6, svg_p->restart);
3903 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3904 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3905 out + 7, outsize + 7, svg_p->restart);
3907 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3908 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3909 out + 8, outsize + 8, svg_p->restart);
3911 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3912 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3913 out + 9, outsize + 9, svg_p->restart);
3915 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3916 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3917 out + 10, outsize + 10, svg_p->restart);
3920 if (action & F_END) {
3921 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3922 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3924 /* Free remaining structures */
3925 free_graphs(out, outsize, spmin, spmax);
3930 ***************************************************************************
3931 * Display ICMPv6 traffic statistics in SVG.
3934 * @a Activity structure with statistics.
3935 * @curr Index in array for current sample statistics.
3936 * @action Action expected from current function.
3937 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3938 * flag indicating that a restart record has been previously
3939 * found (.@restart) and time used for the X axis origin
3941 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3942 * @record_hdr Pointer on record header of current stats sample.
3943 ***************************************************************************
3945 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3946 unsigned long long itv, struct record_header *record_hdr)
3948 struct stats_net_icmp6
3949 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3950 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3951 int group[] = {2, 3, 5, 3, 4};
3952 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3953 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3954 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3955 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3956 "ICMPv6 traffic statistics (5)"};
3957 char *g_title[] = {"imsg6/s", "omsg6/s",
3958 "iech6/s", "iechr6/s", "oechr6/s",
3959 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3960 "irtsol6/s", "ortsol6/s", "irtad6/s",
3961 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3962 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3963 static double *spmin, *spmax;
3965 static int *outsize;
3967 if (action & F_BEGIN) {
3969 * Allocate arrays that will contain the graphs data
3970 * and the min/max values.
3972 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3975 if (action & F_MAIN) {
3976 /* Check for min/max values */
3977 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3978 itv, spmin, spmax, g_fields);
3981 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3982 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3983 out, outsize, svg_p->restart);
3985 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3986 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3987 out + 1, outsize + 1, svg_p->restart);
3989 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3990 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3991 out + 2, outsize + 2, svg_p->restart);
3993 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3994 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3995 out + 3, outsize + 3, svg_p->restart);
3997 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3998 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3999 out + 4, outsize + 4, svg_p->restart);
4001 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4002 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
4003 out + 5, outsize + 5, svg_p->restart);
4005 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4006 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
4007 out + 6, outsize + 6, svg_p->restart);
4009 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4010 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
4011 out + 7, outsize + 7, svg_p->restart);
4013 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4014 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
4015 out + 8, outsize + 8, svg_p->restart);
4017 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4018 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
4019 out + 9, outsize + 9, svg_p->restart);
4021 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4022 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
4023 out + 10, outsize + 10, svg_p->restart);
4025 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4026 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
4027 out + 11, outsize + 11, svg_p->restart);
4029 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4030 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
4031 out + 12, outsize + 12, svg_p->restart);
4033 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4034 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
4035 out + 13, outsize + 13, svg_p->restart);
4037 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4038 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
4039 out + 14, outsize + 14, svg_p->restart);
4041 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4042 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
4043 out + 15, outsize + 15, svg_p->restart);
4045 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4046 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
4047 out + 16, outsize + 16, svg_p->restart);
4050 if (action & F_END) {
4051 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4052 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4054 /* Free remaining structures */
4055 free_graphs(out, outsize, spmin, spmax);
4060 ***************************************************************************
4061 * Display ICMPv6 traffic errors statistics in SVG.
4064 * @a Activity structure with statistics.
4065 * @curr Index in array for current sample statistics.
4066 * @action Action expected from current function.
4067 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4068 * flag indicating that a restart record has been previously
4069 * found (.@restart) and time used for the X axis origin
4071 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4072 * @record_hdr Pointer on record header of current stats sample.
4073 ***************************************************************************
4075 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4076 unsigned long long itv, struct record_header *record_hdr)
4078 struct stats_net_eicmp6
4079 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
4080 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
4081 int group[] = {1, 2, 2, 2, 2, 2};
4082 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4083 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4084 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
4085 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
4086 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
4087 char *g_title[] = {"ierr6/s",
4088 "idtunr6/s", "odtunr6/s",
4089 "itmex6/s", "otmex6/s",
4090 "iprmpb6/s", "oprmpb6/s",
4091 "iredir6/s", "oredir6/s",
4092 "ipck2b6/s", "opck2b6/s"};
4093 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4094 static double *spmin, *spmax;
4096 static int *outsize;
4098 if (action & F_BEGIN) {
4100 * Allocate arrays that will contain the graphs data
4101 * and the min/max values.
4103 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4106 if (action & F_MAIN) {
4107 /* Check for min/max values */
4108 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4109 itv, spmin, spmax, g_fields);
4112 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4113 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4114 out, outsize, svg_p->restart);
4116 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4117 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4118 out + 1, outsize + 1, svg_p->restart);
4120 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4121 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4122 out + 2, outsize + 2, svg_p->restart);
4124 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4125 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4126 out + 3, outsize + 3, svg_p->restart);
4128 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4129 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4130 out + 4, outsize + 4, svg_p->restart);
4132 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4133 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4134 out + 5, outsize + 5, svg_p->restart);
4136 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4137 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4138 out + 6, outsize + 6, svg_p->restart);
4140 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4141 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4142 out + 7, outsize + 7, svg_p->restart);
4144 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4145 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4146 out + 8, outsize + 8, svg_p->restart);
4148 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4149 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4150 out + 9, outsize + 9, svg_p->restart);
4152 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4153 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4154 out + 10, outsize + 10, svg_p->restart);
4157 if (action & F_END) {
4158 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4159 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4161 /* Free remaining structures */
4162 free_graphs(out, outsize, spmin, spmax);
4167 ***************************************************************************
4168 * Display UDPv6 traffic statistics in SVG.
4171 * @a Activity structure with statistics.
4172 * @curr Index in array for current sample statistics.
4173 * @action Action expected from current function.
4174 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4175 * flag indicating that a restart record has been previously
4176 * found (.@restart) and time used for the X axis origin
4178 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4179 * @record_hdr Pointer on record header of current stats sample.
4180 ***************************************************************************
4182 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4183 unsigned long long itv, struct record_header *record_hdr)
4185 struct stats_net_udp6
4186 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4187 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4188 int group[] = {2, 2};
4189 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4190 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4191 char *g_title[] = {"idgm6/s", "odgm6/s",
4192 "noport6/s", "idgmer6/s"};
4193 int g_fields[] = {0, 1, 2, 3};
4194 static double *spmin, *spmax;
4196 static int *outsize;
4198 if (action & F_BEGIN) {
4200 * Allocate arrays that will contain the graphs data
4201 * and the min/max values.
4203 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4206 if (action & F_MAIN) {
4207 /* Check for min/max values */
4208 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4209 itv, spmin, spmax, g_fields);
4212 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4213 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4214 out, outsize, svg_p->restart);
4216 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4217 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4218 out + 1, outsize + 1, svg_p->restart);
4220 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4221 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4222 out + 2, outsize + 2, svg_p->restart);
4224 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4225 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4226 out + 3, outsize + 3, svg_p->restart);
4229 if (action & F_END) {
4230 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4231 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4233 /* Free remaining structures */
4234 free_graphs(out, outsize, spmin, spmax);
4239 ***************************************************************************
4240 * Display CPU frequency statistics in SVG.
4243 * @a Activity structure with statistics.
4244 * @curr Index in array for current sample statistics.
4245 * @action Action expected from current function.
4246 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4247 * flag indicating that a restart record has been previously
4248 * found (.@restart) and time used for the X axis origin
4250 * @itv Interval of time in 1/100th of a second (unused here).
4251 * @record_hdr Pointer on record header of current stats sample.
4252 ***************************************************************************
4254 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4255 unsigned long long itv, struct record_header *record_hdr)
4257 struct stats_pwr_cpufreq *spc, *spp;
4259 int g_type[] = {SVG_LINE_GRAPH};
4260 char *title[] = {"CPU clock frequency"};
4261 char *g_title[] = {"MHz"};
4262 static double *spmin, *spmax;
4264 static int *outsize;
4268 if (action & F_BEGIN) {
4270 * Allocate arrays that will contain the graphs data
4271 * and the min/max values.
4273 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4276 if (action & F_MAIN) {
4278 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4280 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4281 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4283 /* Should current CPU (including CPU "all") be displayed? */
4284 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4289 * Note: Don't skip offline CPU here as it is needed
4290 * to make the graph go though 0.
4294 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4295 ((double) spp->cpufreq) / 100,
4296 ((double) spc->cpufreq) / 100,
4297 out + i, outsize + i, svg_p->restart, svg_p->dt,
4298 spmin + i, spmax + i);
4302 if (action & F_END) {
4305 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
4307 /* Should current CPU (including CPU "all") be displayed? */
4308 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4313 /* This is CPU "all" */
4314 strcpy(item_name, "all");
4318 * If the maximum frequency reached by the CPU is 0, then
4319 * the CPU has been offline on the whole period.
4320 * => Don't display it.
4322 if (*(spmax + i) == 0)
4325 sprintf(item_name, "%d", i - 1);
4328 if (draw_activity_graphs(a->g_nr, g_type,
4329 title, g_title, item_name, group,
4330 spmin + i, spmax + i, out + i, outsize + i,
4331 svg_p, record_hdr, i, a, xid)) {
4336 /* Free remaining structures */
4337 free_graphs(out, outsize, spmin, spmax);
4342 ***************************************************************************
4343 * Display fan statistics in SVG.
4346 * @a Activity structure with statistics.
4347 * @curr Index in array for current sample statistics.
4348 * @action Action expected from current function.
4349 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4350 * flag indicating that a restart record has been previously
4351 * found (.@restart) and time used for the X axis origin
4353 * @itv Interval of time in 1/100th of a second (unused here).
4354 * @record_hdr Pointer on record header of current stats sample.
4355 ***************************************************************************
4357 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4358 unsigned long long itv, struct record_header *record_hdr)
4360 struct stats_pwr_fan *spc, *spp;
4362 int g_type[] = {SVG_LINE_GRAPH};
4363 char *title[] = {"Fans speed"};
4364 char *g_title[] = {"~rpm"};
4365 static double *spmin, *spmax;
4367 static int *outsize;
4368 char item_name[MAX_SENSORS_DEV_LEN + 16];
4371 if (action & F_BEGIN) {
4373 * Allocate arrays that will contain the graphs data
4374 * and the min/max values.
4376 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4379 if (action & F_MAIN) {
4381 for (i = 0; i < a->nr[curr]; i++) {
4383 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4384 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4387 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4390 out + i, outsize + i, svg_p->restart, svg_p->dt,
4391 spmin + i, spmax + i);
4395 if (action & F_END) {
4398 for (i = 0; i < a->item_list_sz; i++) {
4400 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4402 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4403 item_name[sizeof(item_name) - 1] = '\0';
4405 if (draw_activity_graphs(a->g_nr, g_type,
4406 title, g_title, item_name, group,
4407 spmin + i, spmax + i, out + i, outsize + i,
4408 svg_p, record_hdr, FALSE, a, xid)) {
4413 /* Free remaining structures */
4414 free_graphs(out, outsize, spmin, spmax);
4419 ***************************************************************************
4420 * Display temperature statistics in SVG.
4423 * @a Activity structure with statistics.
4424 * @curr Index in array for current sample statistics.
4425 * @action Action expected from current function.
4426 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4427 * flag indicating that a restart record has been previously
4428 * found (.@restart) and time used for the X axis origin
4430 * @itv Interval of time in 1/100th of a second (unused here).
4431 * @record_hdr Pointer on record header of current stats sample.
4432 ***************************************************************************
4434 #define TEMP_ARRAY_SZ 2
4435 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4436 unsigned long long itv, struct record_header *record_hdr)
4438 struct stats_pwr_temp *spc;
4439 int group[] = {1, 1};
4440 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4441 char *title[] = {"Devices temperature (1)",
4442 "Devices temperature (2)"};
4443 char *g_title[] = {"~degC",
4445 static double *spmin, *spmax;
4447 static int *outsize;
4448 char item_name[MAX_SENSORS_DEV_LEN + 16];
4452 if (action & F_BEGIN) {
4454 * Allocate arrays that will contain the graphs data
4455 * and the min/max values.
4457 out = allocate_graph_lines(TEMP_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4460 if (action & F_MAIN) {
4461 /* For each temperature sensor */
4462 for (i = 0; i < a->nr[curr]; i++) {
4464 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4466 /* Look for min/max values */
4467 if (spc->temp < *(spmin + TEMP_ARRAY_SZ * i)) {
4468 *(spmin + TEMP_ARRAY_SZ * i) = spc->temp;
4470 if (spc->temp > *(spmax + TEMP_ARRAY_SZ * i)) {
4471 *(spmax + TEMP_ARRAY_SZ * i) = spc->temp;
4473 tval = (spc->temp_max - spc->temp_min) ?
4474 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4476 if (tval < *(spmin + TEMP_ARRAY_SZ * i + 1)) {
4477 *(spmin + TEMP_ARRAY_SZ * i + 1) = tval;
4479 if (tval > *(spmax + TEMP_ARRAY_SZ * i + 1)) {
4480 *(spmax + TEMP_ARRAY_SZ * i + 1) = tval;
4484 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4486 out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i, svg_p->restart);
4488 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4490 out + TEMP_ARRAY_SZ * i + 1, outsize + TEMP_ARRAY_SZ * i + 1, svg_p->dt);
4494 if (action & F_END) {
4497 for (i = 0; i < a->item_list_sz; i++) {
4499 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4501 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4502 item_name[sizeof(item_name) - 1] = '\0';
4504 if (draw_activity_graphs(a->g_nr, g_type,
4505 title, g_title, item_name, group,
4506 spmin + TEMP_ARRAY_SZ * i, spmax + TEMP_ARRAY_SZ * i,
4507 out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i,
4508 svg_p, record_hdr, FALSE, a, xid)) {
4513 /* Free remaining structures */
4514 free_graphs(out, outsize, spmin, spmax);
4519 ***************************************************************************
4520 * Display voltage inputs statistics in SVG.
4523 * @a Activity structure with statistics.
4524 * @curr Index in array for current sample statistics.
4525 * @action Action expected from current function.
4526 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4527 * flag indicating that a restart record has been previously
4528 * found (.@restart) and time used for the X axis origin
4530 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4531 * @record_hdr Pointer on record header of current stats sample.
4532 ***************************************************************************
4534 #define IN_ARRAY_SZ 2
4535 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4536 unsigned long long itv, struct record_header *record_hdr)
4538 struct stats_pwr_in *spc;
4539 int group[] = {1, 1};
4540 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4541 char *title[] = {"Voltage inputs statistics (1)",
4542 "Voltage inputs statistics (2)"};
4543 char *g_title[] = {"inV",
4545 static double *spmin, *spmax;
4547 static int *outsize;
4548 char item_name[MAX_SENSORS_DEV_LEN + 16];
4552 if (action & F_BEGIN) {
4554 * Allocate arrays that will contain the graphs data
4555 * and the min/max values.
4557 out = allocate_graph_lines(IN_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4560 if (action & F_MAIN) {
4561 /* For each voltage input sensor */
4562 for (i = 0; i < a->nr[curr]; i++) {
4564 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4566 /* Look for min/max values */
4567 if (spc->in < *(spmin + IN_ARRAY_SZ * i)) {
4568 *(spmin + IN_ARRAY_SZ * i) = spc->in;
4570 if (spc->in > *(spmax + IN_ARRAY_SZ * i)) {
4571 *(spmax + IN_ARRAY_SZ * i) = spc->in;
4573 tval = (spc->in_max - spc->in_min) ?
4574 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4576 if (tval < *(spmin + IN_ARRAY_SZ * i + 1)) {
4577 *(spmin + IN_ARRAY_SZ * i + 1) = tval;
4579 if (tval > *(spmax + IN_ARRAY_SZ * i + 1)) {
4580 *(spmax + IN_ARRAY_SZ * i + 1) = tval;
4584 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4586 out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i, svg_p->restart);
4588 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4590 out + IN_ARRAY_SZ * i + 1, outsize + IN_ARRAY_SZ * i + 1, svg_p->dt);
4594 if (action & F_END) {
4597 for (i = 0; i < a->item_list_sz; i++) {
4599 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4601 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4602 item_name[sizeof(item_name) - 1] = '\0';
4604 if (draw_activity_graphs(a->g_nr, g_type,
4605 title, g_title, item_name, group,
4606 spmin + IN_ARRAY_SZ * i, spmax + IN_ARRAY_SZ * i,
4607 out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i,
4608 svg_p, record_hdr, FALSE, a, xid)) {
4613 /* Free remaining structures */
4614 free_graphs(out, outsize, spmin, spmax);
4619 ***************************************************************************
4620 * Display huge pages statistics in SVG.
4623 * @a Activity structure with statistics.
4624 * @curr Index in array for current sample statistics.
4625 * @action Action expected from current function.
4626 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4627 * flag indicating that a restart record has been previously
4628 * found (.@restart) and time used for the X axis origin
4630 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4631 * @record_hdr Pointer on record header of current stats sample.
4632 ***************************************************************************
4634 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4635 unsigned long long itv, struct record_header *record_hdr)
4638 *smc = (struct stats_huge *) a->buf[curr];
4639 int group[] = {4, 1};
4640 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4641 char *title[] = {"Huge pages utilization (1)",
4642 "Huge pages utilization (2)"};
4643 char *g_title[] = {"~kbhugfree", "~kbhugused", "~kbhugrsvd", "~kbhugsurp",
4645 int g_fields[] = {0, 5, 2, 3};
4646 static double *spmin, *spmax;
4648 static int *outsize;
4651 if (action & F_BEGIN) {
4653 * Allocate arrays that will contain the graphs data
4654 * and the min/max values.
4655 * Allocate one additional array (#5) to save min/max
4656 * values for tlhkb (unused).
4658 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
4661 if (action & F_MAIN) {
4662 /* Check for min/max values */
4663 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
4664 itv, spmin, spmax, g_fields);
4666 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4667 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4669 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4670 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4672 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4673 if (tval < *(spmin + 4)) {
4674 *(spmin + 4) = tval;
4676 if (tval > *(spmax + 4)) {
4677 *(spmax + 4) = tval;
4681 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4682 (unsigned long long) smc->frhkb,
4683 out, outsize, svg_p->restart);
4685 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4686 (unsigned long long) smc->tlhkb - smc->frhkb,
4687 out + 1, outsize + 1, svg_p->restart);
4689 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4690 (unsigned long long) smc->rsvdhkb,
4691 out + 2, outsize + 2, svg_p->restart);
4693 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4694 (unsigned long long) smc->surphkb,
4695 out + 3, outsize + 3, svg_p->restart);
4697 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4699 out + 4, outsize + 4, svg_p->dt);
4702 if (action & F_END) {
4703 draw_activity_graphs(a->g_nr, g_type,
4704 title, g_title, NULL, group,
4705 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4707 /* Free remaining structures */
4708 free_graphs(out, outsize, spmin, spmax);
4713 ***************************************************************************
4714 * Display filesystem statistics in SVG.
4717 * @a Activity structure with statistics.
4718 * @curr Index in array for current sample statistics.
4719 * @action Action expected from current function.
4720 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4721 * flag indicating that a restart record has been previously
4722 * found (.@restart) and time used for the X axis origin
4724 * @itv Interval of time in 1/100th of a second (unused here).
4725 * @record_hdr Pointer on record header of current stats sample.
4726 ***************************************************************************
4728 #define FS_ARRAY_SZ 8
4729 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4730 unsigned long long itv, struct record_header *record_hdr)
4732 struct stats_filesystem *sfc, *sfp;
4733 int group[] = {2, 2, 2, 1};
4734 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4735 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4736 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4737 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4738 char *g_title[] = {"~MBfsfree", "~MBfsused",
4739 "%ufsused", "%fsused",
4740 "Ifree/1000", "Iused/1000",
4742 static double *spmin, *spmax;
4744 static int *outsize;
4745 char *dev_name, *item_name;
4747 int i, k, pos, restart;
4749 if (action & F_BEGIN) {
4751 * Allocate arrays (#0..6) that will contain the graphs data
4752 * and the min/max values.
4753 * Also allocate an additional arrays (#7) for each filesystem:
4754 * out + 7 will contain the persistent or standard fs name, or mount point.
4756 out = allocate_graph_lines(FS_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4759 if (action & F_MAIN) {
4760 /* For each filesystem structure */
4761 for (i = 0; i < a->nr[curr]; i++) {
4762 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4764 /* Get name to display (persistent or standard fs name, or mount point) */
4765 dev_name = get_fs_name_to_display(a, flags, sfc);
4767 if (a->item_list != NULL) {
4768 /* A list of devices has been entered on the command line */
4769 if (!search_list_item(a->item_list, dev_name))
4770 /* Device not found */
4774 /* Look for corresponding graph */
4775 for (k = 0; k < a->item_list_sz; k++) {
4776 item_name = *(out + k * FS_ARRAY_SZ + 7);
4777 if (!strcmp(dev_name, item_name))
4782 if (k == a->item_list_sz) {
4783 /* Graph not found: Look for first free entry */
4784 for (k = 0; k < a->item_list_sz; k++) {
4785 item_name = *(out + k * FS_ARRAY_SZ + 7);
4786 if (!strcmp(item_name, ""))
4789 if (k == a->item_list_sz) {
4790 /* No free graph entry: Ignore it (should never happen) */
4792 fprintf(stderr, "%s: Name=%s\n",
4793 __FUNCTION__, sfc->fs_name);
4799 pos = k * FS_ARRAY_SZ;
4801 item_name = *(out + pos + 7);
4802 if (!item_name[0]) {
4803 /* Save filesystem name and mount point (if not already done) */
4804 strncpy(item_name, dev_name, CHUNKSIZE);
4805 item_name[CHUNKSIZE - 1] = '\0';
4809 for (k = 0; k < a->nr[!curr]; k++) {
4810 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4811 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4812 /* Filesystem found in previous sample */
4813 restart = svg_p->restart;
4817 /* Check for min/max values */
4819 /* Compute fsfree min/max values */
4820 tval = (double) sfc->f_bfree;
4821 if (tval > *(spmax + pos)) {
4822 *(spmax + pos) = tval;
4824 if (tval < *(spmin + pos)) {
4825 *(spmin + pos) = tval;
4827 /* Compute fsused min/max values */
4828 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4829 if (tval > *(spmax + pos + 1)) {
4830 *(spmax + pos + 1) = tval;
4832 if (tval < *(spmin + pos + 1)) {
4833 *(spmin + pos + 1) = tval;
4835 /* Compute %ufsused min/max values */
4836 tval = sfc->f_blocks ?
4837 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4838 if (tval > *(spmax + pos + 2)) {
4839 *(spmax + pos + 2) = tval;
4841 if (tval < *(spmin + pos + 2)) {
4842 *(spmin + pos + 2) = tval;
4844 /* Compute %fsused min/max values */
4845 tval = sfc->f_blocks ?
4846 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4847 if (tval > *(spmax + pos + 3)) {
4848 *(spmax + pos + 3) = tval;
4850 if (tval < *(spmin + pos + 3)) {
4851 *(spmin + pos + 3) = tval;
4853 /* Compute Ifree min/max values */
4854 tval = (double) sfc->f_ffree;
4855 if (tval > *(spmax + pos + 4)) {
4856 *(spmax + pos + 4) = tval;
4858 if (tval < *(spmin + pos + 4)) {
4859 *(spmin + pos + 4) = tval;
4861 /* Compute Iused min/max values */
4862 tval = (double) (sfc->f_files - sfc->f_ffree);
4863 if (tval > *(spmax + pos + 5)) {
4864 *(spmax + pos + 5) = tval;
4866 if (tval < *(spmin + pos + 5)) {
4867 *(spmin + pos + 5) = tval;
4869 /* Compute %Iused min/max values */
4870 tval = sfc->f_files ?
4871 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4872 if (tval > *(spmax + pos + 6)) {
4873 *(spmax + pos + 6) = tval;
4875 if (tval < *(spmin + pos + 6)) {
4876 *(spmin + pos + 6) = tval;
4880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4881 (double) sfc->f_bfree / 1024 / 1024,
4882 out + pos, outsize + pos, restart);
4884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4885 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4886 out + pos + 1, outsize + pos + 1, restart);
4888 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4891 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4892 out + pos + 2, outsize + pos + 2, svg_p->dt);
4894 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4897 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4898 out + pos + 3, outsize + pos + 3, svg_p->dt);
4900 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4901 ((double) sfc->f_ffree) / 1000,
4902 out + pos + 4, outsize + pos + 4, restart);
4904 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4905 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4906 out + pos + 5, outsize + pos + 5, restart);
4908 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4911 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4912 out + pos + 6, outsize + pos + 6, svg_p->dt);
4916 if (action & F_END) {
4919 for (i = 0; i < a->item_list_sz; i++) {
4921 /* Check if there is something to display */
4922 pos = i * FS_ARRAY_SZ;
4926 /* Conversion B -> MiB and inodes/1000 */
4927 for (k = 0; k < 2; k++) {
4928 *(spmin + pos + k) /= (1024 * 1024);
4929 *(spmax + pos + k) /= (1024 * 1024);
4930 *(spmin + pos + 4 + k) /= 1000;
4931 *(spmax + pos + 4 + k) /= 1000;
4934 item_name = *(out + pos + 7);
4936 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4937 spmin + pos, spmax + pos, out + pos, outsize + pos,
4938 svg_p, record_hdr, FALSE, a, xid)) {
4943 /* Free remaining structures */
4944 free_graphs(out, outsize, spmin, spmax);
4949 ***************************************************************************
4950 * Display Fibre Channel HBA statistics in SVG.
4953 * @a Activity structure with statistics.
4954 * @curr Index in array for current sample statistics.
4955 * @action Action expected from current function.
4956 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4957 * flag indicating that a restart record has been previously
4958 * found (.@restart) and time used for the X axis origin
4960 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4961 * @record_hdr Pointer on record header of current stats sample.
4962 ***************************************************************************
4964 #define FC_ARRAY_SZ 5
4965 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4966 unsigned long long itv, struct record_header *record_hdr)
4968 struct stats_fchost *sfcc, *sfcp, sfczero;
4969 int group[] = {2, 2};
4970 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4971 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4972 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4973 "fch_rxw/s", "fch_txw/s"};
4974 int g_fields[] = {0, 1, 2, 3};
4975 static double *spmin, *spmax;
4977 static int *outsize;
4979 int i, j, j0, k, found, pos, restart, *unregistered;
4981 if (action & F_BEGIN) {
4983 * Allocate arrays (#0..3) that will contain the graphs data
4984 * and the min/max values.
4985 * Also allocate one additional array (#4) that will contain
4986 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4987 * has either still not been registered, or has been unregistered
4990 out = allocate_graph_lines(FC_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4993 if (action & F_MAIN) {
4994 memset(&sfczero, 0, sizeof(struct stats_fchost));
4996 * Mark previously registered interfaces as now
4997 * possibly unregistered for all graphs.
4999 for (k = 0; k < a->item_list_sz; k++) {
5000 unregistered = outsize + k * FC_ARRAY_SZ + 4;
5001 if (*unregistered == FALSE) {
5002 *unregistered = MAYBE;
5006 /* For each FC HBA */
5007 for (i = 0; i < a->nr[curr]; i++) {
5010 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
5011 restart = svg_p->restart;
5013 /* Look for corresponding graph */
5014 for (k = 0; k < a->item_list_sz; k++) {
5015 item_name = *(out + k * FC_ARRAY_SZ + 4);
5016 if (!strcmp(sfcc->fchost_name, item_name))
5020 if (k == a->item_list_sz) {
5021 /* Graph not found: Look for first free entry */
5022 for (k = 0; k < a->item_list_sz; k++) {
5023 item_name = *(out + k * FC_ARRAY_SZ + 4);
5024 if (!strcmp(item_name, ""))
5027 if (k == a->item_list_sz) {
5028 /* No free graph entry: Ignore it (should never happen) */
5030 fprintf(stderr, "%s: Name=%s\n",
5031 __FUNCTION__, sfcc->fchost_name);
5037 pos = k * FC_ARRAY_SZ;
5038 unregistered = outsize + pos + 4;
5040 if (a->nr[!curr] > 0) {
5041 /* Look for corresponding structure in previous iteration */
5044 if (j >= a->nr[!curr]) {
5045 j = a->nr[!curr] - 1;
5051 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
5052 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
5056 if (++j >= a->nr[!curr]) {
5064 /* This is a newly registered host */
5070 * If current interface was marked as previously unregistered,
5071 * then set restart variable to TRUE so that the graph will be
5072 * discontinuous, and mark it as now registered.
5074 if (*unregistered == TRUE) {
5077 *unregistered = FALSE;
5079 item_name = *(out + pos + 4);
5080 if (!item_name[0]) {
5081 /* Save FC HBA name */
5082 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
5083 item_name[CHUNKSIZE - 1] = '\0';
5086 /* Look for min/max values */
5087 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
5088 itv, spmin + pos, spmax + pos, g_fields);
5091 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5092 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5093 out + pos, outsize + pos, restart);
5095 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5096 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5097 out + pos + 1, outsize + pos + 1, restart);
5099 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5100 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5101 out + pos + 2, outsize + pos + 2, restart);
5103 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5104 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5105 out + pos + 3, outsize + pos + 3, restart);
5108 /* Mark interfaces not seen here as now unregistered */
5109 for (k = 0; k < a->item_list_sz; k++) {
5110 unregistered = outsize + k * FC_ARRAY_SZ + 4;
5111 if (*unregistered != FALSE) {
5112 *unregistered = TRUE;
5117 if (action & F_END) {
5118 for (i = 0; i < a->item_list_sz; i++) {
5120 /* Check if there is something to display */
5121 pos = i * FC_ARRAY_SZ;
5125 item_name = *(out + pos + 4);
5126 draw_activity_graphs(a->g_nr, g_type,
5127 title, g_title, item_name, group,
5128 spmin + pos, spmax + pos, out + pos, outsize + pos,
5129 svg_p, record_hdr, FALSE, a, i);
5132 /* Free remaining structures */
5133 free_graphs(out, outsize, spmin, spmax);
5138 ***************************************************************************
5139 * Display softnet statistics in SVG.
5142 * @a Activity structure with statistics.
5143 * @curr Index in array for current sample statistics.
5144 * @action Action expected from current function.
5145 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5146 * flag indicating that a restart record has been previously
5147 * found (.@restart) and time used for the X axis origin
5149 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5150 * @record_hdr Pointer on record header of current stats sample.
5151 ***************************************************************************
5153 #define SOFT_ARRAY_SZ 5
5154 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5155 unsigned long long itv, struct record_header *record_hdr)
5157 struct stats_softnet *ssnc, *ssnp, ssnczero;
5158 int group[] = {2, 3};
5159 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5160 char *title[] = {"Software-based network processing statistics (1)",
5161 "Software-based network processing statistics (2)"};
5162 char *g_title[] = {"total/s", "dropd/s",
5163 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5164 int g_fields[] = {0, 1, 2, 3, 4};
5165 static double *spmin, *spmax;
5167 static int *outsize;
5169 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5170 int i, pos, restart;
5172 if (action & F_BEGIN) {
5174 * Allocate arrays that will contain the graphs data
5175 * and the min/max values.
5177 out = allocate_graph_lines(SOFT_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
5180 if (action & F_MAIN) {
5181 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5183 /* @nr[curr] cannot normally be greater than @nr_ini */
5184 if (a->nr[curr] > a->nr_ini) {
5185 a->nr_ini = a->nr[curr];
5188 /* Compute statistics for CPU "all" */
5189 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5192 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5193 restart = svg_p->restart;
5195 /* Should current CPU (including CPU "all") be displayed? */
5196 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5200 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5201 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5203 /* Is current CPU marked offline? */
5204 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5206 * Yes and it doesn't follow a RESTART record.
5207 * To add a discontinuity in graph, we simulate
5211 if (svg_p->restart) {
5213 * CPU is offline and it follows a real
5214 * RESTART record. Ignore its current value
5215 * (no previous sample).
5220 pos = i * SOFT_ARRAY_SZ;
5222 /* Check for min/max values */
5223 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5224 itv, spmin + pos, spmax + pos, g_fields);
5227 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5228 S_VALUE(ssnp->processed, ssnc->processed, itv),
5229 out + pos, outsize + pos, restart);
5231 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5232 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5233 out + pos + 1, outsize + pos + 1, restart);
5235 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5236 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5237 out + pos + 2, outsize + pos + 2, restart);
5239 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5240 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5241 out + pos + 3, outsize + pos + 3, restart);
5243 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5244 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5245 out + pos + 4, outsize + pos + 4, restart);
5249 if (action & F_END) {
5250 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
5252 /* Should current CPU (including CPU "all") be displayed? */
5253 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5257 pos = i * SOFT_ARRAY_SZ;
5260 /* This is CPU "all" */
5261 strcpy(item_name, "all");
5264 sprintf(item_name, "%d", i - 1);
5267 draw_activity_graphs(a->g_nr, g_type,
5268 title, g_title, item_name, group,
5269 spmin + pos, spmax + pos, out + pos, outsize + pos,
5270 svg_p, record_hdr, FALSE, a, i);
5273 /* Free remaining structures */
5274 free_graphs(out, outsize, spmin, spmax);
5279 ***************************************************************************
5280 * Display pressure-stall CPU statistics in SVG.
5283 * @a Activity structure with statistics.
5284 * @curr Index in array for current sample statistics.
5285 * @action Action expected from current function.
5286 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5287 * flag indicating that a restart record has been previously
5288 * found (.@restart) and time used for the X axis origin
5290 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5291 * @record_hdr Pointer on record header of current stats sample.
5292 ***************************************************************************
5294 __print_funct_t svg_print_psicpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5295 unsigned long long itv, struct record_header *record_hdr)
5297 struct stats_psi_cpu
5298 *psic = (struct stats_psi_cpu *) a->buf[curr],
5299 *psip = (struct stats_psi_cpu *) a->buf[!curr];
5300 int group[] = {3, 1};
5301 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5302 char *title[] = {"CPU pressure trends (some tasks)", "CPU stall time (some tasks)"};
5303 char *g_title[] = {"%scpu-10", "%scpu-60", "%scpu-300",
5305 static double *spmin, *spmax;
5307 static int *outsize;
5310 if (action & F_BEGIN) {
5312 * Allocate arrays that will contain the graphs data
5313 * and the min/max values.
5315 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
5318 if (action & F_MAIN) {
5319 /* Check for min/max values */
5320 if (psic->some_acpu_10 > *spmax) {
5321 *spmax = psic->some_acpu_10;
5323 if (psic->some_acpu_10 < *spmin) {
5324 *spmin = psic->some_acpu_10;
5326 if (psic->some_acpu_60 > *(spmax + 1)) {
5327 *(spmax + 1) = psic->some_acpu_60;
5329 if (psic->some_acpu_60 < *(spmin + 1)) {
5330 *(spmin + 1) = psic->some_acpu_60;
5332 if (psic->some_acpu_300 > *(spmax + 2)) {
5333 *(spmax + 2) = psic->some_acpu_300;
5335 if (psic->some_acpu_300 < *(spmin + 2)) {
5336 *(spmin + 2) = psic->some_acpu_300;
5338 tval = ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv);
5339 if (tval > *(spmax + 3)) {
5340 *(spmax + 3) = tval;
5342 if (tval < *(spmin + 3)) {
5343 *(spmin + 3) = tval;
5347 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5348 (double) psic->some_acpu_10 / 100,
5349 out, outsize, svg_p->restart);
5351 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5352 (double) psic->some_acpu_60 / 100,
5353 out + 1, outsize + 1, svg_p->restart);
5355 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5356 (double) psic->some_acpu_300 / 100,
5357 out + 2, outsize + 2, svg_p->restart);
5359 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5361 ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv),
5362 out + 3, outsize + 3, svg_p->dt);
5365 if (action & F_END) {
5366 /* Fix min/max values for pressure ratios */
5367 *spmin /= 100; *spmax /= 100;
5368 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5369 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5371 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5372 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5374 /* Free remaining structures */
5375 free_graphs(out, outsize, spmin, spmax);
5380 ***************************************************************************
5381 * Display pressure-stall I/O statistics in SVG.
5384 * @a Activity structure with statistics.
5385 * @curr Index in array for current sample statistics.
5386 * @action Action expected from current function.
5387 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5388 * flag indicating that a restart record has been previously
5389 * found (.@restart) and time used for the X axis origin
5391 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5392 * @record_hdr Pointer on record header of current stats sample.
5393 ***************************************************************************
5395 __print_funct_t svg_print_psiio_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5396 unsigned long long itv, struct record_header *record_hdr)
5399 *psic = (struct stats_psi_io *) a->buf[curr],
5400 *psip = (struct stats_psi_io *) a->buf[!curr];
5401 int group[] = {3, 1, 3, 1};
5402 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5403 char *title[] = {"I/O pressure trends (some tasks)", "I/O stall time (some tasks)",
5404 "I/O pressure trends (full)", "I/O stall time (full)"};
5405 char *g_title[] = {"%sio-10", "%sio-60", "%sio-300",
5407 "%fio-10", "%fio-60", "%fio-300",
5409 static double *spmin, *spmax;
5411 static int *outsize;
5414 if (action & F_BEGIN) {
5416 * Allocate arrays that will contain the graphs data
5417 * and the min/max values.
5419 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5422 if (action & F_MAIN) {
5423 /* Check for min/max values */
5424 if (psic->some_aio_10 > *spmax) {
5425 *spmax = psic->some_aio_10;
5427 if (psic->some_aio_10 < *spmin) {
5428 *spmin = psic->some_aio_10;
5430 if (psic->some_aio_60 > *(spmax + 1)) {
5431 *(spmax + 1) = psic->some_aio_60;
5433 if (psic->some_aio_60 < *(spmin + 1)) {
5434 *(spmin + 1) = psic->some_aio_60;
5436 if (psic->some_aio_300 > *(spmax + 2)) {
5437 *(spmax + 2) = psic->some_aio_300;
5439 if (psic->some_aio_300 < *(spmin + 2)) {
5440 *(spmin + 2) = psic->some_aio_300;
5442 tval = ((double) psic->some_io_total - psip->some_io_total) / (100 * itv);
5443 if (tval > *(spmax + 3)) {
5444 *(spmax + 3) = tval;
5446 if (tval < *(spmin + 3)) {
5447 *(spmin + 3) = tval;
5450 if (psic->full_aio_10 > *(spmax + 4)) {
5451 *(spmax + 4) = psic->full_aio_10;
5453 if (psic->full_aio_10 < *(spmin + 4)) {
5454 *(spmin + 4) = psic->full_aio_10;
5456 if (psic->full_aio_60 > *(spmax + 5)) {
5457 *(spmax + 5) = psic->full_aio_60;
5459 if (psic->full_aio_60 < *(spmin + 5)) {
5460 *(spmin + 5) = psic->full_aio_60;
5462 if (psic->full_aio_300 > *(spmax + 6)) {
5463 *(spmax + 6) = psic->full_aio_300;
5465 if (psic->full_aio_300 < *(spmin + 6)) {
5466 *(spmin + 6) = psic->full_aio_300;
5468 tval = ((double) psic->full_io_total - psip->full_io_total) / (100 * itv);
5469 if (tval > *(spmax + 7)) {
5470 *(spmax + 7) = tval;
5472 if (tval < *(spmin + 7)) {
5473 *(spmin + 7) = tval;
5477 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5478 (double) psic->some_aio_10 / 100,
5479 out, outsize, svg_p->restart);
5481 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5482 (double) psic->some_aio_60 / 100,
5483 out + 1, outsize + 1, svg_p->restart);
5485 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5486 (double) psic->some_aio_300 / 100,
5487 out + 2, outsize + 2, svg_p->restart);
5489 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5491 ((double) psic->some_io_total - psip->some_io_total) / (100 * itv),
5492 out + 3, outsize + 3, svg_p->dt);
5495 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5496 (double) psic->full_aio_10 / 100,
5497 out + 4, outsize + 4, svg_p->restart);
5499 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5500 (double) psic->full_aio_60 / 100,
5501 out + 5, outsize + 5, svg_p->restart);
5503 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5504 (double) psic->full_aio_300 / 100,
5505 out + 6, outsize + 6, svg_p->restart);
5507 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5509 ((double) psic->full_io_total - psip->full_io_total) / (100 * itv),
5510 out + 7, outsize + 7, svg_p->dt);
5513 if (action & F_END) {
5514 /* Fix min/max values for pressure ratios */
5515 *spmin /= 100; *spmax /= 100;
5516 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5517 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5519 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5520 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5521 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5523 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5524 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5526 /* Free remaining structures */
5527 free_graphs(out, outsize, spmin, spmax);
5532 ***************************************************************************
5533 * Display pressure-stall memory statistics in SVG.
5536 * @a Activity structure with statistics.
5537 * @curr Index in array for current sample statistics.
5538 * @action Action expected from current function.
5539 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5540 * flag indicating that a restart record has been previously
5541 * found (.@restart) and time used for the X axis origin
5543 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5544 * @record_hdr Pointer on record header of current stats sample.
5545 ***************************************************************************
5547 __print_funct_t svg_print_psimem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5548 unsigned long long itv, struct record_header *record_hdr)
5550 struct stats_psi_mem
5551 *psic = (struct stats_psi_mem *) a->buf[curr],
5552 *psip = (struct stats_psi_mem *) a->buf[!curr];
5553 int group[] = {3, 1, 3, 1};
5554 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5555 char *title[] = {"Memory pressure trends (some tasks)", "Memory stall time (some tasks)",
5556 "Memory pressure trends (full)", "Memory stall time (full)"};
5557 char *g_title[] = {"%smem-10", "%smem-60", "%smem-300",
5559 "%fmem-10", "%fmem-60", "%fmem-300",
5561 static double *spmin, *spmax;
5563 static int *outsize;
5566 if (action & F_BEGIN) {
5568 * Allocate arrays that will contain the graphs data
5569 * and the min/max values.
5571 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5574 if (action & F_MAIN) {
5575 /* Check for min/max values */
5576 if (psic->some_amem_10 > *spmax) {
5577 *spmax = psic->some_amem_10;
5579 if (psic->some_amem_10 < *spmin) {
5580 *spmin = psic->some_amem_10;
5582 if (psic->some_amem_60 > *(spmax + 1)) {
5583 *(spmax + 1) = psic->some_amem_60;
5585 if (psic->some_amem_60 < *(spmin + 1)) {
5586 *(spmin + 1) = psic->some_amem_60;
5588 if (psic->some_amem_300 > *(spmax + 2)) {
5589 *(spmax + 2) = psic->some_amem_300;
5591 if (psic->some_amem_300 < *(spmin + 2)) {
5592 *(spmin + 2) = psic->some_amem_300;
5594 tval = ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv);
5595 if (tval > *(spmax + 3)) {
5596 *(spmax + 3) = tval;
5598 if (tval < *(spmin + 3)) {
5599 *(spmin + 3) = tval;
5602 if (psic->full_amem_10 > *(spmax + 4)) {
5603 *(spmax + 4) = psic->full_amem_10;
5605 if (psic->full_amem_10 < *(spmin + 4)) {
5606 *(spmin + 4) = psic->full_amem_10;
5608 if (psic->full_amem_60 > *(spmax + 5)) {
5609 *(spmax + 5) = psic->full_amem_60;
5611 if (psic->full_amem_60 < *(spmin + 5)) {
5612 *(spmin + 5) = psic->full_amem_60;
5614 if (psic->full_amem_300 > *(spmax + 6)) {
5615 *(spmax + 6) = psic->full_amem_300;
5617 if (psic->full_amem_300 < *(spmin + 6)) {
5618 *(spmin + 6) = psic->full_amem_300;
5620 tval = ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv);
5621 if (tval > *(spmax + 7)) {
5622 *(spmax + 7) = tval;
5624 if (tval < *(spmin + 7)) {
5625 *(spmin + 7) = tval;
5629 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5630 (double) psic->some_amem_10 / 100,
5631 out, outsize, svg_p->restart);
5633 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5634 (double) psic->some_amem_60 / 100,
5635 out + 1, outsize + 1, svg_p->restart);
5637 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5638 (double) psic->some_amem_300 / 100,
5639 out + 2, outsize + 2, svg_p->restart);
5641 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5643 ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv),
5644 out + 3, outsize + 3, svg_p->dt);
5647 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5648 (double) psic->full_amem_10 / 100,
5649 out + 4, outsize + 4, svg_p->restart);
5651 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5652 (double) psic->full_amem_60 / 100,
5653 out + 5, outsize + 5, svg_p->restart);
5655 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5656 (double) psic->full_amem_300 / 100,
5657 out + 6, outsize + 6, svg_p->restart);
5659 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5661 ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv),
5662 out + 7, outsize + 7, svg_p->dt);
5665 if (action & F_END) {
5666 /* Fix min/max values for pressure ratios */
5667 *spmin /= 100; *spmax /= 100;
5668 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5669 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5671 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5672 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5673 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5675 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5676 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5678 /* Free remaining structures */
5679 free_graphs(out, outsize, spmin, spmax);