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 unsigned int 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)
609 /* Display horizontal lines (except on X axis) */
611 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
612 "stroke: #%06x\" transform=\"scale(1,%f)\"/>\n",
613 ypos * j, SVG_G_XSIZE, ypos * j,
614 svg_colors[palette][SVG_COL_GRID_IDX],
619 * Display graduations.
620 * Use same rounded value for graduation numbers as for grid lines
621 * to make sure they are properly aligned.
623 sprintf(stmp, "%.2f", ypos * j);
624 printf("<text x=\"0\" y=\"%ld\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
625 "text-anchor: end\">%.*f.</text>\n",
626 (long) (atof(stmp) * yfactor),
627 svg_colors[palette][SVG_COL_AXIS_IDX],
631 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
635 ***************************************************************************
636 * Display background grid (vertical lines) and corresponding graduations.
639 * @xpos Gap between two vertical lines.
640 * @xfactor Scaling factor on X axis.
641 * @v_gridnr Default number of vertical lines to display. The actual
642 * number may vary between this value and 2 times this value.
643 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
644 ***************************************************************************
646 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
648 struct record_header stamp;
650 char cur_time[TIMESTAMP_LEN];
653 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
656 * What really matters to know when we should stop drawing vertical lines
657 * is the time end. v_gridnr is only informative and used to calculate
658 * the gap between two lines.
660 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
662 /* Display vertical lines */
663 sa_get_record_timestamp_struct(flags, &stamp, &rectime);
664 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
665 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
666 "stroke: #%06x\" transform=\"scale(%f,1)\"/>\n",
667 xpos * j, xpos * j, -SVG_G_YSIZE,
668 svg_colors[palette][SVG_COL_GRID_IDX],
671 * Display graduations.
672 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
673 * In this case, we should rather display the exact time instead of only the hour.
675 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
676 printf("<text x=\"%ld\" y=\"15\" style=\"fill: #%06x; stroke: none; font-size: 14px; "
677 "text-anchor: start\">%2d:00</text>\n",
678 (long) (xpos * j * xfactor) - 15,
679 svg_colors[palette][SVG_COL_AXIS_IDX],
683 printf("<text x=\"%ld\" y=\"10\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
684 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
685 (long) (xpos * j * xfactor),
686 svg_colors[palette][SVG_COL_AXIS_IDX],
687 (long) (xpos * j * xfactor), cur_time);
689 stamp.ust_time += xpos;
692 if (!PRINT_LOCAL_TIME(flags)) {
693 printf("<text x=\"-10\" y=\"30\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
694 "text-anchor: end\">UTC</text>\n",
695 svg_colors[palette][SVG_COL_INFO_IDX]);
700 ***************************************************************************
701 * Calculate the value on the Y axis between two horizontal lines that will
702 * make the graph background grid.
705 * @lmax Max value reached for this graph.
708 * @dp Number of decimal places for Y graduations.
711 * Value between two horizontal lines.
712 ***************************************************************************
714 double ygrid(double lmax, int *dp)
725 n = (long) (lmax / SVG_H_GRIDNR);
728 return (lmax / SVG_H_GRIDNR);
730 snprintf(val, 32, "%ld", n);
737 return ((double) (((long) (n / e)) * e));
741 ***************************************************************************
742 * Calculate the value on the X axis between two vertical lines that will
743 * make the graph background grid.
746 * @timestart First data timestamp (X coordinate of the first data point).
747 * @timeend Last data timestamp (X coordinate of the last data point).
748 * @v_gridnr Number of vertical lines to display. Its value is normally
749 * SVG_V_GRIDNR, except when option "oneday" is used, in which
750 * case it is set to 12.
753 * Value between two vertical lines.
754 ***************************************************************************
756 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
758 if ((timeend - timestart) <= v_gridnr)
761 return ((timeend - timestart) / v_gridnr);
765 ***************************************************************************
766 * Free global graphs structures.
769 * @out Pointer on array of chars for each graph definition.
770 * @outsize Size of array of chars for each graph definition.
771 * @spmin Array containing min values for graphs.
772 * @spmax Array containing max values for graphs.
773 ***************************************************************************
775 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
792 ***************************************************************************
793 * Skip current view where all graphs have only zero values. This function
794 * is called when option "skipempty" has been used, or when "No data" have
795 * been found for current view.
798 * @out Pointer on array of chars for each graph definition.
799 * @pos Position of current view in the array of graphs definitions.
800 * @group Number of graphs in current view.
803 * @pos Position of next view in the array of graphs definitions.
804 ***************************************************************************
806 void skip_current_view(char **out, int *pos, int group)
811 for (j = 0; j < group; j++) {
812 out_p = *(out + *pos + j);
814 /* Even if not displayed, current graph data have to be freed */
822 ***************************************************************************
823 * Display all graphs for current activity.
826 * @g_nr Number of views to display.
827 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
828 * @title Titles for each set of graphs.
829 * @g_title Titles for each graph.
830 * @item_name Item (network interface, etc.) name.
831 * @group Indicate how graphs are grouped together to make sets.
832 * @spmin Array containing min values for graphs.
833 * @spmax Array containing max values for graphs.
834 * @out Pointer on array of chars for each graph definition.
835 * @outsize Size of array of chars for each graph definition.
836 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
837 * time for the first sample of stats (.@ust_time_first), and
838 * times used as start and end values on the X axis
839 * (.@ust_time_ref and .@ust_time_end).
840 * @record_hdr Pointer on record header of current stats sample.
841 * @skip_void Set to <> 0 if graphs with no data should be skipped.
842 * This is typicallly used to not display CPU offline on the
844 * @id Current activity id.
845 * @xid Current activity extra id number.
848 * TRUE if at least one graph has been displayed.
849 ***************************************************************************
851 int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
852 int group[], double *spmin, double *spmax, char **out, int *outsize,
853 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
854 unsigned int id, unsigned int xid)
857 int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE, palpos;
858 int v_gridnr, xv, yv;
859 unsigned int asfactor[16];
861 double lmax, xfactor, yfactor, ypos, gmin, gmax;
862 char val[32], cur_date[TIMESTAMP_LEN];
865 /* For each view which is part of current activity */
866 for (i = 0; i < g_nr; i++) {
868 /* Used as index in color palette */
869 palpos = (palette == SVG_BW_COL_PALETTE ? 0 : pos);
871 /* Get global min and max value for current view */
872 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
874 /* Don't display empty views if requested */
875 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
876 skip_current_view(out, &pos, group[i]);
879 /* Skip void graphs */
880 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
884 /* Translate to proper position for current activity */
885 printf("<g id=\"g%d-%d\" transform=\"translate(0,%d)\">\n",
888 SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
889 SVG_T_YSIZE * svg_p->graph_no);
893 /* Increment number of views actually displayed */
896 /* Compute top left position of view */
897 if (PACK_VIEWS(flags)) {
898 xv = (views_nr - 1) * SVG_T_XSIZE;
903 yv = (views_nr - 1) * SVG_T_YSIZE;
906 /* Graph background */
907 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\" fill=\"#%06x\"/>\n",
908 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE,
909 svg_colors[palette][SVG_COL_BCKGRD_IDX]);
912 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">%s",
914 svg_colors[palette][SVG_COL_TITLE_IDX],
917 printf(" [%s]", item_name);
920 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
921 "(Min, Max values)</tspan>\n</text>\n",
922 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25,
923 svg_colors[palette][SVG_COL_INFO_IDX]);
926 * At least two samples are needed.
927 * And a min and max value should have been found.
929 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
930 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
932 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">No data</text>\n",
933 xv, yv + SVG_M_YSIZE,
934 svg_colors[palette][SVG_COL_ERROR_IDX]);
935 skip_current_view(out, &pos, group[i]);
940 printf("<polyline points=\"%d,%d %d,%d %d,%d\" style=\"fill: #%06x; stroke: #%06x; stroke-width: 2\"/>\n",
941 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
942 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
943 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
944 svg_colors[palette][SVG_COL_BCKGRD_IDX],
945 svg_colors[palette][SVG_COL_AXIS_IDX]);
947 /* Autoscaling graphs if needed */
948 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
951 for (j = 0; j < group[i]; j++) {
952 /* Set dp to TRUE (1) if current metric is based on integer values */
953 dp = (g_title[pos + j][0] == '~');
954 snprintf(val, 32, "x%u ", asfactor[j]);
955 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
956 "%s %s(%.*f, %.*f)</text>\n",
957 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
958 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
959 asfactor[j] == 1 ? "" : val,
960 !dp * 2, *(spmin + pos + j) * asfactor[j],
961 !dp * 2, *(spmax + pos + j) * asfactor[j]);
964 if (DISPLAY_INFO(flags)) {
965 /* Display additional info (hostname, date) */
966 printf("<text x=\"%d\" y=\"%d\" "
967 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
969 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
970 svg_colors[palette][SVG_COL_INFO_IDX],
971 svg_p->file_hdr->sa_nodename);
973 /* Get report date */
974 set_report_date(localtime_r((const time_t *) &(svg_p->file_hdr->sa_ust_time), &rectime),
975 cur_date, sizeof(cur_date));
976 printf("<tspan x=\"%d\" y=\"%d\" "
977 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
978 "%s</tspan>\n</text>\n",
979 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
980 svg_colors[palette][SVG_COL_INFO_IDX],
984 /* Translate to proper position for current graph within current activity */
985 printf("<g transform=\"translate(%d,%d)\">\n",
986 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
989 if (g_type[i] == SVG_LINE_GRAPH) {
990 /* For line graphs */
992 /* If all values are zero then set current max value to 1 */
998 /* Max value cannot be too small, else Y graduations will be meaningless */
999 if (lmax < SVG_H_GRIDNR * 0.01) {
1000 lmax = SVG_H_GRIDNR * 0.01;
1002 ypos = ygrid(lmax, &dp);
1005 /* For bar graphs (used for %values) */
1006 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
1007 dp = 0; /* No decimals */
1009 /* Max should be always 100% except for percentage values greater than 100% */
1017 yfactor = (double) -SVG_G_YSIZE / lmax;
1019 /* Display horizontal lines and graduations */
1020 display_hgrid(ypos, yfactor, lmax, dp);
1022 /* Set number of vertical lines to 12 when option "oneday" is used */
1023 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1025 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1026 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1028 /* Display vertical lines and graduations */
1029 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1031 /* Draw current graphs set */
1032 for (j = 0; j < group[i]; j++) {
1033 out_p = *(out + pos + j);
1034 if (g_type[i] == SVG_LINE_GRAPH) {
1036 printf("<path d=\"%s\" "
1037 "style=\"vector-effect: non-scaling-stroke; "
1038 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1039 "transform=\"scale(%f,%f)\"/>\n",
1041 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK],
1043 yfactor * asfactor[j]);
1045 else if (*out_p) { /* Ignore flat bars */
1047 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1048 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1049 printf("%s\n", out_p);
1060 /* For next row of views */
1061 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1068 ***************************************************************************
1069 * Display CPU statistics in SVG.
1072 * @a Activity structure with statistics.
1073 * @curr Index in array for current sample statistics.
1074 * @action Action expected from current function.
1075 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1076 * flag indicating that a restart record has been previously
1077 * found (.@restart), and time used for the X axis origin
1079 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1081 * @record_hdr Pointer on record header of current stats sample.
1082 ***************************************************************************
1084 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1085 unsigned long long itv, struct record_header *record_hdr)
1087 struct stats_cpu *scc, *scp;
1088 unsigned long long deltot_jiffies = 1;
1089 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1092 int g_type[] = {SVG_BAR_GRAPH};
1093 char *title[] = {"CPU utilization"};
1094 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1095 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1096 static double *spmin, *spmax;
1098 static int *outsize;
1103 if (action & F_BEGIN) {
1105 * Allocate arrays that will contain the graphs data
1106 * and the min/max values.
1108 out = allocate_graph_lines(10 * a->item_list_sz, &outsize, &spmin, &spmax);
1111 if (action & F_MAIN) {
1113 /* @nr[curr] cannot normally be greater than @nr_ini */
1114 if (a->nr[curr] > a->nr_ini) {
1115 a->nr_ini = a->nr[curr];
1119 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1120 * and look for offline CPU.
1122 if (a->nr_ini > 1) {
1123 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1124 flags, offline_cpu_bitmap);
1128 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1130 /* Should current CPU (including CPU "all") be displayed? */
1131 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1132 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1133 /* Don't display CPU */
1136 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1137 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1143 /* This is CPU "all" */
1144 if (a->nr_ini == 1) {
1146 * This is a UP machine. In this case
1147 * interval has still not been calculated.
1149 deltot_jiffies = get_per_cpu_interval(scc, scp);
1151 if (!deltot_jiffies) {
1152 /* CPU "all" cannot be tickless */
1158 * Recalculate interval for current proc.
1159 * If result is 0 then current CPU is a tickless one.
1161 deltot_jiffies = get_per_cpu_interval(scc, scp);
1163 if (!deltot_jiffies) { /* Current CPU is tickless */
1165 val = 100.0; /* Tickless CPU: %idle = 100% */
1167 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1170 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1174 /* Check min/max values for %user, etc. */
1175 for (k = 0; k < j; k++) {
1176 if (0.0 < *(spmin + pos + k)) {
1177 *(spmin + pos + k) = 0.0;
1179 if (0.0 > *(spmax + pos + k)) {
1180 *(spmax + pos + k) = 0.0;
1185 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1187 out + pos + j, outsize + pos + j, svg_p->dt,
1188 spmin + pos + j, spmax + pos + j);
1193 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1195 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1196 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1197 out + pos, outsize + pos, svg_p->dt,
1198 spmin + pos, spmax + pos);
1202 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1204 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1206 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1207 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1208 out + pos, outsize + pos, svg_p->dt,
1209 spmin + pos, spmax + pos);
1212 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1214 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1215 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1216 out + pos + 1, outsize + pos + 1, svg_p->dt,
1217 spmin + pos + 1, spmax + pos + 1);
1221 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1223 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1225 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1226 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1227 out + pos + 1, outsize + pos + 1, svg_p->dt,
1228 spmin + pos + 1, spmax + pos + 1);
1231 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1233 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1235 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1236 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1238 out + pos + 2, outsize + pos + 2, svg_p->dt,
1239 spmin + pos + 2, spmax + pos + 2);
1243 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1244 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1245 out + pos + 2, outsize + pos + 2, svg_p->dt,
1246 spmin + pos + 2, spmax + pos + 2);
1250 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1251 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1252 out + pos + 3, outsize + pos + 3, svg_p->dt,
1253 spmin + pos + 3, spmax + pos + 3);
1255 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1256 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1257 out + pos + 4, outsize + pos + 4, svg_p->dt,
1258 spmin + pos + 4, spmax + pos + 4);
1260 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1262 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1263 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1264 out + pos + 5, outsize + pos + 5, svg_p->dt,
1265 spmin + pos + 5, spmax + pos + 5);
1267 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1268 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1269 out + pos + 6, outsize + pos + 6, svg_p->dt,
1270 spmin + pos + 6, spmax + pos + 6);
1272 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1273 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1274 out + pos + 7, outsize + pos + 7, svg_p->dt,
1275 spmin + pos + 7, spmax + pos + 7);
1277 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1278 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1279 out + pos + 8, outsize + pos + 8, svg_p->dt,
1280 spmin + pos + 8, spmax + pos + 8);
1289 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1291 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1292 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1293 out + pos + j, outsize + pos + j, svg_p->dt,
1294 spmin + pos + j, spmax + pos + j);
1298 if (action & F_END) {
1299 int xid = 0, displayed;
1301 if (DISPLAY_IDLE(flags)) {
1302 /* Include additional %idle field */
1307 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
1309 /* Should current CPU (including CPU "all") be displayed? */
1310 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1316 /* This is CPU "all" */
1317 strcpy(item_name, "all");
1320 sprintf(item_name, "%d", i - 1);
1323 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1324 displayed = draw_activity_graphs(a->g_nr, g_type,
1325 title, g_title1, item_name, group1,
1326 spmin + pos, spmax + pos, out + pos, outsize + pos,
1327 svg_p, record_hdr, i, a->id, xid);
1330 displayed = draw_activity_graphs(a->g_nr, g_type,
1331 title, g_title2, item_name, group2,
1332 spmin + pos, spmax + pos, out + pos, outsize + pos,
1333 svg_p, record_hdr, i, a->id, xid);
1340 /* Free remaining structures */
1341 free_graphs(out, outsize, spmin, spmax);
1346 ***************************************************************************
1347 * Display task creation and context switch statistics in SVG.
1350 * @a Activity structure with statistics.
1351 * @curr Index in array for current sample statistics.
1352 * @action Action expected from current function.
1353 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1354 * flag indicating that a restart record has been previously
1355 * found (.@restart) and time used for the X axis origin
1357 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1358 * @record_hdr Pointer on record header of current stats sample.
1359 ***************************************************************************
1361 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1362 unsigned long long itv, struct record_header *record_hdr)
1365 *spc = (struct stats_pcsw *) a->buf[curr],
1366 *spp = (struct stats_pcsw *) a->buf[!curr];
1367 int group[] = {1, 1};
1368 int g_fields[] = {1, 0};
1369 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1370 char *title[] = {"Task creation", "Switching activity"};
1371 char *g_title[] = {"proc/s",
1373 static double *spmin, *spmax;
1375 static int *outsize;
1377 if (action & F_BEGIN) {
1379 * Allocate arrays that will contain the graphs data
1380 * and the min/max values.
1382 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1385 if (action & F_MAIN) {
1386 /* Check for min/max values */
1387 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1388 itv, spmin, spmax, g_fields);
1390 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1391 S_VALUE(spp->processes, spc->processes, itv),
1392 out, outsize, svg_p->restart);
1394 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1395 S_VALUE(spp->context_switch, spc->context_switch, itv),
1396 out + 1, outsize + 1, svg_p->restart);
1399 if (action & F_END) {
1400 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1401 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1403 /* Free remaining structures */
1404 free_graphs(out, outsize, spmin, spmax);
1409 ***************************************************************************
1410 * Display swap statistics in SVG.
1413 * @a Activity structure with statistics.
1414 * @curr Index in array for current sample statistics.
1415 * @action Action expected from current function.
1416 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1417 * flag indicating that a restart record has been previously
1418 * found (.@restart) and time used for the X axis origin
1420 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1421 * @record_hdr Pointer on record header of current stats sample.
1422 ***************************************************************************
1424 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1425 unsigned long long itv, struct record_header *record_hdr)
1428 *ssc = (struct stats_swap *) a->buf[curr],
1429 *ssp = (struct stats_swap *) a->buf[!curr];
1431 int g_type[] = {SVG_LINE_GRAPH};
1432 char *title[] = {"Swap activity"};
1433 char *g_title[] = {"pswpin/s", "pswpout/s" };
1434 int g_fields[] = {0, 1};
1435 static double *spmin, *spmax;
1437 static int *outsize;
1439 if (action & F_BEGIN) {
1441 * Allocate arrays that will contain the graphs data
1442 * and the min/max values.
1444 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1447 if (action & F_MAIN) {
1448 /* Check for min/max values */
1449 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1450 itv, spmin, spmax, g_fields);
1452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1453 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1454 out, outsize, svg_p->restart);
1456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1457 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1458 out + 1, outsize + 1, svg_p->restart);
1461 if (action & F_END) {
1462 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1463 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1465 /* Free remaining structures */
1466 free_graphs(out, outsize, spmin, spmax);
1471 ***************************************************************************
1472 * Display paging statistics in SVG.
1475 * @a Activity structure with statistics.
1476 * @curr Index in array for current sample statistics.
1477 * @action Action expected from current function.
1478 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1479 * flag indicating that a restart record has been previously
1480 * found (.@restart) and time used for the X axis origin
1482 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1483 * @record_hdr Pointer on record header of current stats sample.
1484 ***************************************************************************
1486 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1487 unsigned long long itv, struct record_header *record_hdr)
1490 *spc = (struct stats_paging *) a->buf[curr],
1491 *spp = (struct stats_paging *) a->buf[!curr];
1492 int group[] = {2, 2, 4};
1493 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1494 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1495 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1496 "fault/s", "majflt/s",
1497 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1498 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1499 static double *spmin, *spmax;
1501 static int *outsize;
1503 if (action & F_BEGIN) {
1505 * Allocate arrays that will contain the graphs data
1506 * and the min/max values.
1508 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1511 if (action & F_MAIN) {
1512 /* Check for min/max values */
1513 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1514 itv, spmin, spmax, g_fields);
1516 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1517 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1518 out, outsize, svg_p->restart);
1520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1521 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1522 out + 1, outsize + 1, svg_p->restart);
1524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1525 S_VALUE(spp->pgfault, spc->pgfault, itv),
1526 out + 2, outsize + 2, svg_p->restart);
1528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1529 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1530 out + 3, outsize + 3, svg_p->restart);
1532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1533 S_VALUE(spp->pgfree, spc->pgfree, itv),
1534 out + 4, outsize + 4, svg_p->restart);
1536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1537 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1538 out + 5, outsize + 5, svg_p->restart);
1540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1541 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1542 out + 6, outsize + 6, svg_p->restart);
1544 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1545 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1546 out + 7, outsize + 7, svg_p->restart);
1549 if (action & F_END) {
1550 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1551 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1553 /* Free remaining structures */
1554 free_graphs(out, outsize, spmin, spmax);
1559 ***************************************************************************
1560 * Display I/O and transfer rate statistics in SVG.
1563 * @a Activity structure with statistics.
1564 * @curr Index in array for current sample statistics.
1565 * @action Action expected from current function.
1566 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1567 * flag indicating that a restart record has been previously
1568 * found (.@restart) and time used for the X axis origin
1570 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1571 * @record_hdr Pointer on record header of current stats sample.
1572 ***************************************************************************
1574 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1575 unsigned long long itv, struct record_header *record_hdr)
1578 *sic = (struct stats_io *) a->buf[curr],
1579 *sip = (struct stats_io *) a->buf[!curr];
1580 int group[] = {4, 3};
1581 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1582 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1583 char *g_title[] = {"tps", "rtps", "wtps", "dtps",
1584 "bread/s", "bwrtn/s", "bdscd/s"};
1586 * tps:0, rtps:1, wtps:2, dtps:3, bread/s:4, bwrtn/s:5, bdscd/s:6
1596 int g_fields[] = {0, 1, 2, 4, 5, 3, 6};
1597 static double *spmin, *spmax;
1599 static int *outsize;
1601 if (action & F_BEGIN) {
1603 * Allocate arrays that will contain the graphs data
1604 * and the min/max values.
1606 out = allocate_graph_lines(7, &outsize, &spmin, &spmax);
1609 if (action & F_MAIN) {
1610 /* Check for min/max values */
1611 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1612 itv, spmin, spmax, g_fields);
1615 * If we get negative values, this is probably because
1616 * one or more devices/filesystems have been unmounted.
1617 * We display 0.0 in this case though we should rather tell
1618 * the user that the value cannot be calculated here.
1621 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1622 sic->dk_drive < sip->dk_drive ? 0.0 :
1623 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1624 out, outsize, svg_p->restart);
1626 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1627 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1628 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1629 out + 1, outsize + 1, svg_p->restart);
1631 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1632 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1633 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1634 out + 2, outsize + 2, svg_p->restart);
1636 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1637 sic->dk_drive_dio < sip->dk_drive_dio ? 0.0 :
1638 S_VALUE(sip->dk_drive_dio, sic->dk_drive_dio, itv),
1639 out + 3, outsize + 3, svg_p->restart);
1641 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1642 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1643 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1644 out + 4, outsize + 4, svg_p->restart);
1646 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1647 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1648 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1649 out + 5, outsize + 5, svg_p->restart);
1651 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1652 sic->dk_drive_dblk < sip->dk_drive_dblk ? 0.0 :
1653 S_VALUE(sip->dk_drive_dblk, sic->dk_drive_dblk, itv),
1654 out + 6, outsize + 6, svg_p->restart);
1657 if (action & F_END) {
1658 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1659 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1661 /* Free remaining structures */
1662 free_graphs(out, outsize, spmin, spmax);
1667 ***************************************************************************
1668 * Display memory statistics in SVG.
1671 * @a Activity structure with statistics.
1672 * @curr Index in array for current sample statistics.
1673 * @action Action expected from current function.
1674 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1675 * flag indicating that a restart record has been previously
1676 * found (.@restart) and time used for the X axis origin
1678 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1679 * @record_hdr Pointer on record header of current stats sample.
1680 ***************************************************************************
1682 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1683 unsigned long long itv, struct record_header *record_hdr)
1686 *smc = (struct stats_memory *) a->buf[curr];
1687 int group1[] = {3, 1, 3, 1, 3, 5};
1688 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1689 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1690 int group2[] = {3, 1, 1};
1691 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1692 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1693 "Memory utilization (3)", "Memory utilization (4)",
1694 "Memory utilization (5)", "Memory utilization (6)"};
1695 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1696 "Swap utilization (3)"};
1697 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1698 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1699 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1701 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1703 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1704 static double *spmin, *spmax;
1706 static int *outsize;
1710 unsigned long long nousedmem;
1712 if (action & F_BEGIN) {
1714 * Allocate arrays that will contain the graphs data
1715 * and the min/max values.
1717 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1720 if (action & F_MAIN) {
1721 /* Check for min/max values */
1722 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1723 itv, spmin, spmax, g_fields);
1724 /* Compute %memused min/max values */
1725 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1726 if (nousedmem > smc->tlmkb) {
1727 nousedmem = smc->tlmkb;
1729 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1730 if (tval > *(spmax + 3)) {
1731 *(spmax + 3) = tval;
1733 if (tval < *(spmin + 3)) {
1734 *(spmin + 3) = tval;
1736 /* Compute %commit min/max values */
1737 tval = (smc->tlmkb + smc->tlskb) ?
1738 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1739 if (tval > *(spmax + 7)) {
1740 *(spmax + 7) = tval;
1742 if (tval < *(spmin + 7)) {
1743 *(spmin + 7) = tval;
1745 /* Compute %swpused min/max values */
1747 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1748 if (tval > *(spmax + 19)) {
1749 *(spmax + 19) = tval;
1751 if (tval < *(spmin + 19)) {
1752 *(spmin + 19) = tval;
1754 /* Compute %swpcad min/max values */
1755 tval = (smc->tlskb - smc->frskb) ?
1756 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1757 if (tval > *(spmax + 20)) {
1758 *(spmax + 20) = tval;
1760 if (tval < *(spmin + 20)) {
1761 *(spmin + 20) = tval;
1763 /* Compute memused min/max values in MB */
1764 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1765 if (tval > *(spmax + 2)) {
1766 *(spmax + 2) = tval;
1768 if (tval < *(spmin + 2)) {
1769 *(spmin + 2) = tval;
1771 /* Compute swpused min/max values in MB */
1772 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1773 if (tval > *(spmax + 17)) {
1774 *(spmax + 17) = tval;
1776 if (tval < *(spmin + 17)) {
1777 *(spmin + 17) = tval;
1781 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1782 ((double) smc->frmkb) / 1024,
1783 out, outsize, svg_p->restart);
1785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1786 ((double) (smc->tlmkb - nousedmem)) / 1024,
1787 out + 2, outsize + 2, svg_p->restart);
1789 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1790 ((double) smc->availablekb) / 1024,
1791 out + 1, outsize + 1, svg_p->restart);
1793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1794 ((double) smc->bufkb) / 1024,
1795 out + 4, outsize + 4, svg_p->restart);
1797 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1798 ((double) smc->camkb) / 1024,
1799 out + 5, outsize + 5, svg_p->restart);
1801 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1802 ((double) smc->frskb) / 1024,
1803 out + 16, outsize + 16, svg_p->restart);
1805 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1806 ((double) (smc->tlskb - smc->frskb)) / 1024,
1807 out + 17, outsize + 17, svg_p->restart);
1809 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1810 ((double) smc->caskb) / 1024,
1811 out + 18, outsize + 18, svg_p->restart);
1813 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1814 ((double) smc->comkb) / 1024,
1815 out + 6, outsize + 6, svg_p->restart);
1817 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1818 ((double) smc->activekb) / 1024,
1819 out + 8, outsize + 8, svg_p->restart);
1821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1822 ((double) smc->inactkb) / 1024,
1823 out + 9, outsize + 9, svg_p->restart);
1825 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1826 ((double) smc->dirtykb) / 1024,
1827 out + 10, outsize + 10, svg_p->restart);
1829 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1830 ((double) smc->anonpgkb) / 1024,
1831 out + 11, outsize + 11, svg_p->restart);
1833 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1834 ((double) smc->slabkb) / 1024,
1835 out + 12, outsize + 12, svg_p->restart);
1837 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1838 ((double) smc->kstackkb) / 1024,
1839 out + 13, outsize + 13, svg_p->restart);
1841 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1842 ((double) smc->pgtblkb) / 1024,
1843 out + 14, outsize + 14, svg_p->restart);
1845 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1846 ((double) smc->vmusedkb) / 1024,
1847 out + 15, outsize + 15, svg_p->restart);
1849 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1852 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1853 out + 3, outsize + 3, svg_p->dt);
1855 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1857 (smc->tlmkb + smc->tlskb) ?
1858 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1859 out + 7, outsize + 7, svg_p->dt);
1861 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1864 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1865 out + 19, outsize + 19, svg_p->dt);
1867 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1869 (smc->tlskb - smc->frskb) ?
1870 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1871 out + 20, outsize + 20, svg_p->dt);
1874 if (action & F_END) {
1876 /* Conversion kB -> MB */
1877 for (i = 0; i < 17; i++) {
1878 *(spmin + g_fields[i]) /= 1024;
1879 *(spmax + g_fields[i]) /= 1024;
1882 if (DISPLAY_MEMORY(a->opt_flags)) {
1883 if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1884 g_type1, title1, g_title1, NULL, group1,
1885 spmin, spmax, out, outsize, svg_p, record_hdr,
1886 FALSE, a->id, xid)) {
1891 if (DISPLAY_SWAP(a->opt_flags)) {
1892 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1893 spmin + 16, spmax + 16, out + 16, outsize + 16,
1894 svg_p, record_hdr, FALSE, a->id, xid);
1897 /* Free remaining structures */
1898 free_graphs(out, outsize, spmin, spmax);
1903 ***************************************************************************
1904 * Display kernel tables statistics in SVG.
1907 * @a Activity structure with statistics.
1908 * @curr Index in array for current sample statistics.
1909 * @action Action expected from current function.
1910 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1911 * flag indicating that a restart record has been previously
1912 * found (.@restart) and time used for the X axis origin
1914 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1915 * @record_hdr Pointer on record header of current stats sample.
1916 ***************************************************************************
1918 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1919 unsigned long long itv, struct record_header *record_hdr)
1921 struct stats_ktables
1922 *skc = (struct stats_ktables *) a->buf[curr];
1923 int group[] = {3, 1};
1924 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1925 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1926 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1928 int g_fields[] = {1, 2, 0, 3};
1929 static double *spmin, *spmax;
1931 static int *outsize;
1933 if (action & F_BEGIN) {
1935 * Allocate arrays that will contain the graphs data
1936 * and the min/max values.
1938 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1941 if (action & F_MAIN) {
1942 /* Check for min/max values */
1943 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1944 itv, spmin, spmax, g_fields);
1946 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1947 (unsigned long long) skc->dentry_stat,
1948 out, outsize, svg_p->restart);
1950 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1951 (unsigned long long) skc->file_used,
1952 out + 1, outsize + 1, svg_p->restart);
1954 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1955 (unsigned long long) skc->inode_used,
1956 out + 2, outsize + 2, svg_p->restart);
1958 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1959 (unsigned long long) skc->pty_nr,
1960 out + 3, outsize + 3, svg_p->restart);
1963 if (action & F_END) {
1964 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1965 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1967 /* Free remaining structures */
1968 free_graphs(out, outsize, spmin, spmax);
1973 ***************************************************************************
1974 * Display queue and load statistics in SVG.
1977 * @a Activity structure with statistics.
1978 * @curr Index in array for current sample statistics.
1979 * @action Action expected from current function.
1980 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1981 * flag indicating that a restart record has been previously
1982 * found (.@restart) and time used for the X axis origin
1984 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1985 * @record_hdr Pointer on record header of current stats sample.
1986 ***************************************************************************
1988 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1989 unsigned long long itv, struct record_header *record_hdr)
1992 *sqc = (struct stats_queue *) a->buf[curr];
1993 int group[] = {2, 1, 3};
1994 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1995 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
1996 char *g_title[] = {"~runq-sz", "~blocked",
1998 "ldavg-1", "ldavg-5", "ldavg-15"};
1999 int g_fields[] = {0, 1, 2, 3, 4, 5};
2000 static double *spmin, *spmax;
2002 static int *outsize;
2004 if (action & F_BEGIN) {
2006 * Allocate arrays that will contain the graphs data
2007 * and the min/max values.
2009 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2012 if (action & F_MAIN) {
2013 /* Check for min/max values */
2014 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2015 itv, spmin, spmax, g_fields);
2017 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2018 (unsigned long long) sqc->nr_running,
2019 out, outsize, svg_p->restart);
2021 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2022 (unsigned long long) sqc->procs_blocked,
2023 out + 1, outsize + 1, svg_p->restart);
2025 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2026 (unsigned long long) sqc->nr_threads,
2027 out + 2, outsize + 2, svg_p->restart);
2029 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2030 (double) sqc->load_avg_1 / 100,
2031 out + 3, outsize + 3, svg_p->restart);
2033 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2034 (double) sqc->load_avg_5 / 100,
2035 out + 4, outsize + 4, svg_p->restart);
2037 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2038 (double) sqc->load_avg_15 / 100,
2039 out + 5, outsize + 5, svg_p->restart);
2042 if (action & F_END) {
2043 /* Fix min/max values for load average */
2044 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2045 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2046 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2048 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2049 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2051 /* Free remaining structures */
2052 free_graphs(out, outsize, spmin, spmax);
2057 ***************************************************************************
2058 * Display disk statistics in SVG.
2061 * @a Activity structure with statistics.
2062 * @curr Index in array for current sample statistics.
2063 * @action Action expected from current function.
2064 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2065 * flag indicating that a restart record has been previously
2066 * found (.@restart) and time used for the X axis origin
2068 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2069 * @record_hdr Pointer on record header of current stats sample.
2070 ***************************************************************************
2072 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2073 unsigned long long itv, struct record_header *record_hdr)
2075 struct stats_disk *sdc, *sdp, sdpzero;
2076 struct ext_disk_stats xds;
2077 int group[] = {1, 3, 2, 1, 1};
2078 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2079 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2080 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2081 "Block devices statistics (3)", "Block devices statistics (4)",
2082 "Block devices statistics (5)"};
2083 char *g_title[] = {"tps",
2084 "rkB/s", "wkB/s", "dkB/s",
2085 "areq-sz", "aqu-sz",
2088 int g_fields[] = {0, 1, 2};
2090 unsigned int local_types_nr[] = {1, 0, 0};
2091 static double *spmin, *spmax;
2093 static int *outsize;
2094 char *dev_name, *item_name;
2095 double rkB, wkB, dkB, aqusz;
2096 int i, j, k, pos, restart, *unregistered;
2098 if (action & F_BEGIN) {
2100 * Allocate arrays (#0..7) that will contain the graphs data
2101 * and the min/max values.
2102 * Also allocate one additional array (#8) for each disk device:
2103 * out + 8 will contain the device name (WWN id, pretty name or devm-n),
2104 * outsize + 8 will contain a positive value (TRUE) if the device
2105 * has either still not been registered, or has been unregistered.
2107 out = allocate_graph_lines(nr_arrays * a->item_list_sz, &outsize, &spmin, &spmax);
2110 if (action & F_MAIN) {
2111 memset(&sdpzero, 0, STATS_DISK_SIZE);
2112 restart = svg_p->restart;
2114 * Mark previously registered devices as now
2115 * possibly unregistered for all graphs.
2117 for (k = 0; k < a->item_list_sz; k++) {
2118 unregistered = outsize + k * nr_arrays + 8;
2119 if (*unregistered == FALSE) {
2120 *unregistered = MAYBE;
2124 /* For each device structure */
2125 for (i = 0; i < a->nr[curr]; i++) {
2126 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2128 /* Get device name */
2129 dev_name = get_device_name(sdc->major, sdc->minor, sdc->wwn, sdc->part_nr,
2130 DISPLAY_PRETTY(flags), DISPLAY_PERSIST_NAME_S(flags),
2131 USE_STABLE_ID(flags), NULL);
2133 if (a->item_list != NULL) {
2134 /* A list of devices has been entered on the command line */
2135 if (!search_list_item(a->item_list, dev_name))
2136 /* Device not found */
2140 /* Look for corresponding graph */
2141 for (k = 0; k < a->item_list_sz; k++) {
2142 item_name = *(out + k * nr_arrays + 8);
2143 if (!strcmp(dev_name, item_name))
2147 if (k == a->item_list_sz) {
2148 /* Graph not found: Look for first free entry */
2149 for (k = 0; k < a->item_list_sz; k++) {
2150 item_name = *(out + k * nr_arrays + 8);
2151 if (!strcmp(item_name, ""))
2154 if (k == a->item_list_sz) {
2155 /* No free graph entry: Ignore it (should never happen) */
2157 fprintf(stderr, "%s: Name=%s major=%d minor=%d\n",
2158 __FUNCTION__, dev_name, sdc->major, sdc->minor);
2163 pos = k * nr_arrays;
2164 unregistered = outsize + pos + 8;
2167 * If current device was marked as previously unregistered,
2168 * then set restart variable to TRUE so that the graph will be
2169 * discontinuous, and mark it as now registered.
2171 if (*unregistered == TRUE) {
2174 *unregistered = FALSE;
2176 item_name = *(out + pos + 8);
2177 if (!item_name[0]) {
2178 /* Save device name (WWN id or pretty name) if not already done */
2179 strncpy(item_name, dev_name, CHUNKSIZE);
2180 item_name[CHUNKSIZE - 1] = '\0';
2183 j = check_disk_reg(a, curr, !curr, i);
2185 /* This is a newly registered interface. Previous stats are zero */
2189 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2192 /* Check for min/max values */
2193 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2194 itv, spmin + pos, spmax + pos, g_fields);
2196 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2197 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2198 dkB = S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2;
2199 if (rkB < *(spmin + pos + 1)) {
2200 *(spmin + pos + 1) = rkB;
2202 if (rkB > *(spmax + pos + 1)) {
2203 *(spmax + pos + 1) = rkB;
2205 if (wkB < *(spmin + pos + 2)) {
2206 *(spmin + pos + 2) = wkB;
2208 if (wkB > *(spmax + pos + 2)) {
2209 *(spmax + pos + 2) = wkB;
2211 if (dkB < *(spmin + pos + 3)) {
2212 *(spmin + pos + 3) = dkB;
2214 if (dkB > *(spmax + pos + 3)) {
2215 *(spmax + pos + 3) = dkB;
2218 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2219 if ((xds.arqsz / 2) < *(spmin + pos + 4)) {
2220 *(spmin + pos + 4) = xds.arqsz / 2;
2222 if ((xds.arqsz / 2) > *(spmax + pos + 4)) {
2223 *(spmax + pos + 4) = xds.arqsz / 2;
2225 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2226 if (aqusz < *(spmin + pos + 5)) {
2227 *(spmin + pos + 5) = aqusz;
2229 if (aqusz > *(spmax + pos + 5)) {
2230 *(spmax + pos + 5) = aqusz;
2232 if (xds.await < *(spmin + pos + 6)) {
2233 *(spmin + pos + 6) = xds.await;
2235 if (xds.await > *(spmax + pos + 6)) {
2236 *(spmax + pos + 6) = xds.await;
2238 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2239 *(spmin + pos + 7) = xds.util / 10.0;
2241 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2242 *(spmax + pos + 7) = xds.util / 10.0;
2246 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2247 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2248 out + pos, outsize + pos, restart);
2250 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2251 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2252 out + pos + 1, outsize + pos + 1, restart);
2254 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2255 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2256 out + pos + 2, outsize + pos + 2, restart);
2258 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2259 S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2,
2260 out + pos + 3, outsize + pos + 3, restart);
2262 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2264 out + pos + 4, outsize + pos + 4, restart);
2266 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2268 out + pos + 5, outsize + pos + 5, restart);
2270 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2272 out + pos + 6, outsize + pos + 6, restart);
2274 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2275 0.0, xds.util / 10.0,
2276 out + pos + 7, outsize + pos + 7, svg_p->dt);
2279 /* Mark devices not seen here as now unregistered */
2280 for (k = 0; k < a->item_list_sz; k++) {
2281 unregistered = outsize + k * nr_arrays + 8;
2282 if (*unregistered != FALSE) {
2283 *unregistered = TRUE;
2288 if (action & F_END) {
2291 for (i = 0; i < a->item_list_sz; i++) {
2292 /* Check if there is something to display */
2293 pos = i * nr_arrays;
2297 item_name = *(out + pos + 8);
2298 if (draw_activity_graphs(a->g_nr, g_type,
2299 title, g_title, item_name, group,
2300 spmin + pos, spmax + pos, out + pos, outsize + pos,
2301 svg_p, record_hdr, FALSE, a->id, xid)) {
2306 /* Free remaining structures */
2307 free_graphs(out, outsize, spmin, spmax);
2312 ***************************************************************************
2313 * Display network interfaces statistics in SVG.
2316 * @a Activity structure with statistics.
2317 * @curr Index in array for current sample statistics.
2318 * @action Action expected from current function.
2319 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2320 * flag indicating that a restart record has been previously
2321 * found (.@restart) and time used for the X axis origin
2323 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2324 * @record_hdr Pointer on record header of current stats sample.
2325 ***************************************************************************
2327 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2328 unsigned long long itv, struct record_header *record_hdr)
2330 struct stats_net_dev *sndc, *sndp, sndzero;
2331 int group[] = {2, 2, 3, 1};
2332 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2334 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2335 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2336 char *g_title[] = {"rxpck/s", "txpck/s",
2338 "rxcmp/s", "txcmp/s", "rxmcst/s",
2340 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2341 unsigned int local_types_nr[] = {7, 0, 0};
2342 static double *spmin, *spmax;
2344 static int *outsize;
2346 double rxkb, txkb, ifutil;
2347 int i, j, k, pos, restart, *unregistered;
2349 if (action & F_BEGIN) {
2351 * Allocate arrays (#0..7) that will contain the graphs data
2352 * and the min/max values.
2353 * Also allocate one additional array (#8) for each interface:
2354 * out + 8 will contain the interface name,
2355 * outsize + 8 will contain a positive value (TRUE) if the interface
2356 * has either still not been registered, or has been unregistered.
2358 out = allocate_graph_lines(9 * a->item_list_sz, &outsize, &spmin, &spmax);
2361 if (action & F_MAIN) {
2362 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2363 restart = svg_p->restart;
2365 * Mark previously registered interfaces as now
2366 * possibly unregistered for all graphs.
2368 for (k = 0; k < a->item_list_sz; k++) {
2369 unregistered = outsize + k * 9 + 8;
2370 if (*unregistered == FALSE) {
2371 *unregistered = MAYBE;
2375 /* For each network interfaces structure */
2376 for (i = 0; i < a->nr[curr]; i++) {
2377 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2379 if (a->item_list != NULL) {
2380 /* A list of devices has been entered on the command line */
2381 if (!search_list_item(a->item_list, sndc->interface))
2382 /* Device not found */
2386 /* Look for corresponding graph */
2387 for (k = 0; k < a->item_list_sz; k++) {
2388 item_name = *(out + k * 9 + 8);
2389 if (!strcmp(sndc->interface, item_name))
2393 if (k == a->item_list_sz) {
2394 /* Graph not found: Look for first free entry */
2395 for (k = 0; k < a->item_list_sz; k++) {
2396 item_name = *(out + k * 9 + 8);
2397 if (!strcmp(item_name, ""))
2400 if (k == a->item_list_sz) {
2401 /* No free graph entry: Ignore it (should never happen) */
2403 fprintf(stderr, "%s: Name=%s\n",
2404 __FUNCTION__, sndc->interface);
2410 unregistered = outsize + pos + 8;
2412 j = check_net_dev_reg(a, curr, !curr, i);
2414 /* This is a newly registered interface. Previous stats are zero */
2418 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2422 * If current interface was marked as previously unregistered,
2423 * then set restart variable to TRUE so that the graph will be
2424 * discontinuous, and mark it as now registered.
2426 if (*unregistered == TRUE) {
2429 *unregistered = FALSE;
2431 item_name = *(out + pos + 8);
2432 if (!item_name[0]) {
2433 /* Save network interface name (if not already done) */
2434 strncpy(item_name, sndc->interface, CHUNKSIZE);
2435 item_name[CHUNKSIZE - 1] = '\0';
2438 /* Check for min/max values */
2439 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2440 itv, spmin + pos, spmax + pos, g_fields);
2442 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2443 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2444 ifutil = compute_ifutil(sndc, rxkb, txkb);
2445 if (ifutil < *(spmin + pos + 7)) {
2446 *(spmin + pos + 7) = ifutil;
2448 if (ifutil > *(spmax + pos + 7)) {
2449 *(spmax + pos + 7) = ifutil;
2453 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2454 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2455 out + pos, outsize + pos, restart);
2457 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2458 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2459 out + pos + 1, outsize + pos + 1, restart);
2461 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2463 out + pos + 2, outsize + pos + 2, restart);
2465 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2467 out + pos + 3, outsize + pos + 3, restart);
2469 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2470 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2471 out + pos + 4, outsize + pos + 4, restart);
2473 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2474 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2475 out + pos + 5, outsize + pos + 5, restart);
2477 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2478 S_VALUE(sndp->multicast, sndc->multicast, itv),
2479 out + pos + 6, outsize + pos + 6, restart);
2481 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2483 out + pos + 7, outsize + pos + 7, svg_p->dt);
2486 /* Mark interfaces not seen here as now unregistered */
2487 for (k = 0; k < a->item_list_sz; k++) {
2488 unregistered = outsize + k * 9 + 8;
2489 if (*unregistered != FALSE) {
2490 *unregistered = TRUE;
2495 if (action & F_END) {
2498 for (i = 0; i < a->item_list_sz; i++) {
2500 * Check if there is something to display.
2501 * Don't test sndc->interface because maybe the network
2502 * interface has been registered later.
2508 /* Recalculate min and max values in kB, not in B */
2509 *(spmin + pos + 2) /= 1024;
2510 *(spmax + pos + 2) /= 1024;
2511 *(spmin + pos + 3) /= 1024;
2512 *(spmax + pos + 3) /= 1024;
2514 item_name = *(out + pos + 8);
2515 if (draw_activity_graphs(a->g_nr, g_type,
2516 title, g_title, item_name, group,
2517 spmin + pos, spmax + pos, out + pos, outsize + pos,
2518 svg_p, record_hdr, FALSE, a->id, xid)) {
2523 /* Free remaining structures */
2524 free_graphs(out, outsize, spmin, spmax);
2529 ***************************************************************************
2530 * Display network interfaces errors statistics in SVG.
2533 * @a Activity structure with statistics.
2534 * @curr Index in array for current sample statistics.
2535 * @action Action expected from current function.
2536 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2537 * flag indicating that a restart record has been previously
2538 * found (.@restart) and time used for the X axis origin
2540 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2541 * @record_hdr Pointer on record header of current stats sample.
2542 ***************************************************************************
2544 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2545 unsigned long long itv, struct record_header *record_hdr)
2547 struct stats_net_edev *snedc, *snedp, snedzero;
2548 int group[] = {2, 2, 2, 3};
2549 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2551 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2552 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2553 char *g_title[] = {"rxerr/s", "txerr/s",
2554 "rxdrop/s", "txdrop/s",
2555 "rxfifo/s", "txfifo/s",
2556 "coll/s", "txcarr/s", "rxfram/s"};
2557 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2558 static double *spmin, *spmax;
2560 static int *outsize;
2562 int i, j, k, pos, restart, *unregistered;
2564 if (action & F_BEGIN) {
2566 * Allocate arrays (#0..8) that will contain the graphs data
2567 * and the min/max values.
2568 * Also allocate one additional array (#9) for each interface:
2569 * out + 9 will contain the interface name,
2570 * outsize + 9 will contain a positive value (TRUE) if the interface
2571 * has either still not been registered, or has been unregistered.
2573 out = allocate_graph_lines(10 * a->item_list_sz, &outsize, &spmin, &spmax);
2576 if (action & F_MAIN) {
2577 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2578 restart = svg_p->restart;
2580 * Mark previously registered interfaces as now
2581 * possibly unregistered for all graphs.
2583 for (k = 0; k < a->item_list_sz; k++) {
2584 unregistered = outsize + k * 10 + 9;
2585 if (*unregistered == FALSE) {
2586 *unregistered = MAYBE;
2590 /* For each network interfaces structure */
2591 for (i = 0; i < a->nr[curr]; i++) {
2592 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2593 if (!strcmp(snedc->interface, ""))
2594 /* Empty structure: This is the end of the list */
2597 if (a->item_list != NULL) {
2598 /* A list of devices has been entered on the command line */
2599 if (!search_list_item(a->item_list, snedc->interface))
2600 /* Device not found */
2604 /* Look for corresponding graph */
2605 for (k = 0; k < a->item_list_sz; k++) {
2606 item_name = *(out + k * 10 + 9);
2607 if (!strcmp(snedc->interface, item_name))
2611 if (k == a->item_list_sz) {
2612 /* Graph not found: Look for first free entry */
2613 for (k = 0; k < a->item_list_sz; k++) {
2614 item_name = *(out + k * 10 + 9);
2615 if (!strcmp(item_name, ""))
2618 if (k == a->item_list_sz) {
2619 /* No free graph entry: Ignore it (should never happen) */
2621 fprintf(stderr, "%s: Name=%s\n",
2622 __FUNCTION__, snedc->interface);
2629 unregistered = outsize + pos + 9;
2631 j = check_net_edev_reg(a, curr, !curr, i);
2633 /* This is a newly registered interface. Previous stats are zero */
2637 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2641 * If current interface was marked as previously unregistered,
2642 * then set restart variable to TRUE so that the graph will be
2643 * discontinuous, and mark it as now registered.
2645 if (*unregistered == TRUE) {
2648 *unregistered = FALSE;
2650 item_name = *(out + pos + 9);
2651 if (!item_name[0]) {
2652 /* Save network interface name (if not already done) */
2653 strncpy(item_name, snedc->interface, CHUNKSIZE);
2654 item_name[CHUNKSIZE - 1] = '\0';
2657 /* Check for min/max values */
2658 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2659 itv, spmin + pos, spmax + pos, g_fields);
2662 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2663 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2664 out + pos, outsize + pos, restart);
2666 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2667 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2668 out + pos + 1, outsize + pos + 1, restart);
2670 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2671 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2672 out + pos + 2, outsize + pos + 2, restart);
2674 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2675 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2676 out + pos + 3, outsize + pos + 3, restart);
2678 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2679 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2680 out + pos + 4, outsize + pos + 4, restart);
2682 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2683 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2684 out + pos + 5, outsize + pos + 5, restart);
2686 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2687 S_VALUE(snedp->collisions, snedc->collisions, itv),
2688 out + pos + 6, outsize + pos + 6, restart);
2690 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2691 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2692 out + pos + 7, outsize + pos + 7, restart);
2694 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2695 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2696 out + pos + 8, outsize + pos + 8, restart);
2699 /* Mark interfaces not seen here as now unregistered */
2700 for (k = 0; k < a->item_list_sz; k++) {
2701 unregistered = outsize + k * 10 + 9;
2702 if (*unregistered != FALSE) {
2703 *unregistered = TRUE;
2708 if (action & F_END) {
2711 for (i = 0; i < a->item_list_sz; i++) {
2713 * Check if there is something to display.
2714 * Don't test snedc->interface because maybe the network
2715 * interface has been registered later.
2721 item_name = *(out + pos + 9);
2722 if (draw_activity_graphs(a->g_nr, g_type,
2723 title, g_title, item_name, group,
2724 spmin + pos, spmax + pos, out + pos, outsize + pos,
2725 svg_p, record_hdr, FALSE, a->id, xid)) {
2730 /* Free remaining structures */
2731 free_graphs(out, outsize, spmin, spmax);
2736 ***************************************************************************
2737 * Display NFS client statistics in SVG.
2740 * @a Activity structure with statistics.
2741 * @curr Index in array for current sample statistics.
2742 * @action Action expected from current function.
2743 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2744 * flag indicating that a restart record has been previously
2745 * found (.@restart) and time used for the X axis origin
2747 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2748 * @record_hdr Pointer on record header of current stats sample.
2749 ***************************************************************************
2751 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2752 unsigned long long itv, struct record_header *record_hdr)
2754 struct stats_net_nfs
2755 *snnc = (struct stats_net_nfs *) a->buf[curr],
2756 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2757 int group[] = {2, 2, 2};
2758 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2759 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2760 "NFS client statistics (3)"};
2761 char *g_title[] = {"call/s", "retrans/s",
2762 "read/s", "write/s",
2763 "access/s", "getatt/s"};
2764 int g_fields[] = {0, 1, 2, 3, 4, 5};
2765 static double *spmin, *spmax;
2767 static int *outsize;
2769 if (action & F_BEGIN) {
2771 * Allocate arrays that will contain the graphs data
2772 * and the min/max values.
2774 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2777 if (action & F_MAIN) {
2778 /* Check for min/max values */
2779 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2780 itv, spmin, spmax, g_fields);
2783 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2784 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2785 out, outsize, svg_p->restart);
2787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2788 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2789 out + 1, outsize + 1, svg_p->restart);
2791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2792 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2793 out + 2, outsize + 2, svg_p->restart);
2795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2796 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2797 out + 3, outsize + 3, svg_p->restart);
2799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2800 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2801 out + 4, outsize + 4, svg_p->restart);
2803 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2804 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2805 out + 5, outsize + 5, svg_p->restart);
2808 if (action & F_END) {
2809 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2810 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2812 /* Free remaining structures */
2813 free_graphs(out, outsize, spmin, spmax);
2818 ***************************************************************************
2819 * Display NFS server statistics in SVG.
2822 * @a Activity structure with statistics.
2823 * @curr Index in array for current sample statistics.
2824 * @action Action expected from current function.
2825 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2826 * flag indicating that a restart record has been previously
2827 * found (.@restart) and time used for the X axis origin
2829 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2830 * @record_hdr Pointer on record header of current stats sample.
2831 ***************************************************************************
2833 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2834 unsigned long long itv, struct record_header *record_hdr)
2836 struct stats_net_nfsd
2837 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2838 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2839 int group[] = {2, 3, 2, 2, 2};
2840 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2841 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2842 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2843 "NFS server statistics (3)", "NFS server statistics (4)",
2844 "NFS server statistics (5)"};
2845 char *g_title[] = {"scall/s", "badcall/s",
2846 "packet/s", "udp/s", "tcp/s",
2848 "sread/s", "swrite/s",
2849 "saccess/s", "sgetatt/s"};
2850 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2851 static double *spmin, *spmax;
2853 static int *outsize;
2855 if (action & F_BEGIN) {
2857 * Allocate arrays that will contain the graphs data
2858 * and the min/max values.
2860 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2863 if (action & F_MAIN) {
2864 /* Check for min/max values */
2865 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2866 itv, spmin, spmax, g_fields);
2869 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2870 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2871 out, outsize, svg_p->restart);
2873 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2874 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2875 out + 1, outsize + 1, svg_p->restart);
2877 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2878 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2879 out + 2, outsize + 2, svg_p->restart);
2881 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2882 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2883 out + 3, outsize + 3, svg_p->restart);
2885 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2886 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2887 out + 4, outsize + 4, svg_p->restart);
2889 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2890 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2891 out + 5, outsize + 5, svg_p->restart);
2893 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2894 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2895 out + 6, outsize + 6, svg_p->restart);
2897 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2898 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2899 out + 7, outsize + 7, svg_p->restart);
2901 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2902 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2903 out + 8, outsize + 8, svg_p->restart);
2905 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2906 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2907 out + 9, outsize + 9, svg_p->restart);
2909 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2910 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2911 out + 10, outsize + 10, svg_p->restart);
2914 if (action & F_END) {
2915 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2916 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2918 /* Free remaining structures */
2919 free_graphs(out, outsize, spmin, spmax);
2924 ***************************************************************************
2925 * Display socket statistics in SVG.
2928 * @a Activity structure with statistics.
2929 * @curr Index in array for current sample statistics.
2930 * @action Action expected from current function.
2931 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2932 * flag indicating that a restart record has been previously
2933 * found (.@restart) and time used for the X axis origin
2935 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2936 * @record_hdr Pointer on record header of current stats sample.
2937 ***************************************************************************
2939 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2940 unsigned long long itv, struct record_header *record_hdr)
2942 struct stats_net_sock
2943 *snsc = (struct stats_net_sock *) a->buf[curr];
2944 int group[] = {1, 5};
2945 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2946 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2947 char *g_title[] = {"~totsck",
2948 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2949 int g_fields[] = {0, 1, 5, 2, 3, 4};
2950 static double *spmin, *spmax;
2952 static int *outsize;
2954 if (action & F_BEGIN) {
2956 * Allocate arrays that will contain the graphs data
2957 * and the min/max values.
2959 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2962 if (action & F_MAIN) {
2963 /* Check for min/max values */
2964 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2965 itv, spmin, spmax, g_fields);
2967 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2968 (unsigned long long) snsc->sock_inuse,
2969 out, outsize, svg_p->restart);
2971 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2972 (unsigned long long) snsc->tcp_inuse,
2973 out + 1, outsize + 1, svg_p->restart);
2975 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2976 (unsigned long long) snsc->udp_inuse,
2977 out + 2, outsize + 2, svg_p->restart);
2979 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2980 (unsigned long long) snsc->raw_inuse,
2981 out + 3, outsize + 3, svg_p->restart);
2983 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2984 (unsigned long long) snsc->frag_inuse,
2985 out + 4, outsize + 4, svg_p->restart);
2987 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2988 (unsigned long long) snsc->tcp_tw,
2989 out + 5, outsize + 5, svg_p->restart);
2992 if (action & F_END) {
2993 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2994 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2996 /* Free remaining structures */
2997 free_graphs(out, outsize, spmin, spmax);
3002 ***************************************************************************
3003 * Display IPv4 traffic statistics in SVG.
3006 * @a Activity structure with statistics.
3007 * @curr Index in array for current sample statistics.
3008 * @action Action expected from current function.
3009 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3010 * flag indicating that a restart record has been previously
3011 * found (.@restart) and time used for the X axis origin
3013 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3014 * @record_hdr Pointer on record header of current stats sample.
3015 ***************************************************************************
3017 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3018 unsigned long long itv, struct record_header *record_hdr)
3021 *snic = (struct stats_net_ip *) a->buf[curr],
3022 *snip = (struct stats_net_ip *) a->buf[!curr];
3023 int group[] = {4, 2, 2};
3024 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3025 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
3026 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
3027 "asmrq/s", "asmok/s",
3028 "fragok/s", "fragcrt/s"};
3029 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3030 static double *spmin, *spmax;
3032 static int *outsize;
3034 if (action & F_BEGIN) {
3036 * Allocate arrays that will contain the graphs data
3037 * and the min/max values.
3039 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3042 if (action & F_MAIN) {
3043 /* Check for min/max values */
3044 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3045 itv, spmin, spmax, g_fields);
3048 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3049 S_VALUE(snip->InReceives, snic->InReceives, itv),
3050 out, outsize, svg_p->restart);
3052 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3053 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
3054 out + 1, outsize + 1, svg_p->restart);
3056 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3057 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
3058 out + 2, outsize + 2, svg_p->restart);
3060 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3061 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3062 out + 3, outsize + 3, svg_p->restart);
3064 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3065 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3066 out + 4, outsize + 4, svg_p->restart);
3068 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3069 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3070 out + 5, outsize + 5, svg_p->restart);
3072 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3073 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3074 out + 6, outsize + 6, svg_p->restart);
3076 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3077 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3078 out + 7, outsize + 7, svg_p->restart);
3081 if (action & F_END) {
3082 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3083 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3085 /* Free remaining structures */
3086 free_graphs(out, outsize, spmin, spmax);
3091 ***************************************************************************
3092 * Display IPv4 traffic errors statistics in SVG.
3095 * @a Activity structure with statistics.
3096 * @curr Index in array for current sample statistics.
3097 * @action Action expected from current function.
3098 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3099 * flag indicating that a restart record has been previously
3100 * found (.@restart) and time used for the X axis origin
3102 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3103 * @record_hdr Pointer on record header of current stats sample.
3104 ***************************************************************************
3106 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3107 unsigned long long itv, struct record_header *record_hdr)
3109 struct stats_net_eip
3110 *sneic = (struct stats_net_eip *) a->buf[curr],
3111 *sneip = (struct stats_net_eip *) a->buf[!curr];
3112 int group[] = {3, 2, 3};
3113 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3114 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3115 "IPv4 traffic errors statistics (3)"};
3116 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3117 "idisc/s", "odisc/s",
3118 "onort/s", "asmf/s", "fragf/s"};
3119 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3120 static double *spmin, *spmax;
3122 static int *outsize;
3124 if (action & F_BEGIN) {
3126 * Allocate arrays that will contain the graphs data
3127 * and the min/max values.
3129 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3132 if (action & F_MAIN) {
3133 /* Check for min/max values */
3134 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3135 itv, spmin, spmax, g_fields);
3138 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3139 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3140 out, outsize, svg_p->restart);
3142 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3143 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3144 out + 1, outsize + 1, svg_p->restart);
3146 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3147 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3148 out + 2, outsize + 2, svg_p->restart);
3150 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3151 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3152 out + 3, outsize + 3, svg_p->restart);
3154 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3155 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3156 out + 4, outsize + 4, svg_p->restart);
3158 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3159 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3160 out + 5, outsize + 5, svg_p->restart);
3162 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3163 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3164 out + 6, outsize + 6, svg_p->restart);
3166 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3167 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3168 out + 7, outsize + 7, svg_p->restart);
3171 if (action & F_END) {
3172 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3173 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3175 /* Free remaining structures */
3176 free_graphs(out, outsize, spmin, spmax);
3181 ***************************************************************************
3182 * Display ICMPv4 traffic statistics in SVG.
3185 * @a Activity structure with statistics.
3186 * @curr Index in array for current sample statistics.
3187 * @action Action expected from current function.
3188 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3189 * flag indicating that a restart record has been previously
3190 * found (.@restart) and time used for the X axis origin
3192 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3193 * @record_hdr Pointer on record header of current stats sample.
3194 ***************************************************************************
3196 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3197 unsigned long long itv, struct record_header *record_hdr)
3199 struct stats_net_icmp
3200 *snic = (struct stats_net_icmp *) a->buf[curr],
3201 *snip = (struct stats_net_icmp *) a->buf[!curr];
3202 int group[] = {2, 4, 4, 4};
3203 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3205 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3206 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3207 char *g_title[] = {"imsg/s", "omsg/s",
3208 "iech/s", "iechr/s", "oech/s", "oechr/s",
3209 "itm/s", "itmr/s", "otm/s", "otmr/s",
3210 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3211 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3212 static double *spmin, *spmax;
3214 static int *outsize;
3216 if (action & F_BEGIN) {
3218 * Allocate arrays that will contain the graphs data
3219 * and the min/max values.
3221 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3224 if (action & F_MAIN) {
3225 /* Check for min/max values */
3226 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3227 itv, spmin, spmax, g_fields);
3230 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3231 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3232 out, outsize, svg_p->restart);
3234 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3235 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3236 out + 1, outsize + 1, svg_p->restart);
3238 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3239 S_VALUE(snip->InEchos, snic->InEchos, itv),
3240 out + 2, outsize + 2, svg_p->restart);
3242 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3243 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3244 out + 3, outsize + 3, svg_p->restart);
3246 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3247 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3248 out + 4, outsize + 4, svg_p->restart);
3250 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3251 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3252 out + 5, outsize + 5, svg_p->restart);
3254 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3255 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3256 out + 6, outsize + 6, svg_p->restart);
3258 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3259 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3260 out + 7, outsize + 7, svg_p->restart);
3262 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3263 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3264 out + 8, outsize + 8, svg_p->restart);
3266 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3267 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3268 out + 9, outsize + 9, svg_p->restart);
3270 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3271 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3272 out + 10, outsize + 10, svg_p->restart);
3274 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3275 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3276 out + 11, outsize + 11, svg_p->restart);
3278 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3279 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3280 out + 12, outsize + 12, svg_p->restart);
3282 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3283 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3284 out + 13, outsize + 13, svg_p->restart);
3287 if (action & F_END) {
3288 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3289 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3291 /* Free remaining structures */
3292 free_graphs(out, outsize, spmin, spmax);
3297 ***************************************************************************
3298 * Display ICMPv4 traffic errors statistics in SVG.
3301 * @a Activity structure with statistics.
3302 * @curr Index in array for current sample statistics.
3303 * @action Action expected from current function.
3304 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3305 * flag indicating that a restart record has been previously
3306 * found (.@restart) and time used for the X axis origin
3308 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3309 * @record_hdr Pointer on record header of current stats sample.
3310 ***************************************************************************
3312 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3313 unsigned long long itv, struct record_header *record_hdr)
3315 struct stats_net_eicmp
3316 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3317 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3318 int group[] = {2, 2, 2, 2, 2, 2};
3319 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3320 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3321 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3322 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3323 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3324 char *g_title[] = {"ierr/s", "oerr/s",
3325 "idstunr/s", "odstunr/s",
3326 "itmex/s", "otmex/s",
3327 "iparmpb/s", "oparmpb/s",
3328 "isrcq/s", "osrcq/s",
3329 "iredir/s", "oredir/s"};
3330 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3331 static double *spmin, *spmax;
3333 static int *outsize;
3335 if (action & F_BEGIN) {
3337 * Allocate arrays that will contain the graphs data
3338 * and the min/max values.
3340 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3343 if (action & F_MAIN) {
3344 /* Check for min/max values */
3345 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3346 itv, spmin, spmax, g_fields);
3349 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3350 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3351 out, outsize, svg_p->restart);
3353 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3354 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3355 out + 1, outsize + 1, svg_p->restart);
3357 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3358 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3359 out + 2, outsize + 2, svg_p->restart);
3361 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3362 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3363 out + 3, outsize + 3, svg_p->restart);
3365 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3366 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3367 out + 4, outsize + 4, svg_p->restart);
3369 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3370 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3371 out + 5, outsize + 5, svg_p->restart);
3373 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3374 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3375 out + 6, outsize + 6, svg_p->restart);
3377 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3378 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3379 out + 7, outsize + 7, svg_p->restart);
3381 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3382 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3383 out + 8, outsize + 8, svg_p->restart);
3385 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3386 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3387 out + 9, outsize + 9, svg_p->restart);
3389 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3390 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3391 out + 10, outsize + 10, svg_p->restart);
3393 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3394 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3395 out + 11, outsize + 11, svg_p->restart);
3398 if (action & F_END) {
3399 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3400 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3402 /* Free remaining structures */
3403 free_graphs(out, outsize, spmin, spmax);
3408 ***************************************************************************
3409 * Display TCPv4 traffic statistics in SVG.
3412 * @a Activity structure with statistics.
3413 * @curr Index in array for current sample statistics.
3414 * @action Action expected from current function.
3415 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3416 * flag indicating that a restart record has been previously
3417 * found (.@restart) and time used for the X axis origin
3419 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3420 * @record_hdr Pointer on record header of current stats sample.
3421 ***************************************************************************
3423 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3424 unsigned long long itv, struct record_header *record_hdr)
3426 struct stats_net_tcp
3427 *sntc = (struct stats_net_tcp *) a->buf[curr],
3428 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3429 int group[] = {2, 2};
3430 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3431 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3432 char *g_title[] = {"active/s", "passive/s",
3433 "iseg/s", "oseg/s"};
3434 int g_fields[] = {0, 1, 2, 3};
3435 static double *spmin, *spmax;
3437 static int *outsize;
3439 if (action & F_BEGIN) {
3441 * Allocate arrays that will contain the graphs data
3442 * and the min/max values.
3444 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3447 if (action & F_MAIN) {
3448 /* Check for min/max values */
3449 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3450 itv, spmin, spmax, g_fields);
3453 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3454 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3455 out, outsize, svg_p->restart);
3457 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3458 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3459 out + 1, outsize + 1, svg_p->restart);
3461 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3462 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3463 out + 2, outsize + 2, svg_p->restart);
3465 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3466 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3467 out + 3, outsize + 3, svg_p->restart);
3470 if (action & F_END) {
3471 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3472 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3474 /* Free remaining structures */
3475 free_graphs(out, outsize, spmin, spmax);
3480 ***************************************************************************
3481 * Display TCPv4 traffic errors statistics in SVG.
3484 * @a Activity structure with statistics.
3485 * @curr Index in array for current sample statistics.
3486 * @action Action expected from current function.
3487 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3488 * flag indicating that a restart record has been previously
3489 * found (.@restart) and time used for the X axis origin
3491 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3492 * @record_hdr Pointer on record header of current stats sample.
3493 ***************************************************************************
3495 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3496 unsigned long long itv, struct record_header *record_hdr)
3498 struct stats_net_etcp
3499 *snetc = (struct stats_net_etcp *) a->buf[curr],
3500 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3501 int group[] = {2, 3};
3502 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3503 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3504 char *g_title[] = {"atmptf/s", "estres/s",
3505 "retrans/s", "isegerr/s", "orsts/s"};
3506 int g_fields[] = {0, 1, 2, 3, 4};
3507 static double *spmin, *spmax;
3509 static int *outsize;
3511 if (action & F_BEGIN) {
3513 * Allocate arrays that will contain the graphs data
3514 * and the min/max values.
3516 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3519 if (action & F_MAIN) {
3520 /* Check for min/max values */
3521 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3522 itv, spmin, spmax, g_fields);
3525 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3526 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3527 out, outsize, svg_p->restart);
3529 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3530 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3531 out + 1, outsize + 1, svg_p->restart);
3533 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3534 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3535 out + 2, outsize + 2, svg_p->restart);
3537 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3538 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3539 out + 3, outsize + 3, svg_p->restart);
3541 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3542 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3543 out + 4, outsize + 4, svg_p->restart);
3546 if (action & F_END) {
3547 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3548 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3550 /* Free remaining structures */
3551 free_graphs(out, outsize, spmin, spmax);
3556 ***************************************************************************
3557 * Display UDPv4 traffic statistics in SVG.
3560 * @a Activity structure with statistics.
3561 * @curr Index in array for current sample statistics.
3562 * @action Action expected from current function.
3563 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3564 * flag indicating that a restart record has been previously
3565 * found (.@restart) and time used for the X axis origin
3567 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3568 * @record_hdr Pointer on record header of current stats sample.
3569 ***************************************************************************
3571 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3572 unsigned long long itv, struct record_header *record_hdr)
3574 struct stats_net_udp
3575 *snuc = (struct stats_net_udp *) a->buf[curr],
3576 *snup = (struct stats_net_udp *) a->buf[!curr];
3577 int group[] = {2, 2};
3578 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3579 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3580 char *g_title[] = {"idgm/s", "odgm/s",
3581 "noport/s", "idgmerr/s"};
3582 int g_fields[] = {0, 1, 2, 3};
3583 static double *spmin, *spmax;
3585 static int *outsize;
3587 if (action & F_BEGIN) {
3589 * Allocate arrays that will contain the graphs data
3590 * and the min/max values.
3592 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3595 if (action & F_MAIN) {
3596 /* Check for min/max values */
3597 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3598 itv, spmin, spmax, g_fields);
3601 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3602 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3603 out, outsize, svg_p->restart);
3605 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3606 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3607 out + 1, outsize + 1, svg_p->restart);
3609 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3610 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3611 out + 2, outsize + 2, svg_p->restart);
3613 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3614 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3615 out + 3, outsize + 3, svg_p->restart);
3618 if (action & F_END) {
3619 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3620 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3622 /* Free remaining structures */
3623 free_graphs(out, outsize, spmin, spmax);
3628 ***************************************************************************
3629 * Display IPV6 socket statistics in SVG.
3632 * @a Activity structure with statistics.
3633 * @curr Index in array for current sample statistics.
3634 * @action Action expected from current function.
3635 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3636 * flag indicating that a restart record has been previously
3637 * found (.@restart) and time used for the X axis origin
3639 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3640 * @record_hdr Pointer on record header of current stats sample.
3641 ***************************************************************************
3643 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3644 unsigned long long itv, struct record_header *record_hdr)
3646 struct stats_net_sock6
3647 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3649 int g_type[] = {SVG_LINE_GRAPH};
3650 char *title[] = {"IPv6 sockets statistics"};
3651 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3652 int g_fields[] = {0, 1, 2, 3};
3653 static double *spmin, *spmax;
3655 static int *outsize;
3657 if (action & F_BEGIN) {
3659 * Allocate arrays that will contain the graphs data
3660 * and the min/max values.
3662 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3665 if (action & F_MAIN) {
3666 /* Check for min/max values */
3667 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3668 itv, spmin, spmax, g_fields);
3670 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3671 (unsigned long long) snsc->tcp6_inuse,
3672 out, outsize, svg_p->restart);
3674 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3675 (unsigned long long) snsc->udp6_inuse,
3676 out + 1, outsize + 1, svg_p->restart);
3678 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3679 (unsigned long long) snsc->raw6_inuse,
3680 out + 2, outsize + 2, svg_p->restart);
3682 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3683 (unsigned long long) snsc->frag6_inuse,
3684 out + 3, outsize + 3, svg_p->restart);
3687 if (action & F_END) {
3688 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3689 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3691 /* Free remaining structures */
3692 free_graphs(out, outsize, spmin, spmax);
3697 ***************************************************************************
3698 * Display IPv6 traffic statistics in SVG.
3701 * @a Activity structure with statistics.
3702 * @curr Index in array for current sample statistics.
3703 * @action Action expected from current function.
3704 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3705 * flag indicating that a restart record has been previously
3706 * found (.@restart) and time used for the X axis origin
3708 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3709 * @record_hdr Pointer on record header of current stats sample.
3710 ***************************************************************************
3712 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3713 unsigned long long itv, struct record_header *record_hdr)
3715 struct stats_net_ip6
3716 *snic = (struct stats_net_ip6 *) a->buf[curr],
3717 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3718 int group[] = {4, 2, 2, 2};
3719 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3721 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3722 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3723 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3724 "asmrq6/s", "asmok6/s",
3725 "imcpck6/s", "omcpck6/s",
3726 "fragok6/s", "fragcr6/s"};
3727 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3728 static double *spmin, *spmax;
3730 static int *outsize;
3732 if (action & F_BEGIN) {
3734 * Allocate arrays that will contain the graphs data
3735 * and the min/max values.
3737 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3740 if (action & F_MAIN) {
3741 /* Check for min/max values */
3742 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3743 itv, spmin, spmax, g_fields);
3746 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3747 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3748 out, outsize, svg_p->restart);
3750 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3751 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3752 out + 1, outsize + 1, svg_p->restart);
3754 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3755 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3756 out + 2, outsize + 2, svg_p->restart);
3758 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3759 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3760 out + 3, outsize + 3, svg_p->restart);
3762 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3763 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3764 out + 4, outsize + 4, svg_p->restart);
3766 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3767 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3768 out + 5, outsize + 5, svg_p->restart);
3770 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3771 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3772 out + 6, outsize + 6, svg_p->restart);
3774 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3775 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3776 out + 7, outsize + 7, svg_p->restart);
3778 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3779 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3780 out + 8, outsize + 8, svg_p->restart);
3782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3783 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3784 out + 9, outsize + 9, svg_p->restart);
3787 if (action & F_END) {
3788 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3789 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3791 /* Free remaining structures */
3792 free_graphs(out, outsize, spmin, spmax);
3797 ***************************************************************************
3798 * Display IPv6 traffic errors statistics in SVG.
3801 * @a Activity structure with statistics.
3802 * @curr Index in array for current sample statistics.
3803 * @action Action expected from current function.
3804 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3805 * flag indicating that a restart record has been previously
3806 * found (.@restart) and time used for the X axis origin
3808 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3809 * @record_hdr Pointer on record header of current stats sample.
3810 ***************************************************************************
3812 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3813 unsigned long long itv, struct record_header *record_hdr)
3815 struct stats_net_eip6
3816 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3817 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3818 int group[] = {4, 2, 2, 3};
3819 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3821 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3822 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3823 "IPv6 traffic errors statistics (5)"};
3824 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3825 "idisc6/s", "odisc6/s",
3826 "inort6/s", "onort6/s",
3827 "asmf6/s", "fragf6/s", "itrpck6/s"};
3828 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3829 static double *spmin, *spmax;
3831 static int *outsize;
3833 if (action & F_BEGIN) {
3835 * Allocate arrays that will contain the graphs data
3836 * and the min/max values.
3838 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3841 if (action & F_MAIN) {
3842 /* Check for min/max values */
3843 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3844 itv, spmin, spmax, g_fields);
3847 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3848 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3849 out, outsize, svg_p->restart);
3851 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3852 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3853 out + 1, outsize + 1, svg_p->restart);
3855 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3856 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3857 out + 2, outsize + 2, svg_p->restart);
3859 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3860 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3861 out + 3, outsize + 3, svg_p->restart);
3863 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3864 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3865 out + 4, outsize + 4, svg_p->restart);
3867 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3868 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3869 out + 5, outsize + 5, svg_p->restart);
3871 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3872 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3873 out + 6, outsize + 6, svg_p->restart);
3875 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3876 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3877 out + 7, outsize + 7, svg_p->restart);
3879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3880 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3881 out + 8, outsize + 8, svg_p->restart);
3883 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3884 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3885 out + 9, outsize + 9, svg_p->restart);
3887 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3888 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3889 out + 10, outsize + 10, svg_p->restart);
3892 if (action & F_END) {
3893 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3894 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3896 /* Free remaining structures */
3897 free_graphs(out, outsize, spmin, spmax);
3902 ***************************************************************************
3903 * Display ICMPv6 traffic statistics in SVG.
3906 * @a Activity structure with statistics.
3907 * @curr Index in array for current sample statistics.
3908 * @action Action expected from current function.
3909 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3910 * flag indicating that a restart record has been previously
3911 * found (.@restart) and time used for the X axis origin
3913 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3914 * @record_hdr Pointer on record header of current stats sample.
3915 ***************************************************************************
3917 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3918 unsigned long long itv, struct record_header *record_hdr)
3920 struct stats_net_icmp6
3921 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3922 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3923 int group[] = {2, 3, 5, 3, 4};
3924 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3925 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3926 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3927 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3928 "ICMPv6 traffic statistics (5)"};
3929 char *g_title[] = {"imsg6/s", "omsg6/s",
3930 "iech6/s", "iechr6/s", "oechr6/s",
3931 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3932 "irtsol6/s", "ortsol6/s", "irtad6/s",
3933 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3934 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3935 static double *spmin, *spmax;
3937 static int *outsize;
3939 if (action & F_BEGIN) {
3941 * Allocate arrays that will contain the graphs data
3942 * and the min/max values.
3944 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3947 if (action & F_MAIN) {
3948 /* Check for min/max values */
3949 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3950 itv, spmin, spmax, g_fields);
3953 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3954 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3955 out, outsize, svg_p->restart);
3957 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3958 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3959 out + 1, outsize + 1, svg_p->restart);
3961 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3962 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3963 out + 2, outsize + 2, svg_p->restart);
3965 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3966 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3967 out + 3, outsize + 3, svg_p->restart);
3969 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3970 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3971 out + 4, outsize + 4, svg_p->restart);
3973 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3974 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3975 out + 5, outsize + 5, svg_p->restart);
3977 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3978 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3979 out + 6, outsize + 6, svg_p->restart);
3981 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3982 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3983 out + 7, outsize + 7, svg_p->restart);
3985 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3986 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3987 out + 8, outsize + 8, svg_p->restart);
3989 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3990 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3991 out + 9, outsize + 9, svg_p->restart);
3993 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3994 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3995 out + 10, outsize + 10, svg_p->restart);
3997 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3998 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3999 out + 11, outsize + 11, svg_p->restart);
4001 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4002 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
4003 out + 12, outsize + 12, svg_p->restart);
4005 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4006 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
4007 out + 13, outsize + 13, svg_p->restart);
4009 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4010 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
4011 out + 14, outsize + 14, svg_p->restart);
4013 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4014 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
4015 out + 15, outsize + 15, svg_p->restart);
4017 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4018 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
4019 out + 16, outsize + 16, svg_p->restart);
4022 if (action & F_END) {
4023 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4024 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4026 /* Free remaining structures */
4027 free_graphs(out, outsize, spmin, spmax);
4032 ***************************************************************************
4033 * Display ICMPv6 traffic errors statistics in SVG.
4036 * @a Activity structure with statistics.
4037 * @curr Index in array for current sample statistics.
4038 * @action Action expected from current function.
4039 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4040 * flag indicating that a restart record has been previously
4041 * found (.@restart) and time used for the X axis origin
4043 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4044 * @record_hdr Pointer on record header of current stats sample.
4045 ***************************************************************************
4047 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4048 unsigned long long itv, struct record_header *record_hdr)
4050 struct stats_net_eicmp6
4051 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
4052 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
4053 int group[] = {1, 2, 2, 2, 2, 2};
4054 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4055 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4056 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
4057 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
4058 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
4059 char *g_title[] = {"ierr6/s",
4060 "idtunr6/s", "odtunr6/s",
4061 "itmex6/s", "otmex6/s",
4062 "iprmpb6/s", "oprmpb6/s",
4063 "iredir6/s", "oredir6/s",
4064 "ipck2b6/s", "opck2b6/s"};
4065 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4066 static double *spmin, *spmax;
4068 static int *outsize;
4070 if (action & F_BEGIN) {
4072 * Allocate arrays that will contain the graphs data
4073 * and the min/max values.
4075 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4078 if (action & F_MAIN) {
4079 /* Check for min/max values */
4080 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4081 itv, spmin, spmax, g_fields);
4084 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4085 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4086 out, outsize, svg_p->restart);
4088 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4089 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4090 out + 1, outsize + 1, svg_p->restart);
4092 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4093 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4094 out + 2, outsize + 2, svg_p->restart);
4096 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4097 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4098 out + 3, outsize + 3, svg_p->restart);
4100 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4101 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4102 out + 4, outsize + 4, svg_p->restart);
4104 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4105 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4106 out + 5, outsize + 5, svg_p->restart);
4108 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4109 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4110 out + 6, outsize + 6, svg_p->restart);
4112 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4113 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4114 out + 7, outsize + 7, svg_p->restart);
4116 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4117 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4118 out + 8, outsize + 8, svg_p->restart);
4120 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4121 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4122 out + 9, outsize + 9, svg_p->restart);
4124 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4125 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4126 out + 10, outsize + 10, svg_p->restart);
4129 if (action & F_END) {
4130 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4131 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4133 /* Free remaining structures */
4134 free_graphs(out, outsize, spmin, spmax);
4139 ***************************************************************************
4140 * Display UDPv6 traffic statistics in SVG.
4143 * @a Activity structure with statistics.
4144 * @curr Index in array for current sample statistics.
4145 * @action Action expected from current function.
4146 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4147 * flag indicating that a restart record has been previously
4148 * found (.@restart) and time used for the X axis origin
4150 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4151 * @record_hdr Pointer on record header of current stats sample.
4152 ***************************************************************************
4154 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4155 unsigned long long itv, struct record_header *record_hdr)
4157 struct stats_net_udp6
4158 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4159 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4160 int group[] = {2, 2};
4161 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4162 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4163 char *g_title[] = {"idgm6/s", "odgm6/s",
4164 "noport6/s", "idgmer6/s"};
4165 int g_fields[] = {0, 1, 2, 3};
4166 static double *spmin, *spmax;
4168 static int *outsize;
4170 if (action & F_BEGIN) {
4172 * Allocate arrays that will contain the graphs data
4173 * and the min/max values.
4175 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4178 if (action & F_MAIN) {
4179 /* Check for min/max values */
4180 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4181 itv, spmin, spmax, g_fields);
4184 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4185 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4186 out, outsize, svg_p->restart);
4188 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4189 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4190 out + 1, outsize + 1, svg_p->restart);
4192 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4193 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4194 out + 2, outsize + 2, svg_p->restart);
4196 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4197 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4198 out + 3, outsize + 3, svg_p->restart);
4201 if (action & F_END) {
4202 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4203 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4205 /* Free remaining structures */
4206 free_graphs(out, outsize, spmin, spmax);
4211 ***************************************************************************
4212 * Display CPU frequency statistics in SVG.
4215 * @a Activity structure with statistics.
4216 * @curr Index in array for current sample statistics.
4217 * @action Action expected from current function.
4218 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4219 * flag indicating that a restart record has been previously
4220 * found (.@restart) and time used for the X axis origin
4222 * @itv Interval of time in 1/100th of a second (unused here).
4223 * @record_hdr Pointer on record header of current stats sample.
4224 ***************************************************************************
4226 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4227 unsigned long long itv, struct record_header *record_hdr)
4229 struct stats_pwr_cpufreq *spc, *spp;
4231 int g_type[] = {SVG_LINE_GRAPH};
4232 char *title[] = {"CPU clock frequency"};
4233 char *g_title[] = {"MHz"};
4234 static double *spmin, *spmax;
4236 static int *outsize;
4240 if (action & F_BEGIN) {
4242 * Allocate arrays that will contain the graphs data
4243 * and the min/max values.
4245 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4248 if (action & F_MAIN) {
4250 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4252 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4253 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4255 /* Should current CPU (including CPU "all") be displayed? */
4256 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4261 * Note: Don't skip offline CPU here as it is needed
4262 * to make the graph go though 0.
4266 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4267 ((double) spp->cpufreq) / 100,
4268 ((double) spc->cpufreq) / 100,
4269 out + i, outsize + i, svg_p->restart, svg_p->dt,
4270 spmin + i, spmax + i);
4274 if (action & F_END) {
4277 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
4279 /* Should current CPU (including CPU "all") be displayed? */
4280 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4285 /* This is CPU "all" */
4286 strcpy(item_name, "all");
4290 * If the maximum frequency reached by the CPU is 0, then
4291 * the CPU has been offline on the whole period.
4292 * => Don't display it.
4294 if (*(spmax + i) == 0)
4297 sprintf(item_name, "%d", i - 1);
4300 if (draw_activity_graphs(a->g_nr, g_type,
4301 title, g_title, item_name, group,
4302 spmin + i, spmax + i, out + i, outsize + i,
4303 svg_p, record_hdr, i, a->id, xid)) {
4308 /* Free remaining structures */
4309 free_graphs(out, outsize, spmin, spmax);
4314 ***************************************************************************
4315 * Display fan statistics in SVG.
4318 * @a Activity structure with statistics.
4319 * @curr Index in array for current sample statistics.
4320 * @action Action expected from current function.
4321 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4322 * flag indicating that a restart record has been previously
4323 * found (.@restart) and time used for the X axis origin
4325 * @itv Interval of time in 1/100th of a second (unused here).
4326 * @record_hdr Pointer on record header of current stats sample.
4327 ***************************************************************************
4329 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4330 unsigned long long itv, struct record_header *record_hdr)
4332 struct stats_pwr_fan *spc, *spp;
4334 int g_type[] = {SVG_LINE_GRAPH};
4335 char *title[] = {"Fans speed"};
4336 char *g_title[] = {"~rpm"};
4337 static double *spmin, *spmax;
4339 static int *outsize;
4340 char item_name[MAX_SENSORS_DEV_LEN + 16];
4343 if (action & F_BEGIN) {
4345 * Allocate arrays that will contain the graphs data
4346 * and the min/max values.
4348 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4351 if (action & F_MAIN) {
4353 for (i = 0; i < a->nr[curr]; i++) {
4355 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4356 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4359 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4362 out + i, outsize + i, svg_p->restart, svg_p->dt,
4363 spmin + i, spmax + i);
4367 if (action & F_END) {
4370 for (i = 0; i < a->item_list_sz; i++) {
4372 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4374 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4375 item_name[sizeof(item_name) - 1] = '\0';
4377 if (draw_activity_graphs(a->g_nr, g_type,
4378 title, g_title, item_name, group,
4379 spmin + i, spmax + i, out + i, outsize + i,
4380 svg_p, record_hdr, FALSE, a->id, xid)) {
4385 /* Free remaining structures */
4386 free_graphs(out, outsize, spmin, spmax);
4391 ***************************************************************************
4392 * Display temperature statistics in SVG.
4395 * @a Activity structure with statistics.
4396 * @curr Index in array for current sample statistics.
4397 * @action Action expected from current function.
4398 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4399 * flag indicating that a restart record has been previously
4400 * found (.@restart) and time used for the X axis origin
4402 * @itv Interval of time in 1/100th of a second (unused here).
4403 * @record_hdr Pointer on record header of current stats sample.
4404 ***************************************************************************
4406 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4407 unsigned long long itv, struct record_header *record_hdr)
4409 struct stats_pwr_temp *spc;
4410 int group[] = {1, 1};
4411 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4412 char *title[] = {"Devices temperature (1)",
4413 "Devices temperature (2)"};
4414 char *g_title[] = {"~degC",
4416 static double *spmin, *spmax;
4418 static int *outsize;
4419 char item_name[MAX_SENSORS_DEV_LEN + 16];
4423 if (action & F_BEGIN) {
4425 * Allocate arrays that will contain the graphs data
4426 * and the min/max values.
4428 out = allocate_graph_lines(2 * a->item_list_sz, &outsize, &spmin, &spmax);
4431 if (action & F_MAIN) {
4432 /* For each temperature sensor */
4433 for (i = 0; i < a->nr[curr]; i++) {
4435 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4437 /* Look for min/max values */
4438 if (spc->temp < *(spmin + 2 * i)) {
4439 *(spmin + 2 * i) = spc->temp;
4441 if (spc->temp > *(spmax + 2 * i)) {
4442 *(spmax + 2 * i) = spc->temp;
4444 tval = (spc->temp_max - spc->temp_min) ?
4445 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4447 if (tval < *(spmin + 2 * i + 1)) {
4448 *(spmin + 2 * i + 1) = tval;
4450 if (tval > *(spmax + 2 * i + 1)) {
4451 *(spmax + 2 * i + 1) = tval;
4455 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4457 out + 2 * i, outsize + 2 * i, svg_p->restart);
4459 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4461 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4465 if (action & F_END) {
4468 for (i = 0; i < a->item_list_sz; i++) {
4470 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4472 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4473 item_name[sizeof(item_name) - 1] = '\0';
4475 if (draw_activity_graphs(a->g_nr, g_type,
4476 title, g_title, item_name, group,
4477 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4478 svg_p, record_hdr, FALSE, a->id, xid)) {
4483 /* Free remaining structures */
4484 free_graphs(out, outsize, spmin, spmax);
4489 ***************************************************************************
4490 * Display voltage inputs statistics in SVG.
4493 * @a Activity structure with statistics.
4494 * @curr Index in array for current sample statistics.
4495 * @action Action expected from current function.
4496 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4497 * flag indicating that a restart record has been previously
4498 * found (.@restart) and time used for the X axis origin
4500 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4501 * @record_hdr Pointer on record header of current stats sample.
4502 ***************************************************************************
4504 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4505 unsigned long long itv, struct record_header *record_hdr)
4507 struct stats_pwr_in *spc;
4508 int group[] = {1, 1};
4509 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4510 char *title[] = {"Voltage inputs statistics (1)",
4511 "Voltage inputs statistics (2)"};
4512 char *g_title[] = {"inV",
4514 static double *spmin, *spmax;
4516 static int *outsize;
4517 char item_name[MAX_SENSORS_DEV_LEN + 16];
4521 if (action & F_BEGIN) {
4523 * Allocate arrays that will contain the graphs data
4524 * and the min/max values.
4526 out = allocate_graph_lines(2 * a->item_list_sz, &outsize, &spmin, &spmax);
4529 if (action & F_MAIN) {
4530 /* For each voltage input sensor */
4531 for (i = 0; i < a->nr[curr]; i++) {
4533 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4535 /* Look for min/max values */
4536 if (spc->in < *(spmin + 2 * i)) {
4537 *(spmin + 2 * i) = spc->in;
4539 if (spc->in > *(spmax + 2 * i)) {
4540 *(spmax + 2 * i) = spc->in;
4542 tval = (spc->in_max - spc->in_min) ?
4543 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4545 if (tval < *(spmin + 2 * i + 1)) {
4546 *(spmin + 2 * i + 1) = tval;
4548 if (tval > *(spmax + 2 * i + 1)) {
4549 *(spmax + 2 * i + 1) = tval;
4553 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4555 out + 2 * i, outsize + 2 * i, svg_p->restart);
4557 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4559 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4563 if (action & F_END) {
4566 for (i = 0; i < a->item_list_sz; i++) {
4568 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4570 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4571 item_name[sizeof(item_name) - 1] = '\0';
4573 if (draw_activity_graphs(a->g_nr, g_type,
4574 title, g_title, item_name, group,
4575 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4576 svg_p, record_hdr, FALSE, a->id, xid)) {
4581 /* Free remaining structures */
4582 free_graphs(out, outsize, spmin, spmax);
4587 ***************************************************************************
4588 * Display huge pages statistics in SVG.
4591 * @a Activity structure with statistics.
4592 * @curr Index in array for current sample statistics.
4593 * @action Action expected from current function.
4594 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4595 * flag indicating that a restart record has been previously
4596 * found (.@restart) and time used for the X axis origin
4598 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4599 * @record_hdr Pointer on record header of current stats sample.
4600 ***************************************************************************
4602 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4603 unsigned long long itv, struct record_header *record_hdr)
4606 *smc = (struct stats_huge *) a->buf[curr];
4607 int group[] = {4, 1};
4608 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4609 char *title[] = {"Huge pages utilization (1)",
4610 "Huge pages utilization (2)"};
4611 char *g_title[] = {"~kbhugfree", "~kbhugused", "~kbhugrsvd", "~kbhugsurp",
4613 int g_fields[] = {0, 5, 2, 3};
4614 static double *spmin, *spmax;
4616 static int *outsize;
4619 if (action & F_BEGIN) {
4621 * Allocate arrays that will contain the graphs data
4622 * and the min/max values.
4623 * Allocate one additional array (#5) to save min/max
4624 * values for tlhkb (unused).
4626 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
4629 if (action & F_MAIN) {
4630 /* Check for min/max values */
4631 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
4632 itv, spmin, spmax, g_fields);
4634 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4635 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4637 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4638 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4640 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4641 if (tval < *(spmin + 4)) {
4642 *(spmin + 4) = tval;
4644 if (tval > *(spmax + 4)) {
4645 *(spmax + 4) = tval;
4649 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4650 (unsigned long long) smc->frhkb,
4651 out, outsize, svg_p->restart);
4653 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4654 (unsigned long long) smc->tlhkb - smc->frhkb,
4655 out + 1, outsize + 1, svg_p->restart);
4657 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4658 (unsigned long long) smc->rsvdhkb,
4659 out + 2, outsize + 2, svg_p->restart);
4661 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4662 (unsigned long long) smc->surphkb,
4663 out + 3, outsize + 3, svg_p->restart);
4665 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4667 out + 4, outsize + 4, svg_p->dt);
4670 if (action & F_END) {
4671 draw_activity_graphs(a->g_nr, g_type,
4672 title, g_title, NULL, group,
4673 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4675 /* Free remaining structures */
4676 free_graphs(out, outsize, spmin, spmax);
4681 ***************************************************************************
4682 * Display filesystem statistics in SVG.
4685 * @a Activity structure with statistics.
4686 * @curr Index in array for current sample statistics.
4687 * @action Action expected from current function.
4688 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4689 * flag indicating that a restart record has been previously
4690 * found (.@restart) and time used for the X axis origin
4692 * @itv Interval of time in 1/100th of a second (unused here).
4693 * @record_hdr Pointer on record header of current stats sample.
4694 ***************************************************************************
4696 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4697 unsigned long long itv, struct record_header *record_hdr)
4699 struct stats_filesystem *sfc, *sfp;
4700 int group[] = {2, 2, 2, 1};
4701 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4702 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4703 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4704 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4705 char *g_title[] = {"~MBfsfree", "~MBfsused",
4706 "%ufsused", "%fsused",
4707 "Ifree/1000", "Iused/1000",
4710 static double *spmin, *spmax;
4712 static int *outsize;
4713 char *dev_name, *item_name;
4715 int i, k, pos, restart;
4717 if (action & F_BEGIN) {
4719 * Allocate arrays (#0..6) that will contain the graphs data
4720 * and the min/max values.
4721 * Also allocate an additional arrays (#7) for each filesystem:
4722 * out + 7 will contain the persistent or standard fs name, or mount point.
4724 out = allocate_graph_lines(nr_arrays * a->item_list_sz, &outsize, &spmin, &spmax);
4727 if (action & F_MAIN) {
4728 /* For each filesystem structure */
4729 for (i = 0; i < a->nr[curr]; i++) {
4730 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4732 /* Get name to display (persistent or standard fs name, or mount point) */
4733 dev_name = get_fs_name_to_display(a, flags, sfc);
4735 if (a->item_list != NULL) {
4736 /* A list of devices has been entered on the command line */
4737 if (!search_list_item(a->item_list, dev_name))
4738 /* Device not found */
4742 /* Look for corresponding graph */
4743 for (k = 0; k < a->item_list_sz; k++) {
4744 item_name = *(out + k * nr_arrays + 7);
4745 if (!strcmp(dev_name, item_name))
4750 if (k == a->item_list_sz) {
4751 /* Graph not found: Look for first free entry */
4752 for (k = 0; k < a->item_list_sz; k++) {
4753 item_name = *(out + k * nr_arrays + 7);
4754 if (!strcmp(item_name, ""))
4757 if (k == a->item_list_sz) {
4758 /* No free graph entry: Ignore it (should never happen) */
4760 fprintf(stderr, "%s: Name=%s\n",
4761 __FUNCTION__, sfc->fs_name);
4767 pos = k * nr_arrays;
4769 item_name = *(out + pos + 7);
4770 if (!item_name[0]) {
4771 /* Save filesystem name and mount point (if not already done) */
4772 strncpy(item_name, dev_name, CHUNKSIZE);
4773 item_name[CHUNKSIZE - 1] = '\0';
4777 for (k = 0; k < a->nr[!curr]; k++) {
4778 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4779 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4780 /* Filesystem found in previous sample */
4781 restart = svg_p->restart;
4785 /* Check for min/max values */
4787 /* Compute fsfree min/max values */
4788 tval = (double) sfc->f_bfree;
4789 if (tval > *(spmax + pos)) {
4790 *(spmax + pos) = tval;
4792 if (tval < *(spmin + pos)) {
4793 *(spmin + pos) = tval;
4795 /* Compute fsused min/max values */
4796 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4797 if (tval > *(spmax + pos + 1)) {
4798 *(spmax + pos + 1) = tval;
4800 if (tval < *(spmin + pos + 1)) {
4801 *(spmin + pos + 1) = tval;
4803 /* Compute %ufsused min/max values */
4804 tval = sfc->f_blocks ?
4805 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4806 if (tval > *(spmax + pos + 2)) {
4807 *(spmax + pos + 2) = tval;
4809 if (tval < *(spmin + pos + 2)) {
4810 *(spmin + pos + 2) = tval;
4812 /* Compute %fsused min/max values */
4813 tval = sfc->f_blocks ?
4814 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4815 if (tval > *(spmax + pos + 3)) {
4816 *(spmax + pos + 3) = tval;
4818 if (tval < *(spmin + pos + 3)) {
4819 *(spmin + pos + 3) = tval;
4821 /* Compute Ifree min/max values */
4822 tval = (double) sfc->f_ffree;
4823 if (tval > *(spmax + pos + 4)) {
4824 *(spmax + pos + 4) = tval;
4826 if (tval < *(spmin + pos + 4)) {
4827 *(spmin + pos + 4) = tval;
4829 /* Compute Iused min/max values */
4830 tval = (double) (sfc->f_files - sfc->f_ffree);
4831 if (tval > *(spmax + pos + 5)) {
4832 *(spmax + pos + 5) = tval;
4834 if (tval < *(spmin + pos + 5)) {
4835 *(spmin + pos + 5) = tval;
4837 /* Compute %Iused min/max values */
4838 tval = sfc->f_files ?
4839 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4840 if (tval > *(spmax + pos + 6)) {
4841 *(spmax + pos + 6) = tval;
4843 if (tval < *(spmin + pos + 6)) {
4844 *(spmin + pos + 6) = tval;
4848 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4849 (double) sfc->f_bfree / 1024 / 1024,
4850 out + pos, outsize + pos, restart);
4852 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4853 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4854 out + pos + 1, outsize + pos + 1, restart);
4856 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4859 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4860 out + pos + 2, outsize + pos + 2, svg_p->dt);
4862 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4865 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4866 out + pos + 3, outsize + pos + 3, svg_p->dt);
4868 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4869 ((double) sfc->f_ffree) / 1000,
4870 out + pos + 4, outsize + pos + 4, restart);
4872 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4873 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4874 out + pos + 5, outsize + pos + 5, restart);
4876 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4879 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4880 out + pos + 6, outsize + pos + 6, svg_p->dt);
4884 if (action & F_END) {
4887 for (i = 0; i < a->item_list_sz; i++) {
4889 /* Check if there is something to display */
4890 pos = i * nr_arrays;
4894 /* Conversion B -> MiB and inodes/1000 */
4895 for (k = 0; k < 2; k++) {
4896 *(spmin + pos + k) /= (1024 * 1024);
4897 *(spmax + pos + k) /= (1024 * 1024);
4898 *(spmin + pos + 4 + k) /= 1000;
4899 *(spmax + pos + 4 + k) /= 1000;
4902 item_name = *(out + pos + 7);
4904 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4905 spmin + pos, spmax + pos, out + pos, outsize + pos,
4906 svg_p, record_hdr, FALSE, a->id, xid)) {
4911 /* Free remaining structures */
4912 free_graphs(out, outsize, spmin, spmax);
4917 ***************************************************************************
4918 * Display Fibre Channel HBA statistics in SVG.
4921 * @a Activity structure with statistics.
4922 * @curr Index in array for current sample statistics.
4923 * @action Action expected from current function.
4924 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4925 * flag indicating that a restart record has been previously
4926 * found (.@restart) and time used for the X axis origin
4928 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4929 * @record_hdr Pointer on record header of current stats sample.
4930 ***************************************************************************
4932 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4933 unsigned long long itv, struct record_header *record_hdr)
4935 struct stats_fchost *sfcc, *sfcp, sfczero;
4936 int group[] = {2, 2};
4937 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4938 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4939 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4940 "fch_rxw/s", "fch_txw/s"};
4941 int g_fields[] = {0, 1, 2, 3};
4942 static double *spmin, *spmax;
4944 static int *outsize;
4946 int i, j, j0, k, found, pos, restart, *unregistered;
4948 if (action & F_BEGIN) {
4950 * Allocate arrays (#0..3) that will contain the graphs data
4951 * and the min/max values.
4952 * Also allocate one additional array (#4) that will contain
4953 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4954 * has either still not been registered, or has been unregistered
4957 out = allocate_graph_lines(5 * a->item_list_sz, &outsize, &spmin, &spmax);
4960 if (action & F_MAIN) {
4961 memset(&sfczero, 0, sizeof(struct stats_fchost));
4962 restart = svg_p->restart;
4964 * Mark previously registered interfaces as now
4965 * possibly unregistered for all graphs.
4967 for (k = 0; k < a->item_list_sz; k++) {
4968 unregistered = outsize + k * 5 + 4;
4969 if (*unregistered == FALSE) {
4970 *unregistered = MAYBE;
4974 /* For each FC HBA */
4975 for (i = 0; i < a->nr[curr]; i++) {
4978 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4980 /* Look for corresponding graph */
4981 for (k = 0; k < a->item_list_sz; k++) {
4982 item_name = *(out + k * 5 + 4);
4983 if (!strcmp(sfcc->fchost_name, item_name))
4987 if (k == a->item_list_sz) {
4988 /* Graph not found: Look for first free entry */
4989 for (k = 0; k < a->item_list_sz; k++) {
4990 item_name = *(out + k * 5 + 4);
4991 if (!strcmp(item_name, ""))
4994 if (k == a->item_list_sz) {
4995 /* No free graph entry: Ignore it (should never happen) */
4997 fprintf(stderr, "%s: Name=%s\n",
4998 __FUNCTION__, sfcc->fchost_name);
5005 unregistered = outsize + pos + 4;
5007 if (a->nr[!curr] > 0) {
5008 /* Look for corresponding structure in previous iteration */
5011 if (j >= a->nr[!curr]) {
5012 j = a->nr[!curr] - 1;
5018 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
5019 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
5023 if (++j >= a->nr[!curr]) {
5031 /* This is a newly registered host */
5036 * If current interface was marked as previously unregistered,
5037 * then set restart variable to TRUE so that the graph will be
5038 * discontinuous, and mark it as now registered.
5040 if (*unregistered == TRUE) {
5043 *unregistered = FALSE;
5045 item_name = *(out + pos + 4);
5046 if (!item_name[0]) {
5047 /* Save FC HBA name */
5048 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
5049 item_name[CHUNKSIZE - 1] = '\0';
5052 /* Look for min/max values */
5053 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
5054 itv, spmin + pos, spmax + pos, g_fields);
5057 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5058 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5059 out + pos, outsize + pos, restart);
5061 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5062 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5063 out + pos + 1, outsize + pos + 1, restart);
5065 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5066 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5067 out + pos + 2, outsize + pos + 2, restart);
5069 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5070 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5071 out + pos + 3, outsize + pos + 3, restart);
5074 /* Mark interfaces not seen here as now unregistered */
5075 for (k = 0; k < a->item_list_sz; k++) {
5076 unregistered = outsize + k * 5 + 4;
5077 if (*unregistered != FALSE) {
5078 *unregistered = TRUE;
5083 if (action & F_END) {
5084 for (i = 0; i < a->item_list_sz; i++) {
5086 /* Check if there is something to display */
5091 item_name = *(out + pos + 4);
5092 draw_activity_graphs(a->g_nr, g_type,
5093 title, g_title, item_name, group,
5094 spmin + pos, spmax + pos, out + pos, outsize + pos,
5095 svg_p, record_hdr, FALSE, a->id, i);
5098 /* Free remaining structures */
5099 free_graphs(out, outsize, spmin, spmax);
5104 ***************************************************************************
5105 * Display softnet statistics in SVG.
5108 * @a Activity structure with statistics.
5109 * @curr Index in array for current sample statistics.
5110 * @action Action expected from current function.
5111 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5112 * flag indicating that a restart record has been previously
5113 * found (.@restart) and time used for the X axis origin
5115 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5116 * @record_hdr Pointer on record header of current stats sample.
5117 ***************************************************************************
5119 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5120 unsigned long long itv, struct record_header *record_hdr)
5122 struct stats_softnet *ssnc, *ssnp, ssnczero;
5123 int group[] = {2, 3};
5124 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5125 char *title[] = {"Software-based network processing statistics (1)",
5126 "Software-based network processing statistics (2)"};
5127 char *g_title[] = {"total/s", "dropd/s",
5128 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5129 int g_fields[] = {0, 1, 2, 3, 4};
5130 static double *spmin, *spmax;
5132 static int *outsize;
5134 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5135 int i, pos, restart;
5137 if (action & F_BEGIN) {
5139 * Allocate arrays that will contain the graphs data
5140 * and the min/max values.
5142 out = allocate_graph_lines(5 * a->item_list_sz, &outsize, &spmin, &spmax);
5145 if (action & F_MAIN) {
5146 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5148 /* @nr[curr] cannot normally be greater than @nr_ini */
5149 if (a->nr[curr] > a->nr_ini) {
5150 a->nr_ini = a->nr[curr];
5153 /* Compute statistics for CPU "all" */
5154 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5157 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5158 restart = svg_p->restart;
5160 /* Should current CPU (including CPU "all") be displayed? */
5161 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5165 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5166 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5168 /* Is current CPU marked offline? */
5169 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5171 * Yes and it doesn't follow a RESTART record.
5172 * To add a discontinuity in graph, we simulate
5176 if (svg_p->restart) {
5178 * CPU is offline and it follows a real
5179 * RESTART record. Ignore its current value
5180 * (no previous sample).
5187 /* Check for min/max values */
5188 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5189 itv, spmin + pos, spmax + pos, g_fields);
5192 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5193 S_VALUE(ssnp->processed, ssnc->processed, itv),
5194 out + pos, outsize + pos, restart);
5196 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5197 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5198 out + pos + 1, outsize + pos + 1, restart);
5200 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5201 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5202 out + pos + 2, outsize + pos + 2, restart);
5204 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5205 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5206 out + pos + 3, outsize + pos + 3, restart);
5208 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5209 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5210 out + pos + 4, outsize + pos + 4, restart);
5214 if (action & F_END) {
5215 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
5217 /* Should current CPU (including CPU "all") be displayed? */
5218 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5225 /* This is CPU "all" */
5226 strcpy(item_name, "all");
5229 sprintf(item_name, "%d", i - 1);
5232 draw_activity_graphs(a->g_nr, g_type,
5233 title, g_title, item_name, group,
5234 spmin + pos, spmax + pos, out + pos, outsize + pos,
5235 svg_p, record_hdr, FALSE, a->id, i);
5238 /* Free remaining structures */
5239 free_graphs(out, outsize, spmin, spmax);
5244 ***************************************************************************
5245 * Display pressure-stall CPU statistics in SVG.
5248 * @a Activity structure with statistics.
5249 * @curr Index in array for current sample statistics.
5250 * @action Action expected from current function.
5251 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5252 * flag indicating that a restart record has been previously
5253 * found (.@restart) and time used for the X axis origin
5255 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5256 * @record_hdr Pointer on record header of current stats sample.
5257 ***************************************************************************
5259 __print_funct_t svg_print_psicpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5260 unsigned long long itv, struct record_header *record_hdr)
5262 struct stats_psi_cpu
5263 *psic = (struct stats_psi_cpu *) a->buf[curr],
5264 *psip = (struct stats_psi_cpu *) a->buf[!curr];
5265 int group[] = {3, 1};
5266 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5267 char *title[] = {"CPU pressure trends (some tasks)", "CPU stall time (some tasks)"};
5268 char *g_title[] = {"%scpu-10", "%scpu-60", "%scpu-300",
5270 static double *spmin, *spmax;
5272 static int *outsize;
5275 if (action & F_BEGIN) {
5277 * Allocate arrays that will contain the graphs data
5278 * and the min/max values.
5280 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
5283 if (action & F_MAIN) {
5284 /* Check for min/max values */
5285 if (psic->some_acpu_10 > *spmax) {
5286 *spmax = psic->some_acpu_10;
5288 if (psic->some_acpu_10 < *spmin) {
5289 *spmin = psic->some_acpu_10;
5291 if (psic->some_acpu_60 > *(spmax + 1)) {
5292 *(spmax + 1) = psic->some_acpu_60;
5294 if (psic->some_acpu_60 < *(spmin + 1)) {
5295 *(spmin + 1) = psic->some_acpu_60;
5297 if (psic->some_acpu_300 > *(spmax + 2)) {
5298 *(spmax + 2) = psic->some_acpu_300;
5300 if (psic->some_acpu_300 < *(spmin + 2)) {
5301 *(spmin + 2) = psic->some_acpu_300;
5303 tval = ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv);
5304 if (tval > *(spmax + 3)) {
5305 *(spmax + 3) = tval;
5307 if (tval < *(spmin + 3)) {
5308 *(spmin + 3) = tval;
5312 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5313 (double) psic->some_acpu_10 / 100,
5314 out, outsize, svg_p->restart);
5316 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5317 (double) psic->some_acpu_60 / 100,
5318 out + 1, outsize + 1, svg_p->restart);
5320 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5321 (double) psic->some_acpu_300 / 100,
5322 out + 2, outsize + 2, svg_p->restart);
5324 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5326 ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv),
5327 out + 3, outsize + 3, svg_p->dt);
5330 if (action & F_END) {
5331 /* Fix min/max values for pressure ratios */
5332 *spmin /= 100; *spmax /= 100;
5333 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5334 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5336 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5337 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5339 /* Free remaining structures */
5340 free_graphs(out, outsize, spmin, spmax);
5345 ***************************************************************************
5346 * Display pressure-stall I/O statistics in SVG.
5349 * @a Activity structure with statistics.
5350 * @curr Index in array for current sample statistics.
5351 * @action Action expected from current function.
5352 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5353 * flag indicating that a restart record has been previously
5354 * found (.@restart) and time used for the X axis origin
5356 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5357 * @record_hdr Pointer on record header of current stats sample.
5358 ***************************************************************************
5360 __print_funct_t svg_print_psiio_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5361 unsigned long long itv, struct record_header *record_hdr)
5364 *psic = (struct stats_psi_io *) a->buf[curr],
5365 *psip = (struct stats_psi_io *) a->buf[!curr];
5366 int group[] = {3, 1, 3, 1};
5367 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5368 char *title[] = {"I/O pressure trends (some tasks)", "I/O stall time (some tasks)",
5369 "I/O pressure trends (full)", "I/O stall time (full)"};
5370 char *g_title[] = {"%sio-10", "%sio-60", "%sio-300",
5372 "%fio-10", "%fio-60", "%fio-300",
5374 static double *spmin, *spmax;
5376 static int *outsize;
5379 if (action & F_BEGIN) {
5381 * Allocate arrays that will contain the graphs data
5382 * and the min/max values.
5384 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5387 if (action & F_MAIN) {
5388 /* Check for min/max values */
5389 if (psic->some_aio_10 > *spmax) {
5390 *spmax = psic->some_aio_10;
5392 if (psic->some_aio_10 < *spmin) {
5393 *spmin = psic->some_aio_10;
5395 if (psic->some_aio_60 > *(spmax + 1)) {
5396 *(spmax + 1) = psic->some_aio_60;
5398 if (psic->some_aio_60 < *(spmin + 1)) {
5399 *(spmin + 1) = psic->some_aio_60;
5401 if (psic->some_aio_300 > *(spmax + 2)) {
5402 *(spmax + 2) = psic->some_aio_300;
5404 if (psic->some_aio_300 < *(spmin + 2)) {
5405 *(spmin + 2) = psic->some_aio_300;
5407 tval = ((double) psic->some_io_total - psip->some_io_total) / (100 * itv);
5408 if (tval > *(spmax + 3)) {
5409 *(spmax + 3) = tval;
5411 if (tval < *(spmin + 3)) {
5412 *(spmin + 3) = tval;
5415 if (psic->full_aio_10 > *(spmax + 4)) {
5416 *(spmax + 4) = psic->full_aio_10;
5418 if (psic->full_aio_10 < *(spmin + 4)) {
5419 *(spmin + 4) = psic->full_aio_10;
5421 if (psic->full_aio_60 > *(spmax + 5)) {
5422 *(spmax + 5) = psic->full_aio_60;
5424 if (psic->full_aio_60 < *(spmin + 5)) {
5425 *(spmin + 5) = psic->full_aio_60;
5427 if (psic->full_aio_300 > *(spmax + 6)) {
5428 *(spmax + 6) = psic->full_aio_300;
5430 if (psic->full_aio_300 < *(spmin + 6)) {
5431 *(spmin + 6) = psic->full_aio_300;
5433 tval = ((double) psic->full_io_total - psip->full_io_total) / (100 * itv);
5434 if (tval > *(spmax + 7)) {
5435 *(spmax + 7) = tval;
5437 if (tval < *(spmin + 7)) {
5438 *(spmin + 7) = tval;
5442 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5443 (double) psic->some_aio_10 / 100,
5444 out, outsize, svg_p->restart);
5446 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5447 (double) psic->some_aio_60 / 100,
5448 out + 1, outsize + 1, svg_p->restart);
5450 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5451 (double) psic->some_aio_300 / 100,
5452 out + 2, outsize + 2, svg_p->restart);
5454 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5456 ((double) psic->some_io_total - psip->some_io_total) / (100 * itv),
5457 out + 3, outsize + 3, svg_p->dt);
5460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5461 (double) psic->full_aio_10 / 100,
5462 out + 4, outsize + 4, svg_p->restart);
5464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5465 (double) psic->full_aio_60 / 100,
5466 out + 5, outsize + 5, svg_p->restart);
5468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5469 (double) psic->full_aio_300 / 100,
5470 out + 6, outsize + 6, svg_p->restart);
5472 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5474 ((double) psic->full_io_total - psip->full_io_total) / (100 * itv),
5475 out + 7, outsize + 7, svg_p->dt);
5478 if (action & F_END) {
5479 /* Fix min/max values for pressure ratios */
5480 *spmin /= 100; *spmax /= 100;
5481 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5482 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5484 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5485 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5486 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5488 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5489 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5491 /* Free remaining structures */
5492 free_graphs(out, outsize, spmin, spmax);
5497 ***************************************************************************
5498 * Display pressure-stall memory statistics in SVG.
5501 * @a Activity structure with statistics.
5502 * @curr Index in array for current sample statistics.
5503 * @action Action expected from current function.
5504 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5505 * flag indicating that a restart record has been previously
5506 * found (.@restart) and time used for the X axis origin
5508 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5509 * @record_hdr Pointer on record header of current stats sample.
5510 ***************************************************************************
5512 __print_funct_t svg_print_psimem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5513 unsigned long long itv, struct record_header *record_hdr)
5515 struct stats_psi_mem
5516 *psic = (struct stats_psi_mem *) a->buf[curr],
5517 *psip = (struct stats_psi_mem *) a->buf[!curr];
5518 int group[] = {3, 1, 3, 1};
5519 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5520 char *title[] = {"Memory pressure trends (some tasks)", "Memory stall time (some tasks)",
5521 "Memory pressure trends (full)", "Memory stall time (full)"};
5522 char *g_title[] = {"%smem-10", "%smem-60", "%smem-300",
5524 "%fmem-10", "%fmem-60", "%fmem-300",
5526 static double *spmin, *spmax;
5528 static int *outsize;
5531 if (action & F_BEGIN) {
5533 * Allocate arrays that will contain the graphs data
5534 * and the min/max values.
5536 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5539 if (action & F_MAIN) {
5540 /* Check for min/max values */
5541 if (psic->some_amem_10 > *spmax) {
5542 *spmax = psic->some_amem_10;
5544 if (psic->some_amem_10 < *spmin) {
5545 *spmin = psic->some_amem_10;
5547 if (psic->some_amem_60 > *(spmax + 1)) {
5548 *(spmax + 1) = psic->some_amem_60;
5550 if (psic->some_amem_60 < *(spmin + 1)) {
5551 *(spmin + 1) = psic->some_amem_60;
5553 if (psic->some_amem_300 > *(spmax + 2)) {
5554 *(spmax + 2) = psic->some_amem_300;
5556 if (psic->some_amem_300 < *(spmin + 2)) {
5557 *(spmin + 2) = psic->some_amem_300;
5559 tval = ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv);
5560 if (tval > *(spmax + 3)) {
5561 *(spmax + 3) = tval;
5563 if (tval < *(spmin + 3)) {
5564 *(spmin + 3) = tval;
5567 if (psic->full_amem_10 > *(spmax + 4)) {
5568 *(spmax + 4) = psic->full_amem_10;
5570 if (psic->full_amem_10 < *(spmin + 4)) {
5571 *(spmin + 4) = psic->full_amem_10;
5573 if (psic->full_amem_60 > *(spmax + 5)) {
5574 *(spmax + 5) = psic->full_amem_60;
5576 if (psic->full_amem_60 < *(spmin + 5)) {
5577 *(spmin + 5) = psic->full_amem_60;
5579 if (psic->full_amem_300 > *(spmax + 6)) {
5580 *(spmax + 6) = psic->full_amem_300;
5582 if (psic->full_amem_300 < *(spmin + 6)) {
5583 *(spmin + 6) = psic->full_amem_300;
5585 tval = ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv);
5586 if (tval > *(spmax + 7)) {
5587 *(spmax + 7) = tval;
5589 if (tval < *(spmin + 7)) {
5590 *(spmin + 7) = tval;
5594 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5595 (double) psic->some_amem_10 / 100,
5596 out, outsize, svg_p->restart);
5598 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5599 (double) psic->some_amem_60 / 100,
5600 out + 1, outsize + 1, svg_p->restart);
5602 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5603 (double) psic->some_amem_300 / 100,
5604 out + 2, outsize + 2, svg_p->restart);
5606 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5608 ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv),
5609 out + 3, outsize + 3, svg_p->dt);
5612 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5613 (double) psic->full_amem_10 / 100,
5614 out + 4, outsize + 4, svg_p->restart);
5616 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5617 (double) psic->full_amem_60 / 100,
5618 out + 5, outsize + 5, svg_p->restart);
5620 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5621 (double) psic->full_amem_300 / 100,
5622 out + 6, outsize + 6, svg_p->restart);
5624 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5626 ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv),
5627 out + 7, outsize + 7, svg_p->dt);
5630 if (action & F_END) {
5631 /* Fix min/max values for pressure ratios */
5632 *spmin /= 100; *spmax /= 100;
5633 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5634 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5636 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5637 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5638 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5640 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5641 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5643 /* Free remaining structures */
5644 free_graphs(out, outsize, spmin, spmax);