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 #define CPU_ARRAY_SZ 10
1085 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1086 unsigned long long itv, struct record_header *record_hdr)
1088 struct stats_cpu *scc, *scp;
1089 unsigned long long deltot_jiffies = 1;
1090 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1093 int g_type[] = {SVG_BAR_GRAPH};
1094 char *title[] = {"CPU utilization"};
1095 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1096 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1097 static double *spmin, *spmax;
1099 static int *outsize;
1104 if (action & F_BEGIN) {
1106 * Allocate arrays that will contain the graphs data
1107 * and the min/max values.
1109 out = allocate_graph_lines(CPU_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
1112 if (action & F_MAIN) {
1114 /* @nr[curr] cannot normally be greater than @nr_ini */
1115 if (a->nr[curr] > a->nr_ini) {
1116 a->nr_ini = a->nr[curr];
1120 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1121 * and look for offline CPU.
1123 if (a->nr_ini > 1) {
1124 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1125 flags, offline_cpu_bitmap);
1129 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1131 /* Should current CPU (including CPU "all") be displayed? */
1132 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1133 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1134 /* Don't display CPU */
1137 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1138 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1140 pos = i * CPU_ARRAY_SZ;
1144 /* This is CPU "all" */
1145 if (a->nr_ini == 1) {
1147 * This is a UP machine. In this case
1148 * interval has still not been calculated.
1150 deltot_jiffies = get_per_cpu_interval(scc, scp);
1152 if (!deltot_jiffies) {
1153 /* CPU "all" cannot be tickless */
1159 * Recalculate interval for current proc.
1160 * If result is 0 then current CPU is a tickless one.
1162 deltot_jiffies = get_per_cpu_interval(scc, scp);
1164 if (!deltot_jiffies) { /* Current CPU is tickless */
1166 val = 100.0; /* Tickless CPU: %idle = 100% */
1168 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1171 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1175 /* Check min/max values for %user, etc. */
1176 for (k = 0; k < j; k++) {
1177 if (0.0 < *(spmin + pos + k)) {
1178 *(spmin + pos + k) = 0.0;
1180 if (0.0 > *(spmax + pos + k)) {
1181 *(spmax + pos + k) = 0.0;
1186 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1188 out + pos + j, outsize + pos + j, svg_p->dt,
1189 spmin + pos + j, spmax + pos + j);
1194 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1196 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1197 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1198 out + pos, outsize + pos, svg_p->dt,
1199 spmin + pos, spmax + pos);
1203 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1205 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1207 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1208 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1209 out + pos, outsize + pos, svg_p->dt,
1210 spmin + pos, spmax + pos);
1213 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1215 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1216 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1217 out + pos + 1, outsize + pos + 1, svg_p->dt,
1218 spmin + pos + 1, spmax + pos + 1);
1222 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1224 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1226 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1227 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1228 out + pos + 1, outsize + pos + 1, svg_p->dt,
1229 spmin + pos + 1, spmax + pos + 1);
1232 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1234 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1236 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1237 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1239 out + pos + 2, outsize + pos + 2, svg_p->dt,
1240 spmin + pos + 2, spmax + pos + 2);
1244 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1245 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1246 out + pos + 2, outsize + pos + 2, svg_p->dt,
1247 spmin + pos + 2, spmax + pos + 2);
1251 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1252 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1253 out + pos + 3, outsize + pos + 3, svg_p->dt,
1254 spmin + pos + 3, spmax + pos + 3);
1256 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1257 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1258 out + pos + 4, outsize + pos + 4, svg_p->dt,
1259 spmin + pos + 4, spmax + pos + 4);
1261 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1263 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1264 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1265 out + pos + 5, outsize + pos + 5, svg_p->dt,
1266 spmin + pos + 5, spmax + pos + 5);
1268 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1269 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1270 out + pos + 6, outsize + pos + 6, svg_p->dt,
1271 spmin + pos + 6, spmax + pos + 6);
1273 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1274 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1275 out + pos + 7, outsize + pos + 7, svg_p->dt,
1276 spmin + pos + 7, spmax + pos + 7);
1278 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1279 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1280 out + pos + 8, outsize + pos + 8, svg_p->dt,
1281 spmin + pos + 8, spmax + pos + 8);
1290 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1292 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1293 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1294 out + pos + j, outsize + pos + j, svg_p->dt,
1295 spmin + pos + j, spmax + pos + j);
1299 if (action & F_END) {
1300 int xid = 0, displayed;
1302 if (DISPLAY_IDLE(flags)) {
1303 /* Include additional %idle field */
1308 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
1310 /* Should current CPU (including CPU "all") be displayed? */
1311 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1315 pos = i * CPU_ARRAY_SZ;
1317 /* This is CPU "all" */
1318 strcpy(item_name, "all");
1321 sprintf(item_name, "%d", i - 1);
1324 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1325 displayed = draw_activity_graphs(a->g_nr, g_type,
1326 title, g_title1, item_name, group1,
1327 spmin + pos, spmax + pos, out + pos, outsize + pos,
1328 svg_p, record_hdr, i, a->id, xid);
1331 displayed = draw_activity_graphs(a->g_nr, g_type,
1332 title, g_title2, item_name, group2,
1333 spmin + pos, spmax + pos, out + pos, outsize + pos,
1334 svg_p, record_hdr, i, a->id, xid);
1341 /* Free remaining structures */
1342 free_graphs(out, outsize, spmin, spmax);
1347 ***************************************************************************
1348 * Display task creation and context switch statistics in SVG.
1351 * @a Activity structure with statistics.
1352 * @curr Index in array for current sample statistics.
1353 * @action Action expected from current function.
1354 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1355 * flag indicating that a restart record has been previously
1356 * found (.@restart) and time used for the X axis origin
1358 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1359 * @record_hdr Pointer on record header of current stats sample.
1360 ***************************************************************************
1362 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1363 unsigned long long itv, struct record_header *record_hdr)
1366 *spc = (struct stats_pcsw *) a->buf[curr],
1367 *spp = (struct stats_pcsw *) a->buf[!curr];
1368 int group[] = {1, 1};
1369 int g_fields[] = {1, 0};
1370 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1371 char *title[] = {"Task creation", "Switching activity"};
1372 char *g_title[] = {"proc/s",
1374 static double *spmin, *spmax;
1376 static int *outsize;
1378 if (action & F_BEGIN) {
1380 * Allocate arrays that will contain the graphs data
1381 * and the min/max values.
1383 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1386 if (action & F_MAIN) {
1387 /* Check for min/max values */
1388 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1389 itv, spmin, spmax, g_fields);
1391 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1392 S_VALUE(spp->processes, spc->processes, itv),
1393 out, outsize, svg_p->restart);
1395 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1396 S_VALUE(spp->context_switch, spc->context_switch, itv),
1397 out + 1, outsize + 1, svg_p->restart);
1400 if (action & F_END) {
1401 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1402 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1404 /* Free remaining structures */
1405 free_graphs(out, outsize, spmin, spmax);
1410 ***************************************************************************
1411 * Display swap statistics in SVG.
1414 * @a Activity structure with statistics.
1415 * @curr Index in array for current sample statistics.
1416 * @action Action expected from current function.
1417 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1418 * flag indicating that a restart record has been previously
1419 * found (.@restart) and time used for the X axis origin
1421 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1422 * @record_hdr Pointer on record header of current stats sample.
1423 ***************************************************************************
1425 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1426 unsigned long long itv, struct record_header *record_hdr)
1429 *ssc = (struct stats_swap *) a->buf[curr],
1430 *ssp = (struct stats_swap *) a->buf[!curr];
1432 int g_type[] = {SVG_LINE_GRAPH};
1433 char *title[] = {"Swap activity"};
1434 char *g_title[] = {"pswpin/s", "pswpout/s" };
1435 int g_fields[] = {0, 1};
1436 static double *spmin, *spmax;
1438 static int *outsize;
1440 if (action & F_BEGIN) {
1442 * Allocate arrays that will contain the graphs data
1443 * and the min/max values.
1445 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1448 if (action & F_MAIN) {
1449 /* Check for min/max values */
1450 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1451 itv, spmin, spmax, g_fields);
1453 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1454 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1455 out, outsize, svg_p->restart);
1457 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1458 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1459 out + 1, outsize + 1, svg_p->restart);
1462 if (action & F_END) {
1463 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1464 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1466 /* Free remaining structures */
1467 free_graphs(out, outsize, spmin, spmax);
1472 ***************************************************************************
1473 * Display paging statistics in SVG.
1476 * @a Activity structure with statistics.
1477 * @curr Index in array for current sample statistics.
1478 * @action Action expected from current function.
1479 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1480 * flag indicating that a restart record has been previously
1481 * found (.@restart) and time used for the X axis origin
1483 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1484 * @record_hdr Pointer on record header of current stats sample.
1485 ***************************************************************************
1487 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1488 unsigned long long itv, struct record_header *record_hdr)
1491 *spc = (struct stats_paging *) a->buf[curr],
1492 *spp = (struct stats_paging *) a->buf[!curr];
1493 int group[] = {2, 2, 4};
1494 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1495 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1496 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1497 "fault/s", "majflt/s",
1498 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1499 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1500 static double *spmin, *spmax;
1502 static int *outsize;
1504 if (action & F_BEGIN) {
1506 * Allocate arrays that will contain the graphs data
1507 * and the min/max values.
1509 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1512 if (action & F_MAIN) {
1513 /* Check for min/max values */
1514 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1515 itv, spmin, spmax, g_fields);
1517 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1518 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1519 out, outsize, svg_p->restart);
1521 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1522 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1523 out + 1, outsize + 1, svg_p->restart);
1525 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1526 S_VALUE(spp->pgfault, spc->pgfault, itv),
1527 out + 2, outsize + 2, svg_p->restart);
1529 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1530 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1531 out + 3, outsize + 3, svg_p->restart);
1533 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1534 S_VALUE(spp->pgfree, spc->pgfree, itv),
1535 out + 4, outsize + 4, svg_p->restart);
1537 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1538 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1539 out + 5, outsize + 5, svg_p->restart);
1541 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1542 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1543 out + 6, outsize + 6, svg_p->restart);
1545 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1546 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1547 out + 7, outsize + 7, svg_p->restart);
1550 if (action & F_END) {
1551 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1552 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1554 /* Free remaining structures */
1555 free_graphs(out, outsize, spmin, spmax);
1560 ***************************************************************************
1561 * Display I/O and transfer rate statistics in SVG.
1564 * @a Activity structure with statistics.
1565 * @curr Index in array for current sample statistics.
1566 * @action Action expected from current function.
1567 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1568 * flag indicating that a restart record has been previously
1569 * found (.@restart) and time used for the X axis origin
1571 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1572 * @record_hdr Pointer on record header of current stats sample.
1573 ***************************************************************************
1575 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1576 unsigned long long itv, struct record_header *record_hdr)
1579 *sic = (struct stats_io *) a->buf[curr],
1580 *sip = (struct stats_io *) a->buf[!curr];
1581 int group[] = {4, 3};
1582 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1583 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1584 char *g_title[] = {"tps", "rtps", "wtps", "dtps",
1585 "bread/s", "bwrtn/s", "bdscd/s"};
1587 * tps:0, rtps:1, wtps:2, dtps:3, bread/s:4, bwrtn/s:5, bdscd/s:6
1597 int g_fields[] = {0, 1, 2, 4, 5, 3, 6};
1598 static double *spmin, *spmax;
1600 static int *outsize;
1602 if (action & F_BEGIN) {
1604 * Allocate arrays that will contain the graphs data
1605 * and the min/max values.
1607 out = allocate_graph_lines(7, &outsize, &spmin, &spmax);
1610 if (action & F_MAIN) {
1611 /* Check for min/max values */
1612 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1613 itv, spmin, spmax, g_fields);
1616 * If we get negative values, this is probably because
1617 * one or more devices/filesystems have been unmounted.
1618 * We display 0.0 in this case though we should rather tell
1619 * the user that the value cannot be calculated here.
1622 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1623 sic->dk_drive < sip->dk_drive ? 0.0 :
1624 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1625 out, outsize, svg_p->restart);
1627 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1628 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1629 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1630 out + 1, outsize + 1, svg_p->restart);
1632 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1633 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1634 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1635 out + 2, outsize + 2, svg_p->restart);
1637 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1638 sic->dk_drive_dio < sip->dk_drive_dio ? 0.0 :
1639 S_VALUE(sip->dk_drive_dio, sic->dk_drive_dio, itv),
1640 out + 3, outsize + 3, svg_p->restart);
1642 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1643 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1644 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1645 out + 4, outsize + 4, svg_p->restart);
1647 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1648 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1649 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1650 out + 5, outsize + 5, svg_p->restart);
1652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1653 sic->dk_drive_dblk < sip->dk_drive_dblk ? 0.0 :
1654 S_VALUE(sip->dk_drive_dblk, sic->dk_drive_dblk, itv),
1655 out + 6, outsize + 6, svg_p->restart);
1658 if (action & F_END) {
1659 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1660 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1662 /* Free remaining structures */
1663 free_graphs(out, outsize, spmin, spmax);
1668 ***************************************************************************
1669 * Display memory statistics in SVG.
1672 * @a Activity structure with statistics.
1673 * @curr Index in array for current sample statistics.
1674 * @action Action expected from current function.
1675 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1676 * flag indicating that a restart record has been previously
1677 * found (.@restart) and time used for the X axis origin
1679 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1680 * @record_hdr Pointer on record header of current stats sample.
1681 ***************************************************************************
1683 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1684 unsigned long long itv, struct record_header *record_hdr)
1687 *smc = (struct stats_memory *) a->buf[curr];
1688 int group1[] = {3, 1, 3, 1, 3, 5};
1689 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1690 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1691 int group2[] = {3, 1, 1};
1692 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1693 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1694 "Memory utilization (3)", "Memory utilization (4)",
1695 "Memory utilization (5)", "Memory utilization (6)"};
1696 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1697 "Swap utilization (3)"};
1698 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1699 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1700 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1702 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1704 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1705 static double *spmin, *spmax;
1707 static int *outsize;
1711 unsigned long long nousedmem;
1713 if (action & F_BEGIN) {
1715 * Allocate arrays that will contain the graphs data
1716 * and the min/max values.
1718 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1721 if (action & F_MAIN) {
1722 /* Check for min/max values */
1723 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1724 itv, spmin, spmax, g_fields);
1725 /* Compute %memused min/max values */
1726 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1727 if (nousedmem > smc->tlmkb) {
1728 nousedmem = smc->tlmkb;
1730 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1731 if (tval > *(spmax + 3)) {
1732 *(spmax + 3) = tval;
1734 if (tval < *(spmin + 3)) {
1735 *(spmin + 3) = tval;
1737 /* Compute %commit min/max values */
1738 tval = (smc->tlmkb + smc->tlskb) ?
1739 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1740 if (tval > *(spmax + 7)) {
1741 *(spmax + 7) = tval;
1743 if (tval < *(spmin + 7)) {
1744 *(spmin + 7) = tval;
1746 /* Compute %swpused min/max values */
1748 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1749 if (tval > *(spmax + 19)) {
1750 *(spmax + 19) = tval;
1752 if (tval < *(spmin + 19)) {
1753 *(spmin + 19) = tval;
1755 /* Compute %swpcad min/max values */
1756 tval = (smc->tlskb - smc->frskb) ?
1757 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1758 if (tval > *(spmax + 20)) {
1759 *(spmax + 20) = tval;
1761 if (tval < *(spmin + 20)) {
1762 *(spmin + 20) = tval;
1764 /* Compute memused min/max values in MB */
1765 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1766 if (tval > *(spmax + 2)) {
1767 *(spmax + 2) = tval;
1769 if (tval < *(spmin + 2)) {
1770 *(spmin + 2) = tval;
1772 /* Compute swpused min/max values in MB */
1773 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1774 if (tval > *(spmax + 17)) {
1775 *(spmax + 17) = tval;
1777 if (tval < *(spmin + 17)) {
1778 *(spmin + 17) = tval;
1782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1783 ((double) smc->frmkb) / 1024,
1784 out, outsize, svg_p->restart);
1786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1787 ((double) (smc->tlmkb - nousedmem)) / 1024,
1788 out + 2, outsize + 2, svg_p->restart);
1790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1791 ((double) smc->availablekb) / 1024,
1792 out + 1, outsize + 1, svg_p->restart);
1794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1795 ((double) smc->bufkb) / 1024,
1796 out + 4, outsize + 4, svg_p->restart);
1798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1799 ((double) smc->camkb) / 1024,
1800 out + 5, outsize + 5, svg_p->restart);
1802 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1803 ((double) smc->frskb) / 1024,
1804 out + 16, outsize + 16, svg_p->restart);
1806 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1807 ((double) (smc->tlskb - smc->frskb)) / 1024,
1808 out + 17, outsize + 17, svg_p->restart);
1810 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1811 ((double) smc->caskb) / 1024,
1812 out + 18, outsize + 18, svg_p->restart);
1814 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1815 ((double) smc->comkb) / 1024,
1816 out + 6, outsize + 6, svg_p->restart);
1818 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1819 ((double) smc->activekb) / 1024,
1820 out + 8, outsize + 8, svg_p->restart);
1822 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1823 ((double) smc->inactkb) / 1024,
1824 out + 9, outsize + 9, svg_p->restart);
1826 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1827 ((double) smc->dirtykb) / 1024,
1828 out + 10, outsize + 10, svg_p->restart);
1830 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1831 ((double) smc->anonpgkb) / 1024,
1832 out + 11, outsize + 11, svg_p->restart);
1834 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1835 ((double) smc->slabkb) / 1024,
1836 out + 12, outsize + 12, svg_p->restart);
1838 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1839 ((double) smc->kstackkb) / 1024,
1840 out + 13, outsize + 13, svg_p->restart);
1842 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1843 ((double) smc->pgtblkb) / 1024,
1844 out + 14, outsize + 14, svg_p->restart);
1846 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1847 ((double) smc->vmusedkb) / 1024,
1848 out + 15, outsize + 15, svg_p->restart);
1850 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1853 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1854 out + 3, outsize + 3, svg_p->dt);
1856 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1858 (smc->tlmkb + smc->tlskb) ?
1859 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1860 out + 7, outsize + 7, svg_p->dt);
1862 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1865 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1866 out + 19, outsize + 19, svg_p->dt);
1868 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1870 (smc->tlskb - smc->frskb) ?
1871 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1872 out + 20, outsize + 20, svg_p->dt);
1875 if (action & F_END) {
1877 /* Conversion kB -> MB */
1878 for (i = 0; i < 17; i++) {
1879 *(spmin + g_fields[i]) /= 1024;
1880 *(spmax + g_fields[i]) /= 1024;
1883 if (DISPLAY_MEMORY(a->opt_flags)) {
1884 if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1885 g_type1, title1, g_title1, NULL, group1,
1886 spmin, spmax, out, outsize, svg_p, record_hdr,
1887 FALSE, a->id, xid)) {
1892 if (DISPLAY_SWAP(a->opt_flags)) {
1893 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1894 spmin + 16, spmax + 16, out + 16, outsize + 16,
1895 svg_p, record_hdr, FALSE, a->id, xid);
1898 /* Free remaining structures */
1899 free_graphs(out, outsize, spmin, spmax);
1904 ***************************************************************************
1905 * Display kernel tables statistics in SVG.
1908 * @a Activity structure with statistics.
1909 * @curr Index in array for current sample statistics.
1910 * @action Action expected from current function.
1911 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1912 * flag indicating that a restart record has been previously
1913 * found (.@restart) and time used for the X axis origin
1915 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1916 * @record_hdr Pointer on record header of current stats sample.
1917 ***************************************************************************
1919 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1920 unsigned long long itv, struct record_header *record_hdr)
1922 struct stats_ktables
1923 *skc = (struct stats_ktables *) a->buf[curr];
1924 int group[] = {3, 1};
1925 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1926 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1927 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1929 int g_fields[] = {1, 2, 0, 3};
1930 static double *spmin, *spmax;
1932 static int *outsize;
1934 if (action & F_BEGIN) {
1936 * Allocate arrays that will contain the graphs data
1937 * and the min/max values.
1939 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1942 if (action & F_MAIN) {
1943 /* Check for min/max values */
1944 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1945 itv, spmin, spmax, g_fields);
1947 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1948 (unsigned long long) skc->dentry_stat,
1949 out, outsize, svg_p->restart);
1951 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1952 (unsigned long long) skc->file_used,
1953 out + 1, outsize + 1, svg_p->restart);
1955 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1956 (unsigned long long) skc->inode_used,
1957 out + 2, outsize + 2, svg_p->restart);
1959 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1960 (unsigned long long) skc->pty_nr,
1961 out + 3, outsize + 3, svg_p->restart);
1964 if (action & F_END) {
1965 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1966 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1968 /* Free remaining structures */
1969 free_graphs(out, outsize, spmin, spmax);
1974 ***************************************************************************
1975 * Display queue and load statistics in SVG.
1978 * @a Activity structure with statistics.
1979 * @curr Index in array for current sample statistics.
1980 * @action Action expected from current function.
1981 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1982 * flag indicating that a restart record has been previously
1983 * found (.@restart) and time used for the X axis origin
1985 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1986 * @record_hdr Pointer on record header of current stats sample.
1987 ***************************************************************************
1989 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1990 unsigned long long itv, struct record_header *record_hdr)
1993 *sqc = (struct stats_queue *) a->buf[curr];
1994 int group[] = {2, 1, 3};
1995 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1996 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
1997 char *g_title[] = {"~runq-sz", "~blocked",
1999 "ldavg-1", "ldavg-5", "ldavg-15"};
2000 int g_fields[] = {0, 1, 2, 3, 4, 5};
2001 static double *spmin, *spmax;
2003 static int *outsize;
2005 if (action & F_BEGIN) {
2007 * Allocate arrays that will contain the graphs data
2008 * and the min/max values.
2010 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2013 if (action & F_MAIN) {
2014 /* Check for min/max values */
2015 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2016 itv, spmin, spmax, g_fields);
2018 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2019 (unsigned long long) sqc->nr_running,
2020 out, outsize, svg_p->restart);
2022 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2023 (unsigned long long) sqc->procs_blocked,
2024 out + 1, outsize + 1, svg_p->restart);
2026 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2027 (unsigned long long) sqc->nr_threads,
2028 out + 2, outsize + 2, svg_p->restart);
2030 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2031 (double) sqc->load_avg_1 / 100,
2032 out + 3, outsize + 3, svg_p->restart);
2034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2035 (double) sqc->load_avg_5 / 100,
2036 out + 4, outsize + 4, svg_p->restart);
2038 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2039 (double) sqc->load_avg_15 / 100,
2040 out + 5, outsize + 5, svg_p->restart);
2043 if (action & F_END) {
2044 /* Fix min/max values for load average */
2045 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2046 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2047 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2049 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2050 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2052 /* Free remaining structures */
2053 free_graphs(out, outsize, spmin, spmax);
2058 ***************************************************************************
2059 * Display disk statistics in SVG.
2062 * @a Activity structure with statistics.
2063 * @curr Index in array for current sample statistics.
2064 * @action Action expected from current function.
2065 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2066 * flag indicating that a restart record has been previously
2067 * found (.@restart) and time used for the X axis origin
2069 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2070 * @record_hdr Pointer on record header of current stats sample.
2071 ***************************************************************************
2073 #define DISK_ARRAY_SZ 9
2074 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2075 unsigned long long itv, struct record_header *record_hdr)
2077 struct stats_disk *sdc, *sdp, sdpzero;
2078 struct ext_disk_stats xds;
2079 int group[] = {1, 3, 2, 1, 1};
2080 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2081 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2082 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2083 "Block devices statistics (3)", "Block devices statistics (4)",
2084 "Block devices statistics (5)"};
2085 char *g_title[] = {"tps",
2086 "rkB/s", "wkB/s", "dkB/s",
2087 "areq-sz", "aqu-sz",
2090 int g_fields[] = {0, 1, 2};
2091 unsigned int local_types_nr[] = {1, 0, 0};
2092 static double *spmin, *spmax;
2094 static int *outsize;
2095 char *dev_name, *item_name;
2096 double rkB, wkB, dkB, aqusz;
2097 int i, j, k, pos, restart, *unregistered;
2099 if (action & F_BEGIN) {
2101 * Allocate arrays (#0..7) that will contain the graphs data
2102 * and the min/max values.
2103 * Also allocate one additional array (#8) for each disk device:
2104 * out + 8 will contain the device name (WWN id, pretty name or devm-n),
2105 * outsize + 8 will contain a positive value (TRUE) if the device
2106 * has either still not been registered, or has been unregistered.
2108 out = allocate_graph_lines(DISK_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2111 if (action & F_MAIN) {
2112 memset(&sdpzero, 0, STATS_DISK_SIZE);
2113 restart = svg_p->restart;
2115 * Mark previously registered devices as now
2116 * possibly unregistered for all graphs.
2118 for (k = 0; k < a->item_list_sz; k++) {
2119 unregistered = outsize + k * DISK_ARRAY_SZ + 8;
2120 if (*unregistered == FALSE) {
2121 *unregistered = MAYBE;
2125 /* For each device structure */
2126 for (i = 0; i < a->nr[curr]; i++) {
2127 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2129 /* Get device name */
2130 dev_name = get_device_name(sdc->major, sdc->minor, sdc->wwn, sdc->part_nr,
2131 DISPLAY_PRETTY(flags), DISPLAY_PERSIST_NAME_S(flags),
2132 USE_STABLE_ID(flags), NULL);
2134 if (a->item_list != NULL) {
2135 /* A list of devices has been entered on the command line */
2136 if (!search_list_item(a->item_list, dev_name))
2137 /* Device not found */
2141 /* Look for corresponding graph */
2142 for (k = 0; k < a->item_list_sz; k++) {
2143 item_name = *(out + k * DISK_ARRAY_SZ + 8);
2144 if (!strcmp(dev_name, item_name))
2148 if (k == a->item_list_sz) {
2149 /* Graph not found: Look for first free entry */
2150 for (k = 0; k < a->item_list_sz; k++) {
2151 item_name = *(out + k * DISK_ARRAY_SZ + 8);
2152 if (!strcmp(item_name, ""))
2155 if (k == a->item_list_sz) {
2156 /* No free graph entry: Ignore it (should never happen) */
2158 fprintf(stderr, "%s: Name=%s major=%d minor=%d\n",
2159 __FUNCTION__, dev_name, sdc->major, sdc->minor);
2164 pos = k * DISK_ARRAY_SZ;
2165 unregistered = outsize + pos + 8;
2168 * If current device was marked as previously unregistered,
2169 * then set restart variable to TRUE so that the graph will be
2170 * discontinuous, and mark it as now registered.
2172 if (*unregistered == TRUE) {
2175 *unregistered = FALSE;
2177 item_name = *(out + pos + 8);
2178 if (!item_name[0]) {
2179 /* Save device name (WWN id or pretty name) if not already done */
2180 strncpy(item_name, dev_name, CHUNKSIZE);
2181 item_name[CHUNKSIZE - 1] = '\0';
2184 j = check_disk_reg(a, curr, !curr, i);
2186 /* This is a newly registered interface. Previous stats are zero */
2190 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2193 /* Check for min/max values */
2194 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2195 itv, spmin + pos, spmax + pos, g_fields);
2197 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2198 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2199 dkB = S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2;
2200 if (rkB < *(spmin + pos + 1)) {
2201 *(spmin + pos + 1) = rkB;
2203 if (rkB > *(spmax + pos + 1)) {
2204 *(spmax + pos + 1) = rkB;
2206 if (wkB < *(spmin + pos + 2)) {
2207 *(spmin + pos + 2) = wkB;
2209 if (wkB > *(spmax + pos + 2)) {
2210 *(spmax + pos + 2) = wkB;
2212 if (dkB < *(spmin + pos + 3)) {
2213 *(spmin + pos + 3) = dkB;
2215 if (dkB > *(spmax + pos + 3)) {
2216 *(spmax + pos + 3) = dkB;
2219 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2220 if ((xds.arqsz / 2) < *(spmin + pos + 4)) {
2221 *(spmin + pos + 4) = xds.arqsz / 2;
2223 if ((xds.arqsz / 2) > *(spmax + pos + 4)) {
2224 *(spmax + pos + 4) = xds.arqsz / 2;
2226 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2227 if (aqusz < *(spmin + pos + 5)) {
2228 *(spmin + pos + 5) = aqusz;
2230 if (aqusz > *(spmax + pos + 5)) {
2231 *(spmax + pos + 5) = aqusz;
2233 if (xds.await < *(spmin + pos + 6)) {
2234 *(spmin + pos + 6) = xds.await;
2236 if (xds.await > *(spmax + pos + 6)) {
2237 *(spmax + pos + 6) = xds.await;
2239 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2240 *(spmin + pos + 7) = xds.util / 10.0;
2242 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2243 *(spmax + pos + 7) = xds.util / 10.0;
2247 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2248 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2249 out + pos, outsize + pos, restart);
2251 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2252 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2253 out + pos + 1, outsize + pos + 1, restart);
2255 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2256 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2257 out + pos + 2, outsize + pos + 2, restart);
2259 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2260 S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2,
2261 out + pos + 3, outsize + pos + 3, restart);
2263 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2265 out + pos + 4, outsize + pos + 4, restart);
2267 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2269 out + pos + 5, outsize + pos + 5, restart);
2271 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2273 out + pos + 6, outsize + pos + 6, restart);
2275 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2276 0.0, xds.util / 10.0,
2277 out + pos + 7, outsize + pos + 7, svg_p->dt);
2280 /* Mark devices not seen here as now unregistered */
2281 for (k = 0; k < a->item_list_sz; k++) {
2282 unregistered = outsize + k * DISK_ARRAY_SZ + 8;
2283 if (*unregistered != FALSE) {
2284 *unregistered = TRUE;
2289 if (action & F_END) {
2292 for (i = 0; i < a->item_list_sz; i++) {
2293 /* Check if there is something to display */
2294 pos = i * DISK_ARRAY_SZ;
2298 item_name = *(out + pos + 8);
2299 if (draw_activity_graphs(a->g_nr, g_type,
2300 title, g_title, item_name, group,
2301 spmin + pos, spmax + pos, out + pos, outsize + pos,
2302 svg_p, record_hdr, FALSE, a->id, xid)) {
2307 /* Free remaining structures */
2308 free_graphs(out, outsize, spmin, spmax);
2313 ***************************************************************************
2314 * Display network interfaces statistics in SVG.
2317 * @a Activity structure with statistics.
2318 * @curr Index in array for current sample statistics.
2319 * @action Action expected from current function.
2320 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2321 * flag indicating that a restart record has been previously
2322 * found (.@restart) and time used for the X axis origin
2324 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2325 * @record_hdr Pointer on record header of current stats sample.
2326 ***************************************************************************
2328 #define NET_DEV_ARRAY_SZ 9
2329 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2330 unsigned long long itv, struct record_header *record_hdr)
2332 struct stats_net_dev *sndc, *sndp, sndzero;
2333 int group[] = {2, 2, 3, 1};
2334 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2336 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2337 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2338 char *g_title[] = {"rxpck/s", "txpck/s",
2340 "rxcmp/s", "txcmp/s", "rxmcst/s",
2342 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2343 unsigned int local_types_nr[] = {7, 0, 0};
2344 static double *spmin, *spmax;
2346 static int *outsize;
2348 double rxkb, txkb, ifutil;
2349 int i, j, k, pos, restart, *unregistered;
2351 if (action & F_BEGIN) {
2353 * Allocate arrays (#0..7) that will contain the graphs data
2354 * and the min/max values.
2355 * Also allocate one additional array (#8) for each interface:
2356 * out + 8 will contain the interface name,
2357 * outsize + 8 will contain a positive value (TRUE) if the interface
2358 * has either still not been registered, or has been unregistered.
2360 out = allocate_graph_lines(NET_DEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2363 if (action & F_MAIN) {
2364 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2365 restart = svg_p->restart;
2367 * Mark previously registered interfaces as now
2368 * possibly unregistered for all graphs.
2370 for (k = 0; k < a->item_list_sz; k++) {
2371 unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
2372 if (*unregistered == FALSE) {
2373 *unregistered = MAYBE;
2377 /* For each network interfaces structure */
2378 for (i = 0; i < a->nr[curr]; i++) {
2379 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2381 if (a->item_list != NULL) {
2382 /* A list of devices has been entered on the command line */
2383 if (!search_list_item(a->item_list, sndc->interface))
2384 /* Device not found */
2388 /* Look for corresponding graph */
2389 for (k = 0; k < a->item_list_sz; k++) {
2390 item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
2391 if (!strcmp(sndc->interface, item_name))
2395 if (k == a->item_list_sz) {
2396 /* Graph not found: Look for first free entry */
2397 for (k = 0; k < a->item_list_sz; k++) {
2398 item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
2399 if (!strcmp(item_name, ""))
2402 if (k == a->item_list_sz) {
2403 /* No free graph entry: Ignore it (should never happen) */
2405 fprintf(stderr, "%s: Name=%s\n",
2406 __FUNCTION__, sndc->interface);
2411 pos = k * NET_DEV_ARRAY_SZ;
2412 unregistered = outsize + pos + 8;
2414 j = check_net_dev_reg(a, curr, !curr, i);
2416 /* This is a newly registered interface. Previous stats are zero */
2420 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2424 * If current interface was marked as previously unregistered,
2425 * then set restart variable to TRUE so that the graph will be
2426 * discontinuous, and mark it as now registered.
2428 if (*unregistered == TRUE) {
2431 *unregistered = FALSE;
2433 item_name = *(out + pos + 8);
2434 if (!item_name[0]) {
2435 /* Save network interface name (if not already done) */
2436 strncpy(item_name, sndc->interface, CHUNKSIZE);
2437 item_name[CHUNKSIZE - 1] = '\0';
2440 /* Check for min/max values */
2441 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2442 itv, spmin + pos, spmax + pos, g_fields);
2444 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2445 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2446 ifutil = compute_ifutil(sndc, rxkb, txkb);
2447 if (ifutil < *(spmin + pos + 7)) {
2448 *(spmin + pos + 7) = ifutil;
2450 if (ifutil > *(spmax + pos + 7)) {
2451 *(spmax + pos + 7) = ifutil;
2455 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2456 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2457 out + pos, outsize + pos, restart);
2459 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2460 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2461 out + pos + 1, outsize + pos + 1, restart);
2463 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2465 out + pos + 2, outsize + pos + 2, restart);
2467 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2469 out + pos + 3, outsize + pos + 3, restart);
2471 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2472 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2473 out + pos + 4, outsize + pos + 4, restart);
2475 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2476 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2477 out + pos + 5, outsize + pos + 5, restart);
2479 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2480 S_VALUE(sndp->multicast, sndc->multicast, itv),
2481 out + pos + 6, outsize + pos + 6, restart);
2483 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2485 out + pos + 7, outsize + pos + 7, svg_p->dt);
2488 /* Mark interfaces not seen here as now unregistered */
2489 for (k = 0; k < a->item_list_sz; k++) {
2490 unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
2491 if (*unregistered != FALSE) {
2492 *unregistered = TRUE;
2497 if (action & F_END) {
2500 for (i = 0; i < a->item_list_sz; i++) {
2502 * Check if there is something to display.
2503 * Don't test sndc->interface because maybe the network
2504 * interface has been registered later.
2506 pos = i * NET_DEV_ARRAY_SZ;
2510 /* Recalculate min and max values in kB, not in B */
2511 *(spmin + pos + 2) /= 1024;
2512 *(spmax + pos + 2) /= 1024;
2513 *(spmin + pos + 3) /= 1024;
2514 *(spmax + pos + 3) /= 1024;
2516 item_name = *(out + pos + 8);
2517 if (draw_activity_graphs(a->g_nr, g_type,
2518 title, g_title, item_name, group,
2519 spmin + pos, spmax + pos, out + pos, outsize + pos,
2520 svg_p, record_hdr, FALSE, a->id, xid)) {
2525 /* Free remaining structures */
2526 free_graphs(out, outsize, spmin, spmax);
2531 ***************************************************************************
2532 * Display network interfaces errors statistics in SVG.
2535 * @a Activity structure with statistics.
2536 * @curr Index in array for current sample statistics.
2537 * @action Action expected from current function.
2538 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2539 * flag indicating that a restart record has been previously
2540 * found (.@restart) and time used for the X axis origin
2542 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2543 * @record_hdr Pointer on record header of current stats sample.
2544 ***************************************************************************
2546 #define NET_EDEV_ARRAY_SZ 10
2547 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2548 unsigned long long itv, struct record_header *record_hdr)
2550 struct stats_net_edev *snedc, *snedp, snedzero;
2551 int group[] = {2, 2, 2, 3};
2552 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2554 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2555 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2556 char *g_title[] = {"rxerr/s", "txerr/s",
2557 "rxdrop/s", "txdrop/s",
2558 "rxfifo/s", "txfifo/s",
2559 "coll/s", "txcarr/s", "rxfram/s"};
2560 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2561 static double *spmin, *spmax;
2563 static int *outsize;
2565 int i, j, k, pos, restart, *unregistered;
2567 if (action & F_BEGIN) {
2569 * Allocate arrays (#0..8) that will contain the graphs data
2570 * and the min/max values.
2571 * Also allocate one additional array (#9) for each interface:
2572 * out + 9 will contain the interface name,
2573 * outsize + 9 will contain a positive value (TRUE) if the interface
2574 * has either still not been registered, or has been unregistered.
2576 out = allocate_graph_lines(NET_EDEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2579 if (action & F_MAIN) {
2580 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2581 restart = svg_p->restart;
2583 * Mark previously registered interfaces as now
2584 * possibly unregistered for all graphs.
2586 for (k = 0; k < a->item_list_sz; k++) {
2587 unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
2588 if (*unregistered == FALSE) {
2589 *unregistered = MAYBE;
2593 /* For each network interfaces structure */
2594 for (i = 0; i < a->nr[curr]; i++) {
2595 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2596 if (!strcmp(snedc->interface, ""))
2597 /* Empty structure: This is the end of the list */
2600 if (a->item_list != NULL) {
2601 /* A list of devices has been entered on the command line */
2602 if (!search_list_item(a->item_list, snedc->interface))
2603 /* Device not found */
2607 /* Look for corresponding graph */
2608 for (k = 0; k < a->item_list_sz; k++) {
2609 item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
2610 if (!strcmp(snedc->interface, item_name))
2614 if (k == a->item_list_sz) {
2615 /* Graph not found: Look for first free entry */
2616 for (k = 0; k < a->item_list_sz; k++) {
2617 item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
2618 if (!strcmp(item_name, ""))
2621 if (k == a->item_list_sz) {
2622 /* No free graph entry: Ignore it (should never happen) */
2624 fprintf(stderr, "%s: Name=%s\n",
2625 __FUNCTION__, snedc->interface);
2631 pos = k * NET_EDEV_ARRAY_SZ;
2632 unregistered = outsize + pos + 9;
2634 j = check_net_edev_reg(a, curr, !curr, i);
2636 /* This is a newly registered interface. Previous stats are zero */
2640 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2644 * If current interface was marked as previously unregistered,
2645 * then set restart variable to TRUE so that the graph will be
2646 * discontinuous, and mark it as now registered.
2648 if (*unregistered == TRUE) {
2651 *unregistered = FALSE;
2653 item_name = *(out + pos + 9);
2654 if (!item_name[0]) {
2655 /* Save network interface name (if not already done) */
2656 strncpy(item_name, snedc->interface, CHUNKSIZE);
2657 item_name[CHUNKSIZE - 1] = '\0';
2660 /* Check for min/max values */
2661 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2662 itv, spmin + pos, spmax + pos, g_fields);
2665 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2666 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2667 out + pos, outsize + pos, restart);
2669 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2670 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2671 out + pos + 1, outsize + pos + 1, restart);
2673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2674 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2675 out + pos + 2, outsize + pos + 2, restart);
2677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2678 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2679 out + pos + 3, outsize + pos + 3, restart);
2681 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2682 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2683 out + pos + 4, outsize + pos + 4, restart);
2685 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2686 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2687 out + pos + 5, outsize + pos + 5, restart);
2689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2690 S_VALUE(snedp->collisions, snedc->collisions, itv),
2691 out + pos + 6, outsize + pos + 6, restart);
2693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2694 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2695 out + pos + 7, outsize + pos + 7, restart);
2697 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2698 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2699 out + pos + 8, outsize + pos + 8, restart);
2702 /* Mark interfaces not seen here as now unregistered */
2703 for (k = 0; k < a->item_list_sz; k++) {
2704 unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
2705 if (*unregistered != FALSE) {
2706 *unregistered = TRUE;
2711 if (action & F_END) {
2714 for (i = 0; i < a->item_list_sz; i++) {
2716 * Check if there is something to display.
2717 * Don't test snedc->interface because maybe the network
2718 * interface has been registered later.
2720 pos = i * NET_EDEV_ARRAY_SZ;
2724 item_name = *(out + pos + 9);
2725 if (draw_activity_graphs(a->g_nr, g_type,
2726 title, g_title, item_name, group,
2727 spmin + pos, spmax + pos, out + pos, outsize + pos,
2728 svg_p, record_hdr, FALSE, a->id, xid)) {
2733 /* Free remaining structures */
2734 free_graphs(out, outsize, spmin, spmax);
2739 ***************************************************************************
2740 * Display NFS client statistics in SVG.
2743 * @a Activity structure with statistics.
2744 * @curr Index in array for current sample statistics.
2745 * @action Action expected from current function.
2746 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2747 * flag indicating that a restart record has been previously
2748 * found (.@restart) and time used for the X axis origin
2750 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2751 * @record_hdr Pointer on record header of current stats sample.
2752 ***************************************************************************
2754 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2755 unsigned long long itv, struct record_header *record_hdr)
2757 struct stats_net_nfs
2758 *snnc = (struct stats_net_nfs *) a->buf[curr],
2759 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2760 int group[] = {2, 2, 2};
2761 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2762 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2763 "NFS client statistics (3)"};
2764 char *g_title[] = {"call/s", "retrans/s",
2765 "read/s", "write/s",
2766 "access/s", "getatt/s"};
2767 int g_fields[] = {0, 1, 2, 3, 4, 5};
2768 static double *spmin, *spmax;
2770 static int *outsize;
2772 if (action & F_BEGIN) {
2774 * Allocate arrays that will contain the graphs data
2775 * and the min/max values.
2777 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2780 if (action & F_MAIN) {
2781 /* Check for min/max values */
2782 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2783 itv, spmin, spmax, g_fields);
2786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2787 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2788 out, outsize, svg_p->restart);
2790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2791 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2792 out + 1, outsize + 1, svg_p->restart);
2794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2795 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2796 out + 2, outsize + 2, svg_p->restart);
2798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2799 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2800 out + 3, outsize + 3, svg_p->restart);
2802 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2803 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2804 out + 4, outsize + 4, svg_p->restart);
2806 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2807 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2808 out + 5, outsize + 5, svg_p->restart);
2811 if (action & F_END) {
2812 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2813 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2815 /* Free remaining structures */
2816 free_graphs(out, outsize, spmin, spmax);
2821 ***************************************************************************
2822 * Display NFS server statistics in SVG.
2825 * @a Activity structure with statistics.
2826 * @curr Index in array for current sample statistics.
2827 * @action Action expected from current function.
2828 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2829 * flag indicating that a restart record has been previously
2830 * found (.@restart) and time used for the X axis origin
2832 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2833 * @record_hdr Pointer on record header of current stats sample.
2834 ***************************************************************************
2836 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2837 unsigned long long itv, struct record_header *record_hdr)
2839 struct stats_net_nfsd
2840 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2841 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2842 int group[] = {2, 3, 2, 2, 2};
2843 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2844 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2845 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2846 "NFS server statistics (3)", "NFS server statistics (4)",
2847 "NFS server statistics (5)"};
2848 char *g_title[] = {"scall/s", "badcall/s",
2849 "packet/s", "udp/s", "tcp/s",
2851 "sread/s", "swrite/s",
2852 "saccess/s", "sgetatt/s"};
2853 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2854 static double *spmin, *spmax;
2856 static int *outsize;
2858 if (action & F_BEGIN) {
2860 * Allocate arrays that will contain the graphs data
2861 * and the min/max values.
2863 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2866 if (action & F_MAIN) {
2867 /* Check for min/max values */
2868 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2869 itv, spmin, spmax, g_fields);
2872 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2873 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2874 out, outsize, svg_p->restart);
2876 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2877 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2878 out + 1, outsize + 1, svg_p->restart);
2880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2881 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2882 out + 2, outsize + 2, svg_p->restart);
2884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2885 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2886 out + 3, outsize + 3, svg_p->restart);
2888 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2889 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2890 out + 4, outsize + 4, svg_p->restart);
2892 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2893 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2894 out + 5, outsize + 5, svg_p->restart);
2896 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2897 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2898 out + 6, outsize + 6, svg_p->restart);
2900 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2901 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2902 out + 7, outsize + 7, svg_p->restart);
2904 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2905 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2906 out + 8, outsize + 8, svg_p->restart);
2908 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2909 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2910 out + 9, outsize + 9, svg_p->restart);
2912 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2913 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2914 out + 10, outsize + 10, svg_p->restart);
2917 if (action & F_END) {
2918 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2919 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2921 /* Free remaining structures */
2922 free_graphs(out, outsize, spmin, spmax);
2927 ***************************************************************************
2928 * Display socket statistics in SVG.
2931 * @a Activity structure with statistics.
2932 * @curr Index in array for current sample statistics.
2933 * @action Action expected from current function.
2934 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2935 * flag indicating that a restart record has been previously
2936 * found (.@restart) and time used for the X axis origin
2938 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2939 * @record_hdr Pointer on record header of current stats sample.
2940 ***************************************************************************
2942 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2943 unsigned long long itv, struct record_header *record_hdr)
2945 struct stats_net_sock
2946 *snsc = (struct stats_net_sock *) a->buf[curr];
2947 int group[] = {1, 5};
2948 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2949 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2950 char *g_title[] = {"~totsck",
2951 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2952 int g_fields[] = {0, 1, 5, 2, 3, 4};
2953 static double *spmin, *spmax;
2955 static int *outsize;
2957 if (action & F_BEGIN) {
2959 * Allocate arrays that will contain the graphs data
2960 * and the min/max values.
2962 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2965 if (action & F_MAIN) {
2966 /* Check for min/max values */
2967 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2968 itv, spmin, spmax, g_fields);
2970 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2971 (unsigned long long) snsc->sock_inuse,
2972 out, outsize, svg_p->restart);
2974 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2975 (unsigned long long) snsc->tcp_inuse,
2976 out + 1, outsize + 1, svg_p->restart);
2978 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2979 (unsigned long long) snsc->udp_inuse,
2980 out + 2, outsize + 2, svg_p->restart);
2982 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2983 (unsigned long long) snsc->raw_inuse,
2984 out + 3, outsize + 3, svg_p->restart);
2986 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2987 (unsigned long long) snsc->frag_inuse,
2988 out + 4, outsize + 4, svg_p->restart);
2990 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2991 (unsigned long long) snsc->tcp_tw,
2992 out + 5, outsize + 5, svg_p->restart);
2995 if (action & F_END) {
2996 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2997 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2999 /* Free remaining structures */
3000 free_graphs(out, outsize, spmin, spmax);
3005 ***************************************************************************
3006 * Display IPv4 traffic statistics in SVG.
3009 * @a Activity structure with statistics.
3010 * @curr Index in array for current sample statistics.
3011 * @action Action expected from current function.
3012 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3013 * flag indicating that a restart record has been previously
3014 * found (.@restart) and time used for the X axis origin
3016 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3017 * @record_hdr Pointer on record header of current stats sample.
3018 ***************************************************************************
3020 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3021 unsigned long long itv, struct record_header *record_hdr)
3024 *snic = (struct stats_net_ip *) a->buf[curr],
3025 *snip = (struct stats_net_ip *) a->buf[!curr];
3026 int group[] = {4, 2, 2};
3027 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3028 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
3029 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
3030 "asmrq/s", "asmok/s",
3031 "fragok/s", "fragcrt/s"};
3032 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3033 static double *spmin, *spmax;
3035 static int *outsize;
3037 if (action & F_BEGIN) {
3039 * Allocate arrays that will contain the graphs data
3040 * and the min/max values.
3042 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3045 if (action & F_MAIN) {
3046 /* Check for min/max values */
3047 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3048 itv, spmin, spmax, g_fields);
3051 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3052 S_VALUE(snip->InReceives, snic->InReceives, itv),
3053 out, outsize, svg_p->restart);
3055 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3056 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
3057 out + 1, outsize + 1, svg_p->restart);
3059 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3060 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
3061 out + 2, outsize + 2, svg_p->restart);
3063 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3064 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3065 out + 3, outsize + 3, svg_p->restart);
3067 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3068 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3069 out + 4, outsize + 4, svg_p->restart);
3071 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3072 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3073 out + 5, outsize + 5, svg_p->restart);
3075 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3076 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3077 out + 6, outsize + 6, svg_p->restart);
3079 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3080 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3081 out + 7, outsize + 7, svg_p->restart);
3084 if (action & F_END) {
3085 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3086 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3088 /* Free remaining structures */
3089 free_graphs(out, outsize, spmin, spmax);
3094 ***************************************************************************
3095 * Display IPv4 traffic errors statistics in SVG.
3098 * @a Activity structure with statistics.
3099 * @curr Index in array for current sample statistics.
3100 * @action Action expected from current function.
3101 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3102 * flag indicating that a restart record has been previously
3103 * found (.@restart) and time used for the X axis origin
3105 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3106 * @record_hdr Pointer on record header of current stats sample.
3107 ***************************************************************************
3109 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3110 unsigned long long itv, struct record_header *record_hdr)
3112 struct stats_net_eip
3113 *sneic = (struct stats_net_eip *) a->buf[curr],
3114 *sneip = (struct stats_net_eip *) a->buf[!curr];
3115 int group[] = {3, 2, 3};
3116 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3117 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3118 "IPv4 traffic errors statistics (3)"};
3119 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3120 "idisc/s", "odisc/s",
3121 "onort/s", "asmf/s", "fragf/s"};
3122 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3123 static double *spmin, *spmax;
3125 static int *outsize;
3127 if (action & F_BEGIN) {
3129 * Allocate arrays that will contain the graphs data
3130 * and the min/max values.
3132 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3135 if (action & F_MAIN) {
3136 /* Check for min/max values */
3137 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3138 itv, spmin, spmax, g_fields);
3141 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3142 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3143 out, outsize, svg_p->restart);
3145 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3146 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3147 out + 1, outsize + 1, svg_p->restart);
3149 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3150 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3151 out + 2, outsize + 2, svg_p->restart);
3153 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3154 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3155 out + 3, outsize + 3, svg_p->restart);
3157 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3158 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3159 out + 4, outsize + 4, svg_p->restart);
3161 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3162 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3163 out + 5, outsize + 5, svg_p->restart);
3165 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3166 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3167 out + 6, outsize + 6, svg_p->restart);
3169 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3170 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3171 out + 7, outsize + 7, svg_p->restart);
3174 if (action & F_END) {
3175 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3176 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3178 /* Free remaining structures */
3179 free_graphs(out, outsize, spmin, spmax);
3184 ***************************************************************************
3185 * Display ICMPv4 traffic statistics in SVG.
3188 * @a Activity structure with statistics.
3189 * @curr Index in array for current sample statistics.
3190 * @action Action expected from current function.
3191 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3192 * flag indicating that a restart record has been previously
3193 * found (.@restart) and time used for the X axis origin
3195 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3196 * @record_hdr Pointer on record header of current stats sample.
3197 ***************************************************************************
3199 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3200 unsigned long long itv, struct record_header *record_hdr)
3202 struct stats_net_icmp
3203 *snic = (struct stats_net_icmp *) a->buf[curr],
3204 *snip = (struct stats_net_icmp *) a->buf[!curr];
3205 int group[] = {2, 4, 4, 4};
3206 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3208 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3209 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3210 char *g_title[] = {"imsg/s", "omsg/s",
3211 "iech/s", "iechr/s", "oech/s", "oechr/s",
3212 "itm/s", "itmr/s", "otm/s", "otmr/s",
3213 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3214 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3215 static double *spmin, *spmax;
3217 static int *outsize;
3219 if (action & F_BEGIN) {
3221 * Allocate arrays that will contain the graphs data
3222 * and the min/max values.
3224 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3227 if (action & F_MAIN) {
3228 /* Check for min/max values */
3229 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3230 itv, spmin, spmax, g_fields);
3233 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3234 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3235 out, outsize, svg_p->restart);
3237 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3238 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3239 out + 1, outsize + 1, svg_p->restart);
3241 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3242 S_VALUE(snip->InEchos, snic->InEchos, itv),
3243 out + 2, outsize + 2, svg_p->restart);
3245 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3246 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3247 out + 3, outsize + 3, svg_p->restart);
3249 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3250 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3251 out + 4, outsize + 4, svg_p->restart);
3253 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3254 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3255 out + 5, outsize + 5, svg_p->restart);
3257 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3258 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3259 out + 6, outsize + 6, svg_p->restart);
3261 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3262 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3263 out + 7, outsize + 7, svg_p->restart);
3265 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3266 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3267 out + 8, outsize + 8, svg_p->restart);
3269 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3270 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3271 out + 9, outsize + 9, svg_p->restart);
3273 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3274 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3275 out + 10, outsize + 10, svg_p->restart);
3277 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3278 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3279 out + 11, outsize + 11, svg_p->restart);
3281 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3282 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3283 out + 12, outsize + 12, svg_p->restart);
3285 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3286 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3287 out + 13, outsize + 13, svg_p->restart);
3290 if (action & F_END) {
3291 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3292 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3294 /* Free remaining structures */
3295 free_graphs(out, outsize, spmin, spmax);
3300 ***************************************************************************
3301 * Display ICMPv4 traffic errors statistics in SVG.
3304 * @a Activity structure with statistics.
3305 * @curr Index in array for current sample statistics.
3306 * @action Action expected from current function.
3307 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3308 * flag indicating that a restart record has been previously
3309 * found (.@restart) and time used for the X axis origin
3311 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3312 * @record_hdr Pointer on record header of current stats sample.
3313 ***************************************************************************
3315 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3316 unsigned long long itv, struct record_header *record_hdr)
3318 struct stats_net_eicmp
3319 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3320 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3321 int group[] = {2, 2, 2, 2, 2, 2};
3322 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3323 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3324 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3325 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3326 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3327 char *g_title[] = {"ierr/s", "oerr/s",
3328 "idstunr/s", "odstunr/s",
3329 "itmex/s", "otmex/s",
3330 "iparmpb/s", "oparmpb/s",
3331 "isrcq/s", "osrcq/s",
3332 "iredir/s", "oredir/s"};
3333 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3334 static double *spmin, *spmax;
3336 static int *outsize;
3338 if (action & F_BEGIN) {
3340 * Allocate arrays that will contain the graphs data
3341 * and the min/max values.
3343 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3346 if (action & F_MAIN) {
3347 /* Check for min/max values */
3348 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3349 itv, spmin, spmax, g_fields);
3352 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3353 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3354 out, outsize, svg_p->restart);
3356 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3357 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3358 out + 1, outsize + 1, svg_p->restart);
3360 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3361 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3362 out + 2, outsize + 2, svg_p->restart);
3364 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3365 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3366 out + 3, outsize + 3, svg_p->restart);
3368 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3369 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3370 out + 4, outsize + 4, svg_p->restart);
3372 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3373 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3374 out + 5, outsize + 5, svg_p->restart);
3376 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3377 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3378 out + 6, outsize + 6, svg_p->restart);
3380 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3381 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3382 out + 7, outsize + 7, svg_p->restart);
3384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3385 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3386 out + 8, outsize + 8, svg_p->restart);
3388 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3389 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3390 out + 9, outsize + 9, svg_p->restart);
3392 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3393 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3394 out + 10, outsize + 10, svg_p->restart);
3396 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3397 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3398 out + 11, outsize + 11, svg_p->restart);
3401 if (action & F_END) {
3402 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3403 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3405 /* Free remaining structures */
3406 free_graphs(out, outsize, spmin, spmax);
3411 ***************************************************************************
3412 * Display TCPv4 traffic statistics in SVG.
3415 * @a Activity structure with statistics.
3416 * @curr Index in array for current sample statistics.
3417 * @action Action expected from current function.
3418 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3419 * flag indicating that a restart record has been previously
3420 * found (.@restart) and time used for the X axis origin
3422 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3423 * @record_hdr Pointer on record header of current stats sample.
3424 ***************************************************************************
3426 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3427 unsigned long long itv, struct record_header *record_hdr)
3429 struct stats_net_tcp
3430 *sntc = (struct stats_net_tcp *) a->buf[curr],
3431 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3432 int group[] = {2, 2};
3433 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3434 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3435 char *g_title[] = {"active/s", "passive/s",
3436 "iseg/s", "oseg/s"};
3437 int g_fields[] = {0, 1, 2, 3};
3438 static double *spmin, *spmax;
3440 static int *outsize;
3442 if (action & F_BEGIN) {
3444 * Allocate arrays that will contain the graphs data
3445 * and the min/max values.
3447 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3450 if (action & F_MAIN) {
3451 /* Check for min/max values */
3452 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3453 itv, spmin, spmax, g_fields);
3456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3457 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3458 out, outsize, svg_p->restart);
3460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3461 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3462 out + 1, outsize + 1, svg_p->restart);
3464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3465 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3466 out + 2, outsize + 2, svg_p->restart);
3468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3469 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3470 out + 3, outsize + 3, svg_p->restart);
3473 if (action & F_END) {
3474 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3475 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3477 /* Free remaining structures */
3478 free_graphs(out, outsize, spmin, spmax);
3483 ***************************************************************************
3484 * Display TCPv4 traffic errors statistics in SVG.
3487 * @a Activity structure with statistics.
3488 * @curr Index in array for current sample statistics.
3489 * @action Action expected from current function.
3490 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3491 * flag indicating that a restart record has been previously
3492 * found (.@restart) and time used for the X axis origin
3494 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3495 * @record_hdr Pointer on record header of current stats sample.
3496 ***************************************************************************
3498 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3499 unsigned long long itv, struct record_header *record_hdr)
3501 struct stats_net_etcp
3502 *snetc = (struct stats_net_etcp *) a->buf[curr],
3503 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3504 int group[] = {2, 3};
3505 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3506 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3507 char *g_title[] = {"atmptf/s", "estres/s",
3508 "retrans/s", "isegerr/s", "orsts/s"};
3509 int g_fields[] = {0, 1, 2, 3, 4};
3510 static double *spmin, *spmax;
3512 static int *outsize;
3514 if (action & F_BEGIN) {
3516 * Allocate arrays that will contain the graphs data
3517 * and the min/max values.
3519 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3522 if (action & F_MAIN) {
3523 /* Check for min/max values */
3524 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3525 itv, spmin, spmax, g_fields);
3528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3529 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3530 out, outsize, svg_p->restart);
3532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3533 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3534 out + 1, outsize + 1, svg_p->restart);
3536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3537 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3538 out + 2, outsize + 2, svg_p->restart);
3540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3541 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3542 out + 3, outsize + 3, svg_p->restart);
3544 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3545 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3546 out + 4, outsize + 4, svg_p->restart);
3549 if (action & F_END) {
3550 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3551 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3553 /* Free remaining structures */
3554 free_graphs(out, outsize, spmin, spmax);
3559 ***************************************************************************
3560 * Display UDPv4 traffic statistics in SVG.
3563 * @a Activity structure with statistics.
3564 * @curr Index in array for current sample statistics.
3565 * @action Action expected from current function.
3566 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3567 * flag indicating that a restart record has been previously
3568 * found (.@restart) and time used for the X axis origin
3570 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3571 * @record_hdr Pointer on record header of current stats sample.
3572 ***************************************************************************
3574 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3575 unsigned long long itv, struct record_header *record_hdr)
3577 struct stats_net_udp
3578 *snuc = (struct stats_net_udp *) a->buf[curr],
3579 *snup = (struct stats_net_udp *) a->buf[!curr];
3580 int group[] = {2, 2};
3581 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3582 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3583 char *g_title[] = {"idgm/s", "odgm/s",
3584 "noport/s", "idgmerr/s"};
3585 int g_fields[] = {0, 1, 2, 3};
3586 static double *spmin, *spmax;
3588 static int *outsize;
3590 if (action & F_BEGIN) {
3592 * Allocate arrays that will contain the graphs data
3593 * and the min/max values.
3595 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3598 if (action & F_MAIN) {
3599 /* Check for min/max values */
3600 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3601 itv, spmin, spmax, g_fields);
3604 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3605 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3606 out, outsize, svg_p->restart);
3608 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3609 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3610 out + 1, outsize + 1, svg_p->restart);
3612 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3613 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3614 out + 2, outsize + 2, svg_p->restart);
3616 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3617 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3618 out + 3, outsize + 3, svg_p->restart);
3621 if (action & F_END) {
3622 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3623 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3625 /* Free remaining structures */
3626 free_graphs(out, outsize, spmin, spmax);
3631 ***************************************************************************
3632 * Display IPV6 socket statistics in SVG.
3635 * @a Activity structure with statistics.
3636 * @curr Index in array for current sample statistics.
3637 * @action Action expected from current function.
3638 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3639 * flag indicating that a restart record has been previously
3640 * found (.@restart) and time used for the X axis origin
3642 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3643 * @record_hdr Pointer on record header of current stats sample.
3644 ***************************************************************************
3646 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3647 unsigned long long itv, struct record_header *record_hdr)
3649 struct stats_net_sock6
3650 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3652 int g_type[] = {SVG_LINE_GRAPH};
3653 char *title[] = {"IPv6 sockets statistics"};
3654 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3655 int g_fields[] = {0, 1, 2, 3};
3656 static double *spmin, *spmax;
3658 static int *outsize;
3660 if (action & F_BEGIN) {
3662 * Allocate arrays that will contain the graphs data
3663 * and the min/max values.
3665 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3668 if (action & F_MAIN) {
3669 /* Check for min/max values */
3670 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3671 itv, spmin, spmax, g_fields);
3673 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3674 (unsigned long long) snsc->tcp6_inuse,
3675 out, outsize, svg_p->restart);
3677 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3678 (unsigned long long) snsc->udp6_inuse,
3679 out + 1, outsize + 1, svg_p->restart);
3681 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3682 (unsigned long long) snsc->raw6_inuse,
3683 out + 2, outsize + 2, svg_p->restart);
3685 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3686 (unsigned long long) snsc->frag6_inuse,
3687 out + 3, outsize + 3, svg_p->restart);
3690 if (action & F_END) {
3691 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3692 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3694 /* Free remaining structures */
3695 free_graphs(out, outsize, spmin, spmax);
3700 ***************************************************************************
3701 * Display IPv6 traffic statistics in SVG.
3704 * @a Activity structure with statistics.
3705 * @curr Index in array for current sample statistics.
3706 * @action Action expected from current function.
3707 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3708 * flag indicating that a restart record has been previously
3709 * found (.@restart) and time used for the X axis origin
3711 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3712 * @record_hdr Pointer on record header of current stats sample.
3713 ***************************************************************************
3715 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3716 unsigned long long itv, struct record_header *record_hdr)
3718 struct stats_net_ip6
3719 *snic = (struct stats_net_ip6 *) a->buf[curr],
3720 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3721 int group[] = {4, 2, 2, 2};
3722 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3724 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3725 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3726 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3727 "asmrq6/s", "asmok6/s",
3728 "imcpck6/s", "omcpck6/s",
3729 "fragok6/s", "fragcr6/s"};
3730 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3731 static double *spmin, *spmax;
3733 static int *outsize;
3735 if (action & F_BEGIN) {
3737 * Allocate arrays that will contain the graphs data
3738 * and the min/max values.
3740 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3743 if (action & F_MAIN) {
3744 /* Check for min/max values */
3745 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3746 itv, spmin, spmax, g_fields);
3749 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3750 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3751 out, outsize, svg_p->restart);
3753 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3754 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3755 out + 1, outsize + 1, svg_p->restart);
3757 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3758 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3759 out + 2, outsize + 2, svg_p->restart);
3761 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3762 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3763 out + 3, outsize + 3, svg_p->restart);
3765 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3766 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3767 out + 4, outsize + 4, svg_p->restart);
3769 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3770 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3771 out + 5, outsize + 5, svg_p->restart);
3773 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3774 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3775 out + 6, outsize + 6, svg_p->restart);
3777 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3778 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3779 out + 7, outsize + 7, svg_p->restart);
3781 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3782 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3783 out + 8, outsize + 8, svg_p->restart);
3785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3786 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3787 out + 9, outsize + 9, svg_p->restart);
3790 if (action & F_END) {
3791 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3792 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3794 /* Free remaining structures */
3795 free_graphs(out, outsize, spmin, spmax);
3800 ***************************************************************************
3801 * Display IPv6 traffic errors statistics in SVG.
3804 * @a Activity structure with statistics.
3805 * @curr Index in array for current sample statistics.
3806 * @action Action expected from current function.
3807 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3808 * flag indicating that a restart record has been previously
3809 * found (.@restart) and time used for the X axis origin
3811 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3812 * @record_hdr Pointer on record header of current stats sample.
3813 ***************************************************************************
3815 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3816 unsigned long long itv, struct record_header *record_hdr)
3818 struct stats_net_eip6
3819 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3820 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3821 int group[] = {4, 2, 2, 3};
3822 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3824 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3825 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3826 "IPv6 traffic errors statistics (5)"};
3827 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3828 "idisc6/s", "odisc6/s",
3829 "inort6/s", "onort6/s",
3830 "asmf6/s", "fragf6/s", "itrpck6/s"};
3831 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3832 static double *spmin, *spmax;
3834 static int *outsize;
3836 if (action & F_BEGIN) {
3838 * Allocate arrays that will contain the graphs data
3839 * and the min/max values.
3841 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3844 if (action & F_MAIN) {
3845 /* Check for min/max values */
3846 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3847 itv, spmin, spmax, g_fields);
3850 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3851 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3852 out, outsize, svg_p->restart);
3854 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3855 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3856 out + 1, outsize + 1, svg_p->restart);
3858 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3859 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3860 out + 2, outsize + 2, svg_p->restart);
3862 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3863 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3864 out + 3, outsize + 3, svg_p->restart);
3866 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3867 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3868 out + 4, outsize + 4, svg_p->restart);
3870 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3871 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3872 out + 5, outsize + 5, svg_p->restart);
3874 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3875 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3876 out + 6, outsize + 6, svg_p->restart);
3878 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3879 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3880 out + 7, outsize + 7, svg_p->restart);
3882 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3883 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3884 out + 8, outsize + 8, svg_p->restart);
3886 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3887 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3888 out + 9, outsize + 9, svg_p->restart);
3890 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3891 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3892 out + 10, outsize + 10, svg_p->restart);
3895 if (action & F_END) {
3896 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3897 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3899 /* Free remaining structures */
3900 free_graphs(out, outsize, spmin, spmax);
3905 ***************************************************************************
3906 * Display ICMPv6 traffic statistics in SVG.
3909 * @a Activity structure with statistics.
3910 * @curr Index in array for current sample statistics.
3911 * @action Action expected from current function.
3912 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3913 * flag indicating that a restart record has been previously
3914 * found (.@restart) and time used for the X axis origin
3916 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3917 * @record_hdr Pointer on record header of current stats sample.
3918 ***************************************************************************
3920 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3921 unsigned long long itv, struct record_header *record_hdr)
3923 struct stats_net_icmp6
3924 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3925 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3926 int group[] = {2, 3, 5, 3, 4};
3927 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3928 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3929 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3930 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3931 "ICMPv6 traffic statistics (5)"};
3932 char *g_title[] = {"imsg6/s", "omsg6/s",
3933 "iech6/s", "iechr6/s", "oechr6/s",
3934 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3935 "irtsol6/s", "ortsol6/s", "irtad6/s",
3936 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3937 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3938 static double *spmin, *spmax;
3940 static int *outsize;
3942 if (action & F_BEGIN) {
3944 * Allocate arrays that will contain the graphs data
3945 * and the min/max values.
3947 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3950 if (action & F_MAIN) {
3951 /* Check for min/max values */
3952 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3953 itv, spmin, spmax, g_fields);
3956 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3957 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3958 out, outsize, svg_p->restart);
3960 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3961 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3962 out + 1, outsize + 1, svg_p->restart);
3964 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3965 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3966 out + 2, outsize + 2, svg_p->restart);
3968 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3969 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3970 out + 3, outsize + 3, svg_p->restart);
3972 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3973 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3974 out + 4, outsize + 4, svg_p->restart);
3976 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3977 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3978 out + 5, outsize + 5, svg_p->restart);
3980 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3981 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3982 out + 6, outsize + 6, svg_p->restart);
3984 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3985 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3986 out + 7, outsize + 7, svg_p->restart);
3988 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3989 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3990 out + 8, outsize + 8, svg_p->restart);
3992 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3993 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3994 out + 9, outsize + 9, svg_p->restart);
3996 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3997 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3998 out + 10, outsize + 10, svg_p->restart);
4000 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4001 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
4002 out + 11, outsize + 11, svg_p->restart);
4004 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4005 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
4006 out + 12, outsize + 12, svg_p->restart);
4008 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4009 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
4010 out + 13, outsize + 13, svg_p->restart);
4012 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4013 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
4014 out + 14, outsize + 14, svg_p->restart);
4016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4017 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
4018 out + 15, outsize + 15, svg_p->restart);
4020 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4021 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
4022 out + 16, outsize + 16, svg_p->restart);
4025 if (action & F_END) {
4026 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4027 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4029 /* Free remaining structures */
4030 free_graphs(out, outsize, spmin, spmax);
4035 ***************************************************************************
4036 * Display ICMPv6 traffic errors statistics in SVG.
4039 * @a Activity structure with statistics.
4040 * @curr Index in array for current sample statistics.
4041 * @action Action expected from current function.
4042 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4043 * flag indicating that a restart record has been previously
4044 * found (.@restart) and time used for the X axis origin
4046 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4047 * @record_hdr Pointer on record header of current stats sample.
4048 ***************************************************************************
4050 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4051 unsigned long long itv, struct record_header *record_hdr)
4053 struct stats_net_eicmp6
4054 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
4055 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
4056 int group[] = {1, 2, 2, 2, 2, 2};
4057 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4058 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4059 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
4060 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
4061 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
4062 char *g_title[] = {"ierr6/s",
4063 "idtunr6/s", "odtunr6/s",
4064 "itmex6/s", "otmex6/s",
4065 "iprmpb6/s", "oprmpb6/s",
4066 "iredir6/s", "oredir6/s",
4067 "ipck2b6/s", "opck2b6/s"};
4068 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4069 static double *spmin, *spmax;
4071 static int *outsize;
4073 if (action & F_BEGIN) {
4075 * Allocate arrays that will contain the graphs data
4076 * and the min/max values.
4078 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4081 if (action & F_MAIN) {
4082 /* Check for min/max values */
4083 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4084 itv, spmin, spmax, g_fields);
4087 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4088 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4089 out, outsize, svg_p->restart);
4091 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4092 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4093 out + 1, outsize + 1, svg_p->restart);
4095 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4096 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4097 out + 2, outsize + 2, svg_p->restart);
4099 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4100 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4101 out + 3, outsize + 3, svg_p->restart);
4103 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4104 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4105 out + 4, outsize + 4, svg_p->restart);
4107 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4108 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4109 out + 5, outsize + 5, svg_p->restart);
4111 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4112 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4113 out + 6, outsize + 6, svg_p->restart);
4115 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4116 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4117 out + 7, outsize + 7, svg_p->restart);
4119 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4120 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4121 out + 8, outsize + 8, svg_p->restart);
4123 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4124 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4125 out + 9, outsize + 9, svg_p->restart);
4127 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4128 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4129 out + 10, outsize + 10, svg_p->restart);
4132 if (action & F_END) {
4133 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4134 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4136 /* Free remaining structures */
4137 free_graphs(out, outsize, spmin, spmax);
4142 ***************************************************************************
4143 * Display UDPv6 traffic statistics in SVG.
4146 * @a Activity structure with statistics.
4147 * @curr Index in array for current sample statistics.
4148 * @action Action expected from current function.
4149 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4150 * flag indicating that a restart record has been previously
4151 * found (.@restart) and time used for the X axis origin
4153 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4154 * @record_hdr Pointer on record header of current stats sample.
4155 ***************************************************************************
4157 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4158 unsigned long long itv, struct record_header *record_hdr)
4160 struct stats_net_udp6
4161 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4162 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4163 int group[] = {2, 2};
4164 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4165 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4166 char *g_title[] = {"idgm6/s", "odgm6/s",
4167 "noport6/s", "idgmer6/s"};
4168 int g_fields[] = {0, 1, 2, 3};
4169 static double *spmin, *spmax;
4171 static int *outsize;
4173 if (action & F_BEGIN) {
4175 * Allocate arrays that will contain the graphs data
4176 * and the min/max values.
4178 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4181 if (action & F_MAIN) {
4182 /* Check for min/max values */
4183 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4184 itv, spmin, spmax, g_fields);
4187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4188 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4189 out, outsize, svg_p->restart);
4191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4192 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4193 out + 1, outsize + 1, svg_p->restart);
4195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4196 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4197 out + 2, outsize + 2, svg_p->restart);
4199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4200 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4201 out + 3, outsize + 3, svg_p->restart);
4204 if (action & F_END) {
4205 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4206 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4208 /* Free remaining structures */
4209 free_graphs(out, outsize, spmin, spmax);
4214 ***************************************************************************
4215 * Display CPU frequency statistics in SVG.
4218 * @a Activity structure with statistics.
4219 * @curr Index in array for current sample statistics.
4220 * @action Action expected from current function.
4221 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4222 * flag indicating that a restart record has been previously
4223 * found (.@restart) and time used for the X axis origin
4225 * @itv Interval of time in 1/100th of a second (unused here).
4226 * @record_hdr Pointer on record header of current stats sample.
4227 ***************************************************************************
4229 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4230 unsigned long long itv, struct record_header *record_hdr)
4232 struct stats_pwr_cpufreq *spc, *spp;
4234 int g_type[] = {SVG_LINE_GRAPH};
4235 char *title[] = {"CPU clock frequency"};
4236 char *g_title[] = {"MHz"};
4237 static double *spmin, *spmax;
4239 static int *outsize;
4243 if (action & F_BEGIN) {
4245 * Allocate arrays that will contain the graphs data
4246 * and the min/max values.
4248 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4251 if (action & F_MAIN) {
4253 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4255 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4256 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4258 /* Should current CPU (including CPU "all") be displayed? */
4259 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4264 * Note: Don't skip offline CPU here as it is needed
4265 * to make the graph go though 0.
4269 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4270 ((double) spp->cpufreq) / 100,
4271 ((double) spc->cpufreq) / 100,
4272 out + i, outsize + i, svg_p->restart, svg_p->dt,
4273 spmin + i, spmax + i);
4277 if (action & F_END) {
4280 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
4282 /* Should current CPU (including CPU "all") be displayed? */
4283 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4288 /* This is CPU "all" */
4289 strcpy(item_name, "all");
4293 * If the maximum frequency reached by the CPU is 0, then
4294 * the CPU has been offline on the whole period.
4295 * => Don't display it.
4297 if (*(spmax + i) == 0)
4300 sprintf(item_name, "%d", i - 1);
4303 if (draw_activity_graphs(a->g_nr, g_type,
4304 title, g_title, item_name, group,
4305 spmin + i, spmax + i, out + i, outsize + i,
4306 svg_p, record_hdr, i, a->id, xid)) {
4311 /* Free remaining structures */
4312 free_graphs(out, outsize, spmin, spmax);
4317 ***************************************************************************
4318 * Display fan statistics in SVG.
4321 * @a Activity structure with statistics.
4322 * @curr Index in array for current sample statistics.
4323 * @action Action expected from current function.
4324 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4325 * flag indicating that a restart record has been previously
4326 * found (.@restart) and time used for the X axis origin
4328 * @itv Interval of time in 1/100th of a second (unused here).
4329 * @record_hdr Pointer on record header of current stats sample.
4330 ***************************************************************************
4332 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4333 unsigned long long itv, struct record_header *record_hdr)
4335 struct stats_pwr_fan *spc, *spp;
4337 int g_type[] = {SVG_LINE_GRAPH};
4338 char *title[] = {"Fans speed"};
4339 char *g_title[] = {"~rpm"};
4340 static double *spmin, *spmax;
4342 static int *outsize;
4343 char item_name[MAX_SENSORS_DEV_LEN + 16];
4346 if (action & F_BEGIN) {
4348 * Allocate arrays that will contain the graphs data
4349 * and the min/max values.
4351 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4354 if (action & F_MAIN) {
4356 for (i = 0; i < a->nr[curr]; i++) {
4358 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4359 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4362 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4365 out + i, outsize + i, svg_p->restart, svg_p->dt,
4366 spmin + i, spmax + i);
4370 if (action & F_END) {
4373 for (i = 0; i < a->item_list_sz; i++) {
4375 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4377 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4378 item_name[sizeof(item_name) - 1] = '\0';
4380 if (draw_activity_graphs(a->g_nr, g_type,
4381 title, g_title, item_name, group,
4382 spmin + i, spmax + i, out + i, outsize + i,
4383 svg_p, record_hdr, FALSE, a->id, xid)) {
4388 /* Free remaining structures */
4389 free_graphs(out, outsize, spmin, spmax);
4394 ***************************************************************************
4395 * Display temperature statistics in SVG.
4398 * @a Activity structure with statistics.
4399 * @curr Index in array for current sample statistics.
4400 * @action Action expected from current function.
4401 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4402 * flag indicating that a restart record has been previously
4403 * found (.@restart) and time used for the X axis origin
4405 * @itv Interval of time in 1/100th of a second (unused here).
4406 * @record_hdr Pointer on record header of current stats sample.
4407 ***************************************************************************
4409 #define TEMP_ARRAY_SZ 2
4410 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4411 unsigned long long itv, struct record_header *record_hdr)
4413 struct stats_pwr_temp *spc;
4414 int group[] = {1, 1};
4415 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4416 char *title[] = {"Devices temperature (1)",
4417 "Devices temperature (2)"};
4418 char *g_title[] = {"~degC",
4420 static double *spmin, *spmax;
4422 static int *outsize;
4423 char item_name[MAX_SENSORS_DEV_LEN + 16];
4427 if (action & F_BEGIN) {
4429 * Allocate arrays that will contain the graphs data
4430 * and the min/max values.
4432 out = allocate_graph_lines(TEMP_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4435 if (action & F_MAIN) {
4436 /* For each temperature sensor */
4437 for (i = 0; i < a->nr[curr]; i++) {
4439 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4441 /* Look for min/max values */
4442 if (spc->temp < *(spmin + TEMP_ARRAY_SZ * i)) {
4443 *(spmin + TEMP_ARRAY_SZ * i) = spc->temp;
4445 if (spc->temp > *(spmax + TEMP_ARRAY_SZ * i)) {
4446 *(spmax + TEMP_ARRAY_SZ * i) = spc->temp;
4448 tval = (spc->temp_max - spc->temp_min) ?
4449 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4451 if (tval < *(spmin + TEMP_ARRAY_SZ * i + 1)) {
4452 *(spmin + TEMP_ARRAY_SZ * i + 1) = tval;
4454 if (tval > *(spmax + TEMP_ARRAY_SZ * i + 1)) {
4455 *(spmax + TEMP_ARRAY_SZ * i + 1) = tval;
4459 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4461 out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i, svg_p->restart);
4463 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4465 out + TEMP_ARRAY_SZ * i + 1, outsize + TEMP_ARRAY_SZ * i + 1, svg_p->dt);
4469 if (action & F_END) {
4472 for (i = 0; i < a->item_list_sz; i++) {
4474 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4476 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4477 item_name[sizeof(item_name) - 1] = '\0';
4479 if (draw_activity_graphs(a->g_nr, g_type,
4480 title, g_title, item_name, group,
4481 spmin + TEMP_ARRAY_SZ * i, spmax + TEMP_ARRAY_SZ * i,
4482 out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i,
4483 svg_p, record_hdr, FALSE, a->id, xid)) {
4488 /* Free remaining structures */
4489 free_graphs(out, outsize, spmin, spmax);
4494 ***************************************************************************
4495 * Display voltage inputs statistics in SVG.
4498 * @a Activity structure with statistics.
4499 * @curr Index in array for current sample statistics.
4500 * @action Action expected from current function.
4501 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4502 * flag indicating that a restart record has been previously
4503 * found (.@restart) and time used for the X axis origin
4505 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4506 * @record_hdr Pointer on record header of current stats sample.
4507 ***************************************************************************
4509 #define IN_ARRAY_SZ 2
4510 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4511 unsigned long long itv, struct record_header *record_hdr)
4513 struct stats_pwr_in *spc;
4514 int group[] = {1, 1};
4515 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4516 char *title[] = {"Voltage inputs statistics (1)",
4517 "Voltage inputs statistics (2)"};
4518 char *g_title[] = {"inV",
4520 static double *spmin, *spmax;
4522 static int *outsize;
4523 char item_name[MAX_SENSORS_DEV_LEN + 16];
4527 if (action & F_BEGIN) {
4529 * Allocate arrays that will contain the graphs data
4530 * and the min/max values.
4532 out = allocate_graph_lines(IN_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4535 if (action & F_MAIN) {
4536 /* For each voltage input sensor */
4537 for (i = 0; i < a->nr[curr]; i++) {
4539 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4541 /* Look for min/max values */
4542 if (spc->in < *(spmin + IN_ARRAY_SZ * i)) {
4543 *(spmin + IN_ARRAY_SZ * i) = spc->in;
4545 if (spc->in > *(spmax + IN_ARRAY_SZ * i)) {
4546 *(spmax + IN_ARRAY_SZ * i) = spc->in;
4548 tval = (spc->in_max - spc->in_min) ?
4549 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4551 if (tval < *(spmin + IN_ARRAY_SZ * i + 1)) {
4552 *(spmin + IN_ARRAY_SZ * i + 1) = tval;
4554 if (tval > *(spmax + IN_ARRAY_SZ * i + 1)) {
4555 *(spmax + IN_ARRAY_SZ * i + 1) = tval;
4559 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4561 out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i, svg_p->restart);
4563 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4565 out + IN_ARRAY_SZ * i + 1, outsize + IN_ARRAY_SZ * i + 1, svg_p->dt);
4569 if (action & F_END) {
4572 for (i = 0; i < a->item_list_sz; i++) {
4574 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4576 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4577 item_name[sizeof(item_name) - 1] = '\0';
4579 if (draw_activity_graphs(a->g_nr, g_type,
4580 title, g_title, item_name, group,
4581 spmin + IN_ARRAY_SZ * i, spmax + IN_ARRAY_SZ * i,
4582 out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i,
4583 svg_p, record_hdr, FALSE, a->id, xid)) {
4588 /* Free remaining structures */
4589 free_graphs(out, outsize, spmin, spmax);
4594 ***************************************************************************
4595 * Display huge pages statistics in SVG.
4598 * @a Activity structure with statistics.
4599 * @curr Index in array for current sample statistics.
4600 * @action Action expected from current function.
4601 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4602 * flag indicating that a restart record has been previously
4603 * found (.@restart) and time used for the X axis origin
4605 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4606 * @record_hdr Pointer on record header of current stats sample.
4607 ***************************************************************************
4609 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4610 unsigned long long itv, struct record_header *record_hdr)
4613 *smc = (struct stats_huge *) a->buf[curr];
4614 int group[] = {4, 1};
4615 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4616 char *title[] = {"Huge pages utilization (1)",
4617 "Huge pages utilization (2)"};
4618 char *g_title[] = {"~kbhugfree", "~kbhugused", "~kbhugrsvd", "~kbhugsurp",
4620 int g_fields[] = {0, 5, 2, 3};
4621 static double *spmin, *spmax;
4623 static int *outsize;
4626 if (action & F_BEGIN) {
4628 * Allocate arrays that will contain the graphs data
4629 * and the min/max values.
4630 * Allocate one additional array (#5) to save min/max
4631 * values for tlhkb (unused).
4633 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
4636 if (action & F_MAIN) {
4637 /* Check for min/max values */
4638 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
4639 itv, spmin, spmax, g_fields);
4641 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4642 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4644 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4645 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4647 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4648 if (tval < *(spmin + 4)) {
4649 *(spmin + 4) = tval;
4651 if (tval > *(spmax + 4)) {
4652 *(spmax + 4) = tval;
4656 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4657 (unsigned long long) smc->frhkb,
4658 out, outsize, svg_p->restart);
4660 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4661 (unsigned long long) smc->tlhkb - smc->frhkb,
4662 out + 1, outsize + 1, svg_p->restart);
4664 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4665 (unsigned long long) smc->rsvdhkb,
4666 out + 2, outsize + 2, svg_p->restart);
4668 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4669 (unsigned long long) smc->surphkb,
4670 out + 3, outsize + 3, svg_p->restart);
4672 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4674 out + 4, outsize + 4, svg_p->dt);
4677 if (action & F_END) {
4678 draw_activity_graphs(a->g_nr, g_type,
4679 title, g_title, NULL, group,
4680 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4682 /* Free remaining structures */
4683 free_graphs(out, outsize, spmin, spmax);
4688 ***************************************************************************
4689 * Display filesystem statistics in SVG.
4692 * @a Activity structure with statistics.
4693 * @curr Index in array for current sample statistics.
4694 * @action Action expected from current function.
4695 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4696 * flag indicating that a restart record has been previously
4697 * found (.@restart) and time used for the X axis origin
4699 * @itv Interval of time in 1/100th of a second (unused here).
4700 * @record_hdr Pointer on record header of current stats sample.
4701 ***************************************************************************
4703 #define FS_ARRAY_SZ 8
4704 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4705 unsigned long long itv, struct record_header *record_hdr)
4707 struct stats_filesystem *sfc, *sfp;
4708 int group[] = {2, 2, 2, 1};
4709 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4710 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4711 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4712 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4713 char *g_title[] = {"~MBfsfree", "~MBfsused",
4714 "%ufsused", "%fsused",
4715 "Ifree/1000", "Iused/1000",
4717 static double *spmin, *spmax;
4719 static int *outsize;
4720 char *dev_name, *item_name;
4722 int i, k, pos, restart;
4724 if (action & F_BEGIN) {
4726 * Allocate arrays (#0..6) that will contain the graphs data
4727 * and the min/max values.
4728 * Also allocate an additional arrays (#7) for each filesystem:
4729 * out + 7 will contain the persistent or standard fs name, or mount point.
4731 out = allocate_graph_lines(FS_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4734 if (action & F_MAIN) {
4735 /* For each filesystem structure */
4736 for (i = 0; i < a->nr[curr]; i++) {
4737 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4739 /* Get name to display (persistent or standard fs name, or mount point) */
4740 dev_name = get_fs_name_to_display(a, flags, sfc);
4742 if (a->item_list != NULL) {
4743 /* A list of devices has been entered on the command line */
4744 if (!search_list_item(a->item_list, dev_name))
4745 /* Device not found */
4749 /* Look for corresponding graph */
4750 for (k = 0; k < a->item_list_sz; k++) {
4751 item_name = *(out + k * FS_ARRAY_SZ + 7);
4752 if (!strcmp(dev_name, item_name))
4757 if (k == a->item_list_sz) {
4758 /* Graph not found: Look for first free entry */
4759 for (k = 0; k < a->item_list_sz; k++) {
4760 item_name = *(out + k * FS_ARRAY_SZ + 7);
4761 if (!strcmp(item_name, ""))
4764 if (k == a->item_list_sz) {
4765 /* No free graph entry: Ignore it (should never happen) */
4767 fprintf(stderr, "%s: Name=%s\n",
4768 __FUNCTION__, sfc->fs_name);
4774 pos = k * FS_ARRAY_SZ;
4776 item_name = *(out + pos + 7);
4777 if (!item_name[0]) {
4778 /* Save filesystem name and mount point (if not already done) */
4779 strncpy(item_name, dev_name, CHUNKSIZE);
4780 item_name[CHUNKSIZE - 1] = '\0';
4784 for (k = 0; k < a->nr[!curr]; k++) {
4785 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4786 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4787 /* Filesystem found in previous sample */
4788 restart = svg_p->restart;
4792 /* Check for min/max values */
4794 /* Compute fsfree min/max values */
4795 tval = (double) sfc->f_bfree;
4796 if (tval > *(spmax + pos)) {
4797 *(spmax + pos) = tval;
4799 if (tval < *(spmin + pos)) {
4800 *(spmin + pos) = tval;
4802 /* Compute fsused min/max values */
4803 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4804 if (tval > *(spmax + pos + 1)) {
4805 *(spmax + pos + 1) = tval;
4807 if (tval < *(spmin + pos + 1)) {
4808 *(spmin + pos + 1) = tval;
4810 /* Compute %ufsused min/max values */
4811 tval = sfc->f_blocks ?
4812 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4813 if (tval > *(spmax + pos + 2)) {
4814 *(spmax + pos + 2) = tval;
4816 if (tval < *(spmin + pos + 2)) {
4817 *(spmin + pos + 2) = tval;
4819 /* Compute %fsused min/max values */
4820 tval = sfc->f_blocks ?
4821 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4822 if (tval > *(spmax + pos + 3)) {
4823 *(spmax + pos + 3) = tval;
4825 if (tval < *(spmin + pos + 3)) {
4826 *(spmin + pos + 3) = tval;
4828 /* Compute Ifree min/max values */
4829 tval = (double) sfc->f_ffree;
4830 if (tval > *(spmax + pos + 4)) {
4831 *(spmax + pos + 4) = tval;
4833 if (tval < *(spmin + pos + 4)) {
4834 *(spmin + pos + 4) = tval;
4836 /* Compute Iused min/max values */
4837 tval = (double) (sfc->f_files - sfc->f_ffree);
4838 if (tval > *(spmax + pos + 5)) {
4839 *(spmax + pos + 5) = tval;
4841 if (tval < *(spmin + pos + 5)) {
4842 *(spmin + pos + 5) = tval;
4844 /* Compute %Iused min/max values */
4845 tval = sfc->f_files ?
4846 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4847 if (tval > *(spmax + pos + 6)) {
4848 *(spmax + pos + 6) = tval;
4850 if (tval < *(spmin + pos + 6)) {
4851 *(spmin + pos + 6) = tval;
4855 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4856 (double) sfc->f_bfree / 1024 / 1024,
4857 out + pos, outsize + pos, restart);
4859 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4860 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4861 out + pos + 1, outsize + pos + 1, restart);
4863 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4866 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4867 out + pos + 2, outsize + pos + 2, svg_p->dt);
4869 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4872 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4873 out + pos + 3, outsize + pos + 3, svg_p->dt);
4875 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4876 ((double) sfc->f_ffree) / 1000,
4877 out + pos + 4, outsize + pos + 4, restart);
4879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4880 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4881 out + pos + 5, outsize + pos + 5, restart);
4883 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4886 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4887 out + pos + 6, outsize + pos + 6, svg_p->dt);
4891 if (action & F_END) {
4894 for (i = 0; i < a->item_list_sz; i++) {
4896 /* Check if there is something to display */
4897 pos = i * FS_ARRAY_SZ;
4901 /* Conversion B -> MiB and inodes/1000 */
4902 for (k = 0; k < 2; k++) {
4903 *(spmin + pos + k) /= (1024 * 1024);
4904 *(spmax + pos + k) /= (1024 * 1024);
4905 *(spmin + pos + 4 + k) /= 1000;
4906 *(spmax + pos + 4 + k) /= 1000;
4909 item_name = *(out + pos + 7);
4911 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4912 spmin + pos, spmax + pos, out + pos, outsize + pos,
4913 svg_p, record_hdr, FALSE, a->id, xid)) {
4918 /* Free remaining structures */
4919 free_graphs(out, outsize, spmin, spmax);
4924 ***************************************************************************
4925 * Display Fibre Channel HBA statistics in SVG.
4928 * @a Activity structure with statistics.
4929 * @curr Index in array for current sample statistics.
4930 * @action Action expected from current function.
4931 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4932 * flag indicating that a restart record has been previously
4933 * found (.@restart) and time used for the X axis origin
4935 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4936 * @record_hdr Pointer on record header of current stats sample.
4937 ***************************************************************************
4939 #define FC_ARRAY_SZ 5
4940 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4941 unsigned long long itv, struct record_header *record_hdr)
4943 struct stats_fchost *sfcc, *sfcp, sfczero;
4944 int group[] = {2, 2};
4945 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4946 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4947 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4948 "fch_rxw/s", "fch_txw/s"};
4949 int g_fields[] = {0, 1, 2, 3};
4950 static double *spmin, *spmax;
4952 static int *outsize;
4954 int i, j, j0, k, found, pos, restart, *unregistered;
4956 if (action & F_BEGIN) {
4958 * Allocate arrays (#0..3) that will contain the graphs data
4959 * and the min/max values.
4960 * Also allocate one additional array (#4) that will contain
4961 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4962 * has either still not been registered, or has been unregistered
4965 out = allocate_graph_lines(FC_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4968 if (action & F_MAIN) {
4969 memset(&sfczero, 0, sizeof(struct stats_fchost));
4970 restart = svg_p->restart;
4972 * Mark previously registered interfaces as now
4973 * possibly unregistered for all graphs.
4975 for (k = 0; k < a->item_list_sz; k++) {
4976 unregistered = outsize + k * FC_ARRAY_SZ + 4;
4977 if (*unregistered == FALSE) {
4978 *unregistered = MAYBE;
4982 /* For each FC HBA */
4983 for (i = 0; i < a->nr[curr]; i++) {
4986 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4988 /* Look for corresponding graph */
4989 for (k = 0; k < a->item_list_sz; k++) {
4990 item_name = *(out + k * FC_ARRAY_SZ + 4);
4991 if (!strcmp(sfcc->fchost_name, item_name))
4995 if (k == a->item_list_sz) {
4996 /* Graph not found: Look for first free entry */
4997 for (k = 0; k < a->item_list_sz; k++) {
4998 item_name = *(out + k * FC_ARRAY_SZ + 4);
4999 if (!strcmp(item_name, ""))
5002 if (k == a->item_list_sz) {
5003 /* No free graph entry: Ignore it (should never happen) */
5005 fprintf(stderr, "%s: Name=%s\n",
5006 __FUNCTION__, sfcc->fchost_name);
5012 pos = k * FC_ARRAY_SZ;
5013 unregistered = outsize + pos + 4;
5015 if (a->nr[!curr] > 0) {
5016 /* Look for corresponding structure in previous iteration */
5019 if (j >= a->nr[!curr]) {
5020 j = a->nr[!curr] - 1;
5026 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
5027 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
5031 if (++j >= a->nr[!curr]) {
5039 /* This is a newly registered host */
5044 * If current interface was marked as previously unregistered,
5045 * then set restart variable to TRUE so that the graph will be
5046 * discontinuous, and mark it as now registered.
5048 if (*unregistered == TRUE) {
5051 *unregistered = FALSE;
5053 item_name = *(out + pos + 4);
5054 if (!item_name[0]) {
5055 /* Save FC HBA name */
5056 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
5057 item_name[CHUNKSIZE - 1] = '\0';
5060 /* Look for min/max values */
5061 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
5062 itv, spmin + pos, spmax + pos, g_fields);
5065 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5066 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5067 out + pos, outsize + pos, restart);
5069 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5070 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5071 out + pos + 1, outsize + pos + 1, restart);
5073 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5074 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5075 out + pos + 2, outsize + pos + 2, restart);
5077 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5078 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5079 out + pos + 3, outsize + pos + 3, restart);
5082 /* Mark interfaces not seen here as now unregistered */
5083 for (k = 0; k < a->item_list_sz; k++) {
5084 unregistered = outsize + k * FC_ARRAY_SZ + 4;
5085 if (*unregistered != FALSE) {
5086 *unregistered = TRUE;
5091 if (action & F_END) {
5092 for (i = 0; i < a->item_list_sz; i++) {
5094 /* Check if there is something to display */
5095 pos = i * FC_ARRAY_SZ;
5099 item_name = *(out + pos + 4);
5100 draw_activity_graphs(a->g_nr, g_type,
5101 title, g_title, item_name, group,
5102 spmin + pos, spmax + pos, out + pos, outsize + pos,
5103 svg_p, record_hdr, FALSE, a->id, i);
5106 /* Free remaining structures */
5107 free_graphs(out, outsize, spmin, spmax);
5112 ***************************************************************************
5113 * Display softnet statistics in SVG.
5116 * @a Activity structure with statistics.
5117 * @curr Index in array for current sample statistics.
5118 * @action Action expected from current function.
5119 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5120 * flag indicating that a restart record has been previously
5121 * found (.@restart) and time used for the X axis origin
5123 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5124 * @record_hdr Pointer on record header of current stats sample.
5125 ***************************************************************************
5127 #define SOFT_ARRAY_SZ 5
5128 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5129 unsigned long long itv, struct record_header *record_hdr)
5131 struct stats_softnet *ssnc, *ssnp, ssnczero;
5132 int group[] = {2, 3};
5133 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5134 char *title[] = {"Software-based network processing statistics (1)",
5135 "Software-based network processing statistics (2)"};
5136 char *g_title[] = {"total/s", "dropd/s",
5137 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5138 int g_fields[] = {0, 1, 2, 3, 4};
5139 static double *spmin, *spmax;
5141 static int *outsize;
5143 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5144 int i, pos, restart;
5146 if (action & F_BEGIN) {
5148 * Allocate arrays that will contain the graphs data
5149 * and the min/max values.
5151 out = allocate_graph_lines(SOFT_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
5154 if (action & F_MAIN) {
5155 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5157 /* @nr[curr] cannot normally be greater than @nr_ini */
5158 if (a->nr[curr] > a->nr_ini) {
5159 a->nr_ini = a->nr[curr];
5162 /* Compute statistics for CPU "all" */
5163 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5166 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5167 restart = svg_p->restart;
5169 /* Should current CPU (including CPU "all") be displayed? */
5170 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5174 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5175 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5177 /* Is current CPU marked offline? */
5178 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5180 * Yes and it doesn't follow a RESTART record.
5181 * To add a discontinuity in graph, we simulate
5185 if (svg_p->restart) {
5187 * CPU is offline and it follows a real
5188 * RESTART record. Ignore its current value
5189 * (no previous sample).
5194 pos = i * SOFT_ARRAY_SZ;
5196 /* Check for min/max values */
5197 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5198 itv, spmin + pos, spmax + pos, g_fields);
5201 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5202 S_VALUE(ssnp->processed, ssnc->processed, itv),
5203 out + pos, outsize + pos, restart);
5205 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5206 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5207 out + pos + 1, outsize + pos + 1, restart);
5209 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5210 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5211 out + pos + 2, outsize + pos + 2, restart);
5213 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5214 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5215 out + pos + 3, outsize + pos + 3, restart);
5217 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5218 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5219 out + pos + 4, outsize + pos + 4, restart);
5223 if (action & F_END) {
5224 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
5226 /* Should current CPU (including CPU "all") be displayed? */
5227 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5231 pos = i * SOFT_ARRAY_SZ;
5234 /* This is CPU "all" */
5235 strcpy(item_name, "all");
5238 sprintf(item_name, "%d", i - 1);
5241 draw_activity_graphs(a->g_nr, g_type,
5242 title, g_title, item_name, group,
5243 spmin + pos, spmax + pos, out + pos, outsize + pos,
5244 svg_p, record_hdr, FALSE, a->id, i);
5247 /* Free remaining structures */
5248 free_graphs(out, outsize, spmin, spmax);
5253 ***************************************************************************
5254 * Display pressure-stall CPU statistics in SVG.
5257 * @a Activity structure with statistics.
5258 * @curr Index in array for current sample statistics.
5259 * @action Action expected from current function.
5260 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5261 * flag indicating that a restart record has been previously
5262 * found (.@restart) and time used for the X axis origin
5264 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5265 * @record_hdr Pointer on record header of current stats sample.
5266 ***************************************************************************
5268 __print_funct_t svg_print_psicpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5269 unsigned long long itv, struct record_header *record_hdr)
5271 struct stats_psi_cpu
5272 *psic = (struct stats_psi_cpu *) a->buf[curr],
5273 *psip = (struct stats_psi_cpu *) a->buf[!curr];
5274 int group[] = {3, 1};
5275 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5276 char *title[] = {"CPU pressure trends (some tasks)", "CPU stall time (some tasks)"};
5277 char *g_title[] = {"%scpu-10", "%scpu-60", "%scpu-300",
5279 static double *spmin, *spmax;
5281 static int *outsize;
5284 if (action & F_BEGIN) {
5286 * Allocate arrays that will contain the graphs data
5287 * and the min/max values.
5289 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
5292 if (action & F_MAIN) {
5293 /* Check for min/max values */
5294 if (psic->some_acpu_10 > *spmax) {
5295 *spmax = psic->some_acpu_10;
5297 if (psic->some_acpu_10 < *spmin) {
5298 *spmin = psic->some_acpu_10;
5300 if (psic->some_acpu_60 > *(spmax + 1)) {
5301 *(spmax + 1) = psic->some_acpu_60;
5303 if (psic->some_acpu_60 < *(spmin + 1)) {
5304 *(spmin + 1) = psic->some_acpu_60;
5306 if (psic->some_acpu_300 > *(spmax + 2)) {
5307 *(spmax + 2) = psic->some_acpu_300;
5309 if (psic->some_acpu_300 < *(spmin + 2)) {
5310 *(spmin + 2) = psic->some_acpu_300;
5312 tval = ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv);
5313 if (tval > *(spmax + 3)) {
5314 *(spmax + 3) = tval;
5316 if (tval < *(spmin + 3)) {
5317 *(spmin + 3) = tval;
5321 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5322 (double) psic->some_acpu_10 / 100,
5323 out, outsize, svg_p->restart);
5325 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5326 (double) psic->some_acpu_60 / 100,
5327 out + 1, outsize + 1, svg_p->restart);
5329 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5330 (double) psic->some_acpu_300 / 100,
5331 out + 2, outsize + 2, svg_p->restart);
5333 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5335 ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv),
5336 out + 3, outsize + 3, svg_p->dt);
5339 if (action & F_END) {
5340 /* Fix min/max values for pressure ratios */
5341 *spmin /= 100; *spmax /= 100;
5342 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5343 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5345 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5346 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5348 /* Free remaining structures */
5349 free_graphs(out, outsize, spmin, spmax);
5354 ***************************************************************************
5355 * Display pressure-stall I/O statistics in SVG.
5358 * @a Activity structure with statistics.
5359 * @curr Index in array for current sample statistics.
5360 * @action Action expected from current function.
5361 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5362 * flag indicating that a restart record has been previously
5363 * found (.@restart) and time used for the X axis origin
5365 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5366 * @record_hdr Pointer on record header of current stats sample.
5367 ***************************************************************************
5369 __print_funct_t svg_print_psiio_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5370 unsigned long long itv, struct record_header *record_hdr)
5373 *psic = (struct stats_psi_io *) a->buf[curr],
5374 *psip = (struct stats_psi_io *) a->buf[!curr];
5375 int group[] = {3, 1, 3, 1};
5376 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5377 char *title[] = {"I/O pressure trends (some tasks)", "I/O stall time (some tasks)",
5378 "I/O pressure trends (full)", "I/O stall time (full)"};
5379 char *g_title[] = {"%sio-10", "%sio-60", "%sio-300",
5381 "%fio-10", "%fio-60", "%fio-300",
5383 static double *spmin, *spmax;
5385 static int *outsize;
5388 if (action & F_BEGIN) {
5390 * Allocate arrays that will contain the graphs data
5391 * and the min/max values.
5393 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5396 if (action & F_MAIN) {
5397 /* Check for min/max values */
5398 if (psic->some_aio_10 > *spmax) {
5399 *spmax = psic->some_aio_10;
5401 if (psic->some_aio_10 < *spmin) {
5402 *spmin = psic->some_aio_10;
5404 if (psic->some_aio_60 > *(spmax + 1)) {
5405 *(spmax + 1) = psic->some_aio_60;
5407 if (psic->some_aio_60 < *(spmin + 1)) {
5408 *(spmin + 1) = psic->some_aio_60;
5410 if (psic->some_aio_300 > *(spmax + 2)) {
5411 *(spmax + 2) = psic->some_aio_300;
5413 if (psic->some_aio_300 < *(spmin + 2)) {
5414 *(spmin + 2) = psic->some_aio_300;
5416 tval = ((double) psic->some_io_total - psip->some_io_total) / (100 * itv);
5417 if (tval > *(spmax + 3)) {
5418 *(spmax + 3) = tval;
5420 if (tval < *(spmin + 3)) {
5421 *(spmin + 3) = tval;
5424 if (psic->full_aio_10 > *(spmax + 4)) {
5425 *(spmax + 4) = psic->full_aio_10;
5427 if (psic->full_aio_10 < *(spmin + 4)) {
5428 *(spmin + 4) = psic->full_aio_10;
5430 if (psic->full_aio_60 > *(spmax + 5)) {
5431 *(spmax + 5) = psic->full_aio_60;
5433 if (psic->full_aio_60 < *(spmin + 5)) {
5434 *(spmin + 5) = psic->full_aio_60;
5436 if (psic->full_aio_300 > *(spmax + 6)) {
5437 *(spmax + 6) = psic->full_aio_300;
5439 if (psic->full_aio_300 < *(spmin + 6)) {
5440 *(spmin + 6) = psic->full_aio_300;
5442 tval = ((double) psic->full_io_total - psip->full_io_total) / (100 * itv);
5443 if (tval > *(spmax + 7)) {
5444 *(spmax + 7) = tval;
5446 if (tval < *(spmin + 7)) {
5447 *(spmin + 7) = tval;
5451 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5452 (double) psic->some_aio_10 / 100,
5453 out, outsize, svg_p->restart);
5455 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5456 (double) psic->some_aio_60 / 100,
5457 out + 1, outsize + 1, svg_p->restart);
5459 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5460 (double) psic->some_aio_300 / 100,
5461 out + 2, outsize + 2, svg_p->restart);
5463 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5465 ((double) psic->some_io_total - psip->some_io_total) / (100 * itv),
5466 out + 3, outsize + 3, svg_p->dt);
5469 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5470 (double) psic->full_aio_10 / 100,
5471 out + 4, outsize + 4, svg_p->restart);
5473 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5474 (double) psic->full_aio_60 / 100,
5475 out + 5, outsize + 5, svg_p->restart);
5477 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5478 (double) psic->full_aio_300 / 100,
5479 out + 6, outsize + 6, svg_p->restart);
5481 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5483 ((double) psic->full_io_total - psip->full_io_total) / (100 * itv),
5484 out + 7, outsize + 7, svg_p->dt);
5487 if (action & F_END) {
5488 /* Fix min/max values for pressure ratios */
5489 *spmin /= 100; *spmax /= 100;
5490 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5491 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5493 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5494 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5495 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5497 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5498 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5500 /* Free remaining structures */
5501 free_graphs(out, outsize, spmin, spmax);
5506 ***************************************************************************
5507 * Display pressure-stall memory statistics in SVG.
5510 * @a Activity structure with statistics.
5511 * @curr Index in array for current sample statistics.
5512 * @action Action expected from current function.
5513 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5514 * flag indicating that a restart record has been previously
5515 * found (.@restart) and time used for the X axis origin
5517 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5518 * @record_hdr Pointer on record header of current stats sample.
5519 ***************************************************************************
5521 __print_funct_t svg_print_psimem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5522 unsigned long long itv, struct record_header *record_hdr)
5524 struct stats_psi_mem
5525 *psic = (struct stats_psi_mem *) a->buf[curr],
5526 *psip = (struct stats_psi_mem *) a->buf[!curr];
5527 int group[] = {3, 1, 3, 1};
5528 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5529 char *title[] = {"Memory pressure trends (some tasks)", "Memory stall time (some tasks)",
5530 "Memory pressure trends (full)", "Memory stall time (full)"};
5531 char *g_title[] = {"%smem-10", "%smem-60", "%smem-300",
5533 "%fmem-10", "%fmem-60", "%fmem-300",
5535 static double *spmin, *spmax;
5537 static int *outsize;
5540 if (action & F_BEGIN) {
5542 * Allocate arrays that will contain the graphs data
5543 * and the min/max values.
5545 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5548 if (action & F_MAIN) {
5549 /* Check for min/max values */
5550 if (psic->some_amem_10 > *spmax) {
5551 *spmax = psic->some_amem_10;
5553 if (psic->some_amem_10 < *spmin) {
5554 *spmin = psic->some_amem_10;
5556 if (psic->some_amem_60 > *(spmax + 1)) {
5557 *(spmax + 1) = psic->some_amem_60;
5559 if (psic->some_amem_60 < *(spmin + 1)) {
5560 *(spmin + 1) = psic->some_amem_60;
5562 if (psic->some_amem_300 > *(spmax + 2)) {
5563 *(spmax + 2) = psic->some_amem_300;
5565 if (psic->some_amem_300 < *(spmin + 2)) {
5566 *(spmin + 2) = psic->some_amem_300;
5568 tval = ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv);
5569 if (tval > *(spmax + 3)) {
5570 *(spmax + 3) = tval;
5572 if (tval < *(spmin + 3)) {
5573 *(spmin + 3) = tval;
5576 if (psic->full_amem_10 > *(spmax + 4)) {
5577 *(spmax + 4) = psic->full_amem_10;
5579 if (psic->full_amem_10 < *(spmin + 4)) {
5580 *(spmin + 4) = psic->full_amem_10;
5582 if (psic->full_amem_60 > *(spmax + 5)) {
5583 *(spmax + 5) = psic->full_amem_60;
5585 if (psic->full_amem_60 < *(spmin + 5)) {
5586 *(spmin + 5) = psic->full_amem_60;
5588 if (psic->full_amem_300 > *(spmax + 6)) {
5589 *(spmax + 6) = psic->full_amem_300;
5591 if (psic->full_amem_300 < *(spmin + 6)) {
5592 *(spmin + 6) = psic->full_amem_300;
5594 tval = ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv);
5595 if (tval > *(spmax + 7)) {
5596 *(spmax + 7) = tval;
5598 if (tval < *(spmin + 7)) {
5599 *(spmin + 7) = tval;
5603 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5604 (double) psic->some_amem_10 / 100,
5605 out, outsize, svg_p->restart);
5607 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5608 (double) psic->some_amem_60 / 100,
5609 out + 1, outsize + 1, svg_p->restart);
5611 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5612 (double) psic->some_amem_300 / 100,
5613 out + 2, outsize + 2, svg_p->restart);
5615 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5617 ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv),
5618 out + 3, outsize + 3, svg_p->dt);
5621 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5622 (double) psic->full_amem_10 / 100,
5623 out + 4, outsize + 4, svg_p->restart);
5625 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5626 (double) psic->full_amem_60 / 100,
5627 out + 5, outsize + 5, svg_p->restart);
5629 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5630 (double) psic->full_amem_300 / 100,
5631 out + 6, outsize + 6, svg_p->restart);
5633 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5635 ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv),
5636 out + 7, outsize + 7, svg_p->dt);
5639 if (action & F_END) {
5640 /* Fix min/max values for pressure ratios */
5641 *spmin /= 100; *spmax /= 100;
5642 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5643 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5645 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5646 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5647 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5649 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5650 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5652 /* Free remaining structures */
5653 free_graphs(out, outsize, spmin, spmax);