2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016-2019 by Sebastien GODARD (sysstat <at> orange.fr)
5 ***************************************************************************
6 * This program is free software; you can redistribute it and/or modify it *
7 * under the terms of the GNU General Public License as published by the *
8 * Free Software Foundation; either version 2 of the License, or (at your *
9 * option) any later version. *
11 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * You should have received a copy of the GNU General Public License along *
17 * with this program; if not, write to the Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *
19 ***************************************************************************
30 #include "svg_stats.h"
35 #define _(string) gettext(string)
37 #define _(string) (string)
40 extern unsigned int flags;
43 unsigned int svg_colors[SVG_COL_PALETTE_NR][SVG_COL_PALETTE_SIZE] =
44 {{0x00cc00, 0xff00bf, 0x00ffff, 0xff0000, /* Default palette */
45 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
46 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
47 0xcc3300, 0x50040f, 0xffffbf, 0x193d55,
48 0x000000, 0xffffff, 0x202020, 0xffff00,
49 0xffff00, 0x808080, 0xa52a2a, 0xff0000},
51 {0x000000, 0x1a1aff, 0x1affb2, 0xb21aff, /* Custom color palette */
52 0x1ab2ff, 0xff1a1a, 0xffb31a, 0xb2ff1a,
53 0xefefef, 0x000000, 0x1a1aff, 0x1affb2,
54 0xb21aff, 0x1ab2ff, 0xff1a1a, 0xffb31a,
55 0xffffff, 0x000000, 0xbebebe, 0x000000,
56 0x000000, 0x000000, 0x000000, 0x000000},
58 {0x696969, 0xbebebe, 0x000000, 0xa9a9a9, /* Black & white palette */
59 0x708090, 0xc0c0c0, 0x808080, 0xd3d3d3,
60 0x909090, 0x696969, 0xbebebe, 0x000000,
61 0x000000, 0xa9a9a9, 0xc0c0c0, 0x808080,
62 0xffffff, 0x000000, 0xbebebe, 0x000000,
63 0x000000, 0x000000, 0x000000, 0x000000}};
66 ***************************************************************************
67 * Compare the values of a statistics sample with the max and min values
68 * already found in previous samples for this same activity. If some new
69 * min or max values are found, then save them.
70 * Assume values cannot be negative.
71 * The structure containing the statistics sample is composed of @llu_nr
72 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
73 * followed by @u_nr unsigned int fields.
76 * @types_nr Number of fields whose type is "long long", "long" and "int"
77 * composing the structure.
78 * @cs Pointer on current sample statistics structure.
79 * @ps Pointer on previous sample statistics structure (may be NULL).
80 * @itv Interval of time in 1/100th of a second.
81 * @spmin Array containing min values already found for this activity.
82 * @spmax Array containing max values already found for this activity.
83 * @g_fields Index in spmin/spmax arrays where extrema values for each
84 * activity metric will be saved. As a consequence spmin/spmax
85 * arrays may contain values in a different order than that of
86 * the fields in the statistics structure.
89 * @spmin Array containg the possible new min values for current activity.
90 * @spmax Array containg the possible new max values for current activity.
91 ***************************************************************************
93 void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
94 double *spmin, double *spmax, int g_fields[])
96 unsigned long long *lluc, *llup;
97 unsigned long *luc, *lup;
98 unsigned int *uc, *up;
102 /* Compare unsigned long long fields */
103 lluc = (unsigned long long *) cs;
104 llup = (unsigned long long *) ps;
105 for (i = 0; i < types_nr[0]; i++, m++) {
107 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
111 * If no pointer on previous sample has been given
112 * then the value is not a per-second one.
114 val = (double) *lluc;
116 if (val < *(spmin + g_fields[m])) {
117 *(spmin + g_fields[m]) = val;
119 if (val > *(spmax + g_fields[m])) {
120 *(spmax + g_fields[m]) = val;
122 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
124 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
128 /* Compare unsigned long fields */
129 luc = (unsigned long *) lluc;
130 lup = (unsigned long *) llup;
131 for (i = 0; i < types_nr[1]; i++, m++) {
133 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
138 if (val < *(spmin + g_fields[m])) {
139 *(spmin + g_fields[m]) = val;
141 if (val > *(spmax + g_fields[m])) {
142 *(spmax + g_fields[m]) = val;
144 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
146 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
150 /* Compare unsigned int fields */
151 uc = (unsigned int *) luc;
152 up = (unsigned int *) lup;
153 for (i = 0; i < types_nr[2]; i++, m++) {
155 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
160 if (val < *(spmin + g_fields[m])) {
161 *(spmin + g_fields[m]) = val;
163 if (val > *(spmax + g_fields[m])) {
164 *(spmax + g_fields[m]) = val;
166 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
168 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
174 ***************************************************************************
175 * Find the min and max values of all the graphs that will be drawn in the
176 * same view. The graphs have their own min and max values in
177 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
180 * @pos Position in array for the first graph extrema value.
181 * @n Number of graphs to scan.
182 * @spmin Array containing min values for graphs.
183 * @spmax Array containing max values for graphs.
186 * @gmin Global min value found.
187 * @gmax Global max value found.
188 ***************************************************************************
190 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
191 double *gmin, double *gmax)
195 *gmin = *(spmin + pos);
196 *gmax = *(spmax + pos);
198 for (i = 1; i < n; i++) {
199 if (*(spmin + pos + i) < *gmin) {
200 *gmin = *(spmin + pos + i);
202 if (*(spmax + pos + i) > *gmax) {
203 *gmax = *(spmax + pos + i);
209 ***************************************************************************
210 * Allocate arrays used to save graphs data, min and max values.
211 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
212 * array is returned. This is equivalent to "char data[][n]" where each
213 * element is of indeterminate size and will contain the graph data (eg.
214 * << path d="M12,14 L13,16..." ... >>.
215 * The size of element data[i] is given by outsize[i].
216 * Also allocate an array to save min values (equivalent to "double spmin[n]")
217 * and an array for max values (equivalent to "double spmax[n]").
220 * @n Number of graphs to draw for current activity.
223 * @outsize Array that will contain the sizes of each element in array
224 * of chars. Equivalent to "int outsize[n]" with
225 * outsize[n] = sizeof(data[][n]).
226 * @spmin Array that will contain min values for current activity.
227 * @spmax Array that will contain max values for current activity.
230 * Pointer on array of arrays of chars that will contain the graphs data.
232 * NB: @min and @max arrays contain values in the same order as the fields
233 * in the statistics structure.
234 ***************************************************************************
236 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
243 * Allocate an array of pointers. Each of these pointers will
244 * be an array of chars.
246 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
250 /* Allocate array that will contain the size of each array of chars */
251 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
255 /* Allocate array that will contain the min value of each graph */
256 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
260 /* Allocate array that will contain the max value of each graph */
261 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
265 /* Allocate arrays of chars that will contain graphs data */
266 for (i = 0; i < n; i++) {
267 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
272 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
273 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
274 *(*spmin + i) = DBL_MAX; /* Init min and max values */
275 *(*spmax + i) = -DBL_MAX;
282 ***************************************************************************
283 * Save SVG code for current graph.
286 * @data SVG code to append to current graph definition.
287 * @out Pointer on array of chars for current graph definition.
288 * @outsize Size of array of chars for current graph definition.
291 * @out Pointer on array of chars for current graph definition that
292 * has been updated with the addition of current sample data.
293 * @outsize Array that containing the (possibly new) sizes of each
294 * element in array of chars.
295 ***************************************************************************
297 void save_svg_data(char *data, char **out, int *outsize)
303 /* Determine space left in array */
304 len = *outsize - strlen(out_p) - 1;
305 if (strlen(data) >= len) {
307 * If current array of chars doesn't have enough space left
308 * then reallocate it with CHUNKSIZE more bytes.
310 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
312 *outsize += CHUNKSIZE;
315 strncat(out_p, data, len);
319 ***************************************************************************
320 * Update line graph definition by appending current X,Y coordinates.
323 * @timetag Timestamp in seconds since the epoch for current sample
324 * stats. Will be used as X coordinate.
325 * @value Value of current sample metric. Will be used as Y coordinate.
326 * @out Pointer on array of chars for current graph definition.
327 * @outsize Size of array of chars for current graph definition.
328 * @restart Set to TRUE if a RESTART record has been read since the last
332 * @out Pointer on array of chars for current graph definition that
333 * has been updated with the addition of current sample data.
334 * @outsize Array that containing the (possibly new) sizes of each
335 * element in array of chars.
336 ***************************************************************************
338 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
343 /* Prepare additional graph definition data */
344 snprintf(data, 128, " %c%llu,%.2f", restart ? 'M' : 'L', timetag, value);
347 save_svg_data(data, out, outsize);
351 ***************************************************************************
352 * Update line graph definition by appending current X,Y coordinates. Use
353 * (unsigned long) integer values here.
356 * @timetag Timestamp in seconds since the epoch for current sample
357 * stats. Will be used as X coordinate.
358 * @value Value of current sample metric. Will be used as Y coordinate.
359 * @out Pointer on array of chars for current graph definition.
360 * @outsize Size of array of chars for current graph definition.
361 * @restart Set to TRUE if a RESTART record has been read since the last
365 * @out Pointer on array of chars for current graph definition that
366 * has been updated with the addition of current sample data.
367 * @outsize Array that containing the (possibly new) sizes of each
368 * element in array of chars.
369 ***************************************************************************
371 void lniappend(unsigned long long timetag, unsigned long long value, char **out,
372 int *outsize, int restart)
376 /* Prepare additional graph definition data */
377 snprintf(data, 128, " %c%llu,%llu", restart ? 'M' : 'L', timetag, value);
380 save_svg_data(data, out, outsize);
384 ***************************************************************************
385 * Update bar graph definition by adding a new rectangle.
388 * @timetag Timestamp in seconds since the epoch for current sample
389 * stats. Will be used as X coordinate.
390 * @value Value of current sample metric. Will be used as rectangle
392 * @offset Offset for Y coordinate.
393 * @out Pointer on array of chars for current graph definition.
394 * @outsize Size of array of chars for current graph definition.
395 * @dt Interval of time in seconds between current and previous
399 * @out Pointer on array of chars for current graph definition that
400 * has been updated with the addition of current sample data.
401 * @outsize Array that containing the (possibly new) sizes of each
402 * element in array of chars.
403 ***************************************************************************
405 void brappend(unsigned long long timetag, double offset, double value, char **out,
406 int *outsize, unsigned long long dt)
409 unsigned long long t = 0;
411 /* Prepare additional graph definition data */
412 if ((value == 0.0) || (dt == 0))
413 /* Don't draw a flat rectangle! */
419 snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
420 t, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
423 save_svg_data(data, out, outsize);
428 ***************************************************************************
429 * Update CPU graph and min/max values for each metric.
432 * @timetag Timestamp in seconds since the epoch for current sample
433 * stats. Will be used as X coordinate.
434 * @offset Offset for Y coordinate.
435 * @value Value of current CPU metric. Will be used as rectangle
437 * @out Pointer on array of chars for current graph definition.
438 * @outsize Size of array of chars for current graph definition.
439 * @dt Interval of time in seconds between current and previous
441 * @spmin Min value already found for this CPU metric.
442 * @spmax Max value already found for this CPU metric.
445 * @offset New offset value, to use to draw next rectangle
446 * @out Pointer on array of chars for current graph definition that
447 * has been updated with the addition of current sample data.
448 * @outsize Array that containing the (possibly new) sizes of each
449 * element in array of chars.
450 ***************************************************************************
452 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
453 int *outsize, unsigned long long dt, double *spmin, double *spmax)
455 /* Save min and max values */
456 if (value < *spmin) {
459 if (value > *spmax) {
462 /* Prepare additional graph definition data */
463 brappend(timetag, *offset, value, out, outsize, dt);
469 ***************************************************************************
470 * Update rectangular graph and min/max values.
473 * @timetag Timestamp in seconds since the epoch for current sample
474 * stats. Will be used as X coordinate.
475 * @p_value Metric value for previous sample
476 * @value Metric value for current sample.
477 * @out Pointer on array of chars for current graph definition.
478 * @outsize Size of array of chars for current graph definition.
479 * @restart Set to TRUE if a RESTART record has been read since the last
481 * @dt Interval of time in seconds between current and previous
483 * @spmin Min value already found for this metric.
484 * @spmax Max value already found for this metric.
487 * @out Pointer on array of chars for current graph definition that
488 * has been updated with the addition of current sample data.
489 * @outsize Array that containing the (possibly new) sizes of each
490 * element in array of chars.
491 * @spmin Min value for this metric.
492 * @spmax Max value for this metric.
493 ***************************************************************************
495 void recappend(unsigned long long timetag, double p_value, double value, char **out,
496 int *outsize, int restart, unsigned long long dt,
497 double *spmin, double *spmax)
499 char data[512], data1[128], data2[128];
500 unsigned long long t = 0;
502 /* Save min and max values */
503 if (value < *spmin) {
506 if (value > *spmax) {
512 /* Prepare additional graph definition data */
514 snprintf(data1, sizeof(data1), " M%llu,%.2f", t, p_value);
515 data1[sizeof(data1) - 1] = '\0';
517 if (p_value != value) {
518 snprintf(data2, sizeof(data2), " L%llu,%.2f", timetag, value);
519 data2[sizeof(data2) - 1] = '\0';
521 snprintf(data, sizeof(data), "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
522 p_value != value ? data2 : "");
523 data[sizeof(data) - 1] = '\0';
525 save_svg_data(data, out, outsize);
529 ***************************************************************************
530 * Calculate 10 raised to the power of n.
533 * @n Power number to use.
536 * 10 raised to the power of n.
537 ***************************************************************************
539 unsigned int pwr10(int n)
544 for (i = 0; i < n; i++) {
552 ***************************************************************************
553 * Autoscale graphs of a given view.
556 * @asf_nr (Maximum) number of autoscale factors.
557 * @group Number of graphs in current view.
558 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
559 * @pos Position in array for the first graph in view.
560 * @gmax Global max value for all graphs in view.
561 * @spmax Array containing max values for graphs.
564 * @asfactor Autoscale factors (one for each graph).
565 ***************************************************************************
567 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
568 double gmax, double *spmax)
573 for (j = 0; j < asf_nr; j++) {
574 /* Init autoscale factors */
578 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
580 for (j = 0; (j < group) && (j < asf_nr); j++) {
581 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
584 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
585 if (strlen(val) > 0) {
586 asfactor[j] = pwr10(strlen(val) - 1);
593 ***************************************************************************
594 * Display background grid (horizontal lines) and corresponding graduations.
597 * @ypos Gap between two horizontal lines.
598 * @yfactor Scaling factor on Y axis.
599 * @lmax Max value for current view.
600 * @dp Number of decimal places for graduations.
601 ***************************************************************************
603 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
609 /* Display horizontal lines (except on X axis) */
611 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
612 "stroke: #%06x\" transform=\"scale(1,%f)\"/>\n",
613 ypos * j, SVG_G_XSIZE, ypos * j,
614 svg_colors[palette][SVG_COL_GRID_IDX],
619 * Display graduations.
620 * Use same rounded value for graduation numbers as for grid lines
621 * to make sure they are properly aligned.
623 sprintf(stmp, "%.2f", ypos * j);
624 printf("<text x=\"0\" y=\"%ld\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
625 "text-anchor: end\">%.*f.</text>\n",
626 (long) (atof(stmp) * yfactor),
627 svg_colors[palette][SVG_COL_AXIS_IDX],
631 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
635 ***************************************************************************
636 * Display background grid (vertical lines) and corresponding graduations.
639 * @xpos Gap between two vertical lines.
640 * @xfactor Scaling factor on X axis.
641 * @v_gridnr Default number of vertical lines to display. The actual
642 * number may vary between this value and 2 times this value.
643 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
644 ***************************************************************************
646 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
648 struct record_header stamp;
650 char cur_time[TIMESTAMP_LEN];
653 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
656 * What really matters to know when we should stop drawing vertical lines
657 * is the time end. v_gridnr is only informative and used to calculate
658 * the gap between two lines.
660 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
662 /* Display vertical lines */
663 sa_get_record_timestamp_struct(flags, &stamp, &rectime);
664 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
665 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
666 "stroke: #%06x\" transform=\"scale(%f,1)\"/>\n",
667 xpos * j, xpos * j, -SVG_G_YSIZE,
668 svg_colors[palette][SVG_COL_GRID_IDX],
671 * Display graduations.
672 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
673 * In this case, we should rather display the exact time instead of only the hour.
675 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
676 printf("<text x=\"%ld\" y=\"15\" style=\"fill: #%06x; stroke: none; font-size: 14px; "
677 "text-anchor: start\">%2d:00</text>\n",
678 (long) (xpos * j * xfactor) - 15,
679 svg_colors[palette][SVG_COL_AXIS_IDX],
683 printf("<text x=\"%ld\" y=\"10\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
684 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
685 (long) (xpos * j * xfactor),
686 svg_colors[palette][SVG_COL_AXIS_IDX],
687 (long) (xpos * j * xfactor), cur_time);
689 stamp.ust_time += xpos;
692 if (!PRINT_LOCAL_TIME(flags)) {
693 printf("<text x=\"-10\" y=\"30\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
694 "text-anchor: end\">UTC</text>\n",
695 svg_colors[palette][SVG_COL_INFO_IDX]);
700 ***************************************************************************
701 * Calculate the value on the Y axis between two horizontal lines that will
702 * make the graph background grid.
705 * @lmax Max value reached for this graph.
708 * @dp Number of decimal places for Y graduations.
711 * Value between two horizontal lines.
712 ***************************************************************************
714 double ygrid(double lmax, int *dp)
725 n = (long) (lmax / SVG_H_GRIDNR);
728 return (lmax / SVG_H_GRIDNR);
730 snprintf(val, 32, "%ld", n);
737 return ((double) (((long) (n / e)) * e));
741 ***************************************************************************
742 * Calculate the value on the X axis between two vertical lines that will
743 * make the graph background grid.
746 * @timestart First data timestamp (X coordinate of the first data point).
747 * @timeend Last data timestamp (X coordinate of the last data point).
748 * @v_gridnr Number of vertical lines to display. Its value is normally
749 * SVG_V_GRIDNR, except when option "oneday" is used, in which
750 * case it is set to 12.
753 * Value between two vertical lines.
754 ***************************************************************************
756 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
758 if ((timeend - timestart) <= v_gridnr)
761 return ((timeend - timestart) / v_gridnr);
765 ***************************************************************************
766 * Free global graphs structures.
769 * @out Pointer on array of chars for each graph definition.
770 * @outsize Size of array of chars for each graph definition.
771 * @spmin Array containing min values for graphs.
772 * @spmax Array containing max values for graphs.
773 ***************************************************************************
775 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
792 ***************************************************************************
793 * Skip current view where all graphs have only zero values. This function
794 * is called when option "skipempty" has been used, or when "No data" have
795 * been found for current view.
798 * @out Pointer on array of chars for each graph definition.
799 * @pos Position of current view in the array of graphs definitions.
800 * @group Number of graphs in current view.
803 * @pos Position of next view in the array of graphs definitions.
804 ***************************************************************************
806 void skip_current_view(char **out, int *pos, int group)
811 for (j = 0; j < group; j++) {
812 out_p = *(out + *pos + j);
814 /* Even if not displayed, current graph data have to be freed */
822 ***************************************************************************
823 * Display all graphs for current activity.
826 * @g_nr Number of views to display.
827 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
828 * @title Titles for each set of graphs.
829 * @g_title Titles for each graph.
830 * @item_name Item (network interface, etc.) name.
831 * @group Indicate how graphs are grouped together to make sets.
832 * @spmin Array containing min values for graphs.
833 * @spmax Array containing max values for graphs.
834 * @out Pointer on array of chars for each graph definition.
835 * @outsize Size of array of chars for each graph definition.
836 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
837 * time for the first sample of stats (.@ust_time_first), and
838 * times used as start and end values on the X axis
839 * (.@ust_time_ref and .@ust_time_end).
840 * @record_hdr Pointer on record header of current stats sample.
841 * @skip_void Set to <> 0 if graphs with no data should be skipped.
842 * This is typicallly used to not display CPU offline on the
844 * @id Current activity id.
845 * @xid Current activity extra id number.
848 * TRUE if at least one graph has been displayed.
849 ***************************************************************************
851 int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
852 int group[], double *spmin, double *spmax, char **out, int *outsize,
853 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
854 unsigned int id, unsigned int xid)
857 int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE, palpos;
858 int v_gridnr, xv, yv;
859 unsigned int asfactor[16];
861 double lmax, xfactor, yfactor, ypos, gmin, gmax;
862 char val[32], cur_date[TIMESTAMP_LEN];
865 /* For each view which is part of current activity */
866 for (i = 0; i < g_nr; i++) {
868 /* Used as index in color palette */
869 palpos = (palette == SVG_BW_COL_PALETTE ? 0 : pos);
871 /* Get global min and max value for current view */
872 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
874 /* Don't display empty views if requested */
875 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
876 skip_current_view(out, &pos, group[i]);
879 /* Skip void graphs */
880 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
884 /* Translate to proper position for current activity */
885 printf("<g id=\"g%d-%d\" transform=\"translate(0,%d)\">\n",
888 SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
889 SVG_T_YSIZE * svg_p->graph_no);
893 /* Increment number of views actually displayed */
896 /* Compute top left position of view */
897 if (PACK_VIEWS(flags)) {
898 xv = (views_nr - 1) * SVG_T_XSIZE;
903 yv = (views_nr - 1) * SVG_T_YSIZE;
906 /* Graph background */
907 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\" fill=\"#%06x\"/>\n",
908 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE,
909 svg_colors[palette][SVG_COL_BCKGRD_IDX]);
912 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">%s",
914 svg_colors[palette][SVG_COL_TITLE_IDX],
917 printf(" [%s]", item_name);
920 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
921 "(Min, Max values)</tspan>\n</text>\n",
922 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25,
923 svg_colors[palette][SVG_COL_INFO_IDX]);
926 * At least two samples are needed.
927 * And a min and max value should have been found.
929 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
930 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
932 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">No data</text>\n",
933 xv, yv + SVG_M_YSIZE,
934 svg_colors[palette][SVG_COL_ERROR_IDX]);
935 skip_current_view(out, &pos, group[i]);
940 printf("<polyline points=\"%d,%d %d,%d %d,%d\" style=\"fill: #%06x; stroke: #%06x; stroke-width: 2\"/>\n",
941 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
942 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
943 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
944 svg_colors[palette][SVG_COL_BCKGRD_IDX],
945 svg_colors[palette][SVG_COL_AXIS_IDX]);
947 /* Autoscaling graphs if needed */
948 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
951 for (j = 0; j < group[i]; j++) {
952 /* Set dp to TRUE (1) if current metric is based on integer values */
953 dp = (g_title[pos + j][0] == '~');
954 snprintf(val, 32, "x%u ", asfactor[j]);
955 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
956 "%s %s(%.*f, %.*f)</text>\n",
957 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
958 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
959 asfactor[j] == 1 ? "" : val,
960 !dp * 2, *(spmin + pos + j) * asfactor[j],
961 !dp * 2, *(spmax + pos + j) * asfactor[j]);
964 if (DISPLAY_INFO(flags)) {
965 /* Display additional info (hostname, date) */
966 printf("<text x=\"%d\" y=\"%d\" "
967 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
969 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
970 svg_colors[palette][SVG_COL_INFO_IDX],
971 svg_p->file_hdr->sa_nodename);
973 /* Get report date */
974 set_report_date(localtime_r((const time_t *) &(svg_p->file_hdr->sa_ust_time), &rectime),
975 cur_date, sizeof(cur_date));
976 printf("<tspan x=\"%d\" y=\"%d\" "
977 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
978 "%s</tspan>\n</text>\n",
979 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
980 svg_colors[palette][SVG_COL_INFO_IDX],
984 /* Translate to proper position for current graph within current activity */
985 printf("<g transform=\"translate(%d,%d)\">\n",
986 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
989 if (g_type[i] == SVG_LINE_GRAPH) {
990 /* For line graphs */
992 /* If all values are zero then set current max value to 1 */
998 /* Max value cannot be too small, else Y graduations will be meaningless */
999 if (lmax < SVG_H_GRIDNR * 0.01) {
1000 lmax = SVG_H_GRIDNR * 0.01;
1002 ypos = ygrid(lmax, &dp);
1005 /* For bar graphs (used for %values) */
1006 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
1007 dp = 0; /* No decimals */
1009 /* Max should be always 100% except for percentage values greater than 100% */
1017 yfactor = (double) -SVG_G_YSIZE / lmax;
1019 /* Display horizontal lines and graduations */
1020 display_hgrid(ypos, yfactor, lmax, dp);
1022 /* Set number of vertical lines to 12 when option "oneday" is used */
1023 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1025 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1026 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1028 /* Display vertical lines and graduations */
1029 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1031 /* Draw current graphs set */
1032 for (j = 0; j < group[i]; j++) {
1033 out_p = *(out + pos + j);
1034 if (g_type[i] == SVG_LINE_GRAPH) {
1036 printf("<path d=\"%s\" "
1037 "style=\"vector-effect: non-scaling-stroke; "
1038 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1039 "transform=\"scale(%f,%f)\"/>\n",
1041 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK],
1043 yfactor * asfactor[j]);
1045 else if (*out_p) { /* Ignore flat bars */
1047 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1048 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1049 printf("%s\n", out_p);
1060 /* For next row of views */
1061 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1068 ***************************************************************************
1069 * Display CPU statistics in SVG.
1072 * @a Activity structure with statistics.
1073 * @curr Index in array for current sample statistics.
1074 * @action Action expected from current function.
1075 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1076 * flag indicating that a restart record has been previously
1077 * found (.@restart), and time used for the X axis origin
1079 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1081 * @record_hdr Pointer on record header of current stats sample.
1082 ***************************************************************************
1084 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1085 unsigned long long itv, struct record_header *record_hdr)
1087 struct stats_cpu *scc, *scp;
1088 unsigned long long deltot_jiffies = 1;
1089 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1092 int g_type[] = {SVG_BAR_GRAPH};
1093 char *title[] = {"CPU utilization"};
1094 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1095 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1096 static double *spmin, *spmax;
1098 static int *outsize;
1103 if (action & F_BEGIN) {
1105 * Allocate arrays that will contain the graphs data
1106 * and the min/max values.
1108 out = allocate_graph_lines(10 * a->item_list_sz, &outsize, &spmin, &spmax);
1111 if (action & F_MAIN) {
1113 /* @nr[curr] cannot normally be greater than @nr_ini */
1114 if (a->nr[curr] > a->nr_ini) {
1115 a->nr_ini = a->nr[curr];
1119 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1120 * and look for offline CPU.
1122 if (a->nr_ini > 1) {
1123 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1124 flags, offline_cpu_bitmap);
1128 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1130 /* Should current CPU (including CPU "all") be displayed? */
1131 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1132 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1133 /* Don't display CPU */
1136 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1137 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1143 /* This is CPU "all" */
1144 if (a->nr_ini == 1) {
1146 * This is a UP machine. In this case
1147 * interval has still not been calculated.
1149 deltot_jiffies = get_per_cpu_interval(scc, scp);
1151 if (!deltot_jiffies) {
1152 /* CPU "all" cannot be tickless */
1158 * Recalculate interval for current proc.
1159 * If result is 0 then current CPU is a tickless one.
1161 deltot_jiffies = get_per_cpu_interval(scc, scp);
1163 if (!deltot_jiffies) { /* Current CPU is tickless */
1165 val = 100.0; /* Tickless CPU: %idle = 100% */
1167 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1170 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1174 /* Check min/max values for %user, etc. */
1175 for (k = 0; k < j; k++) {
1176 if (0.0 < *(spmin + pos + k)) {
1177 *(spmin + pos + k) = 0.0;
1179 if (0.0 > *(spmax + pos + k)) {
1180 *(spmax + pos + k) = 0.0;
1185 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1187 out + pos + j, outsize + pos + j, svg_p->dt,
1188 spmin + pos + j, spmax + pos + j);
1193 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1195 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1196 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1197 out + pos, outsize + pos, svg_p->dt,
1198 spmin + pos, spmax + pos);
1202 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1204 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1206 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1207 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1208 out + pos, outsize + pos, svg_p->dt,
1209 spmin + pos, spmax + pos);
1212 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1214 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1215 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1216 out + pos + 1, outsize + pos + 1, svg_p->dt,
1217 spmin + pos + 1, spmax + pos + 1);
1221 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1223 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1225 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1226 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1227 out + pos + 1, outsize + pos + 1, svg_p->dt,
1228 spmin + pos + 1, spmax + pos + 1);
1231 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1233 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1235 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1236 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1238 out + pos + 2, outsize + pos + 2, svg_p->dt,
1239 spmin + pos + 2, spmax + pos + 2);
1243 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1244 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1245 out + pos + 2, outsize + pos + 2, svg_p->dt,
1246 spmin + pos + 2, spmax + pos + 2);
1250 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1251 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1252 out + pos + 3, outsize + pos + 3, svg_p->dt,
1253 spmin + pos + 3, spmax + pos + 3);
1255 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1256 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1257 out + pos + 4, outsize + pos + 4, svg_p->dt,
1258 spmin + pos + 4, spmax + pos + 4);
1260 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1262 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1263 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1264 out + pos + 5, outsize + pos + 5, svg_p->dt,
1265 spmin + pos + 5, spmax + pos + 5);
1267 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1268 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1269 out + pos + 6, outsize + pos + 6, svg_p->dt,
1270 spmin + pos + 6, spmax + pos + 6);
1272 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1273 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1274 out + pos + 7, outsize + pos + 7, svg_p->dt,
1275 spmin + pos + 7, spmax + pos + 7);
1277 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1278 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1279 out + pos + 8, outsize + pos + 8, svg_p->dt,
1280 spmin + pos + 8, spmax + pos + 8);
1289 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1291 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1292 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1293 out + pos + j, outsize + pos + j, svg_p->dt,
1294 spmin + pos + j, spmax + pos + j);
1298 if (action & F_END) {
1299 int xid = 0, displayed;
1301 if (DISPLAY_IDLE(flags)) {
1302 /* Include additional %idle field */
1307 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
1309 /* Should current CPU (including CPU "all") be displayed? */
1310 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1316 /* This is CPU "all" */
1317 strcpy(item_name, "all");
1320 sprintf(item_name, "%d", i - 1);
1323 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1324 displayed = draw_activity_graphs(a->g_nr, g_type,
1325 title, g_title1, item_name, group1,
1326 spmin + pos, spmax + pos, out + pos, outsize + pos,
1327 svg_p, record_hdr, i, a->id, xid);
1330 displayed = draw_activity_graphs(a->g_nr, g_type,
1331 title, g_title2, item_name, group2,
1332 spmin + pos, spmax + pos, out + pos, outsize + pos,
1333 svg_p, record_hdr, i, a->id, xid);
1340 /* Free remaining structures */
1341 free_graphs(out, outsize, spmin, spmax);
1346 ***************************************************************************
1347 * Display task creation and context switch statistics in SVG.
1350 * @a Activity structure with statistics.
1351 * @curr Index in array for current sample statistics.
1352 * @action Action expected from current function.
1353 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1354 * flag indicating that a restart record has been previously
1355 * found (.@restart) and time used for the X axis origin
1357 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1358 * @record_hdr Pointer on record header of current stats sample.
1359 ***************************************************************************
1361 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1362 unsigned long long itv, struct record_header *record_hdr)
1365 *spc = (struct stats_pcsw *) a->buf[curr],
1366 *spp = (struct stats_pcsw *) a->buf[!curr];
1367 int group[] = {1, 1};
1368 int g_fields[] = {1, 0};
1369 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1370 char *title[] = {"Task creation", "Switching activity"};
1371 char *g_title[] = {"proc/s",
1373 static double *spmin, *spmax;
1375 static int *outsize;
1377 if (action & F_BEGIN) {
1379 * Allocate arrays that will contain the graphs data
1380 * and the min/max values.
1382 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1385 if (action & F_MAIN) {
1386 /* Check for min/max values */
1387 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1388 itv, spmin, spmax, g_fields);
1390 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1391 S_VALUE(spp->processes, spc->processes, itv),
1392 out, outsize, svg_p->restart);
1394 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1395 S_VALUE(spp->context_switch, spc->context_switch, itv),
1396 out + 1, outsize + 1, svg_p->restart);
1399 if (action & F_END) {
1400 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1401 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1403 /* Free remaining structures */
1404 free_graphs(out, outsize, spmin, spmax);
1409 ***************************************************************************
1410 * Display swap statistics in SVG.
1413 * @a Activity structure with statistics.
1414 * @curr Index in array for current sample statistics.
1415 * @action Action expected from current function.
1416 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1417 * flag indicating that a restart record has been previously
1418 * found (.@restart) and time used for the X axis origin
1420 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1421 * @record_hdr Pointer on record header of current stats sample.
1422 ***************************************************************************
1424 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1425 unsigned long long itv, struct record_header *record_hdr)
1428 *ssc = (struct stats_swap *) a->buf[curr],
1429 *ssp = (struct stats_swap *) a->buf[!curr];
1431 int g_type[] = {SVG_LINE_GRAPH};
1432 char *title[] = {"Swap activity"};
1433 char *g_title[] = {"pswpin/s", "pswpout/s" };
1434 int g_fields[] = {0, 1};
1435 static double *spmin, *spmax;
1437 static int *outsize;
1439 if (action & F_BEGIN) {
1441 * Allocate arrays that will contain the graphs data
1442 * and the min/max values.
1444 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1447 if (action & F_MAIN) {
1448 /* Check for min/max values */
1449 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1450 itv, spmin, spmax, g_fields);
1452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1453 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1454 out, outsize, svg_p->restart);
1456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1457 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1458 out + 1, outsize + 1, svg_p->restart);
1461 if (action & F_END) {
1462 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1463 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1465 /* Free remaining structures */
1466 free_graphs(out, outsize, spmin, spmax);
1471 ***************************************************************************
1472 * Display paging statistics in SVG.
1475 * @a Activity structure with statistics.
1476 * @curr Index in array for current sample statistics.
1477 * @action Action expected from current function.
1478 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1479 * flag indicating that a restart record has been previously
1480 * found (.@restart) and time used for the X axis origin
1482 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1483 * @record_hdr Pointer on record header of current stats sample.
1484 ***************************************************************************
1486 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1487 unsigned long long itv, struct record_header *record_hdr)
1490 *spc = (struct stats_paging *) a->buf[curr],
1491 *spp = (struct stats_paging *) a->buf[!curr];
1492 int group[] = {2, 2, 4};
1493 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1494 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1495 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1496 "fault/s", "majflt/s",
1497 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1498 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1499 static double *spmin, *spmax;
1501 static int *outsize;
1503 if (action & F_BEGIN) {
1505 * Allocate arrays that will contain the graphs data
1506 * and the min/max values.
1508 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1511 if (action & F_MAIN) {
1512 /* Check for min/max values */
1513 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1514 itv, spmin, spmax, g_fields);
1516 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1517 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1518 out, outsize, svg_p->restart);
1520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1521 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1522 out + 1, outsize + 1, svg_p->restart);
1524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1525 S_VALUE(spp->pgfault, spc->pgfault, itv),
1526 out + 2, outsize + 2, svg_p->restart);
1528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1529 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1530 out + 3, outsize + 3, svg_p->restart);
1532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1533 S_VALUE(spp->pgfree, spc->pgfree, itv),
1534 out + 4, outsize + 4, svg_p->restart);
1536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1537 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1538 out + 5, outsize + 5, svg_p->restart);
1540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1541 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1542 out + 6, outsize + 6, svg_p->restart);
1544 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1545 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1546 out + 7, outsize + 7, svg_p->restart);
1549 if (action & F_END) {
1550 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1551 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1553 /* Free remaining structures */
1554 free_graphs(out, outsize, spmin, spmax);
1559 ***************************************************************************
1560 * Display I/O and transfer rate statistics in SVG.
1563 * @a Activity structure with statistics.
1564 * @curr Index in array for current sample statistics.
1565 * @action Action expected from current function.
1566 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1567 * flag indicating that a restart record has been previously
1568 * found (.@restart) and time used for the X axis origin
1570 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1571 * @record_hdr Pointer on record header of current stats sample.
1572 ***************************************************************************
1574 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1575 unsigned long long itv, struct record_header *record_hdr)
1578 *sic = (struct stats_io *) a->buf[curr],
1579 *sip = (struct stats_io *) a->buf[!curr];
1580 int group[] = {4, 3};
1581 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1582 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1583 char *g_title[] = {"tps", "rtps", "wtps", "dtps",
1584 "bread/s", "bwrtn/s", "bdscd/s"};
1586 * tps:0, rtps:1, wtps:2, dtps:3, bread/s:4, bwrtn/s:5, bdscd/s:6
1596 int g_fields[] = {0, 1, 2, 4, 5, 3, 6};
1597 static double *spmin, *spmax;
1599 static int *outsize;
1601 if (action & F_BEGIN) {
1603 * Allocate arrays that will contain the graphs data
1604 * and the min/max values.
1606 out = allocate_graph_lines(7, &outsize, &spmin, &spmax);
1609 if (action & F_MAIN) {
1610 /* Check for min/max values */
1611 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1612 itv, spmin, spmax, g_fields);
1615 * If we get negative values, this is probably because
1616 * one or more devices/filesystems have been unmounted.
1617 * We display 0.0 in this case though we should rather tell
1618 * the user that the value cannot be calculated here.
1621 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1622 sic->dk_drive < sip->dk_drive ? 0.0 :
1623 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1624 out, outsize, svg_p->restart);
1626 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1627 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1628 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1629 out + 1, outsize + 1, svg_p->restart);
1631 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1632 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1633 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1634 out + 2, outsize + 2, svg_p->restart);
1636 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1637 sic->dk_drive_dio < sip->dk_drive_dio ? 0.0 :
1638 S_VALUE(sip->dk_drive_dio, sic->dk_drive_dio, itv),
1639 out + 3, outsize + 3, svg_p->restart);
1641 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1642 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1643 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1644 out + 4, outsize + 4, svg_p->restart);
1646 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1647 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1648 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1649 out + 5, outsize + 5, svg_p->restart);
1651 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1652 sic->dk_drive_dblk < sip->dk_drive_dblk ? 0.0 :
1653 S_VALUE(sip->dk_drive_dblk, sic->dk_drive_dblk, itv),
1654 out + 6, outsize + 6, svg_p->restart);
1657 if (action & F_END) {
1658 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1659 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1661 /* Free remaining structures */
1662 free_graphs(out, outsize, spmin, spmax);
1667 ***************************************************************************
1668 * Display memory statistics in SVG.
1671 * @a Activity structure with statistics.
1672 * @curr Index in array for current sample statistics.
1673 * @action Action expected from current function.
1674 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1675 * flag indicating that a restart record has been previously
1676 * found (.@restart) and time used for the X axis origin
1678 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1679 * @record_hdr Pointer on record header of current stats sample.
1680 ***************************************************************************
1682 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1683 unsigned long long itv, struct record_header *record_hdr)
1686 *smc = (struct stats_memory *) a->buf[curr];
1687 int group1[] = {3, 1, 3, 1, 3, 5};
1688 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1689 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1690 int group2[] = {3, 1, 1};
1691 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1692 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1693 "Memory utilization (3)", "Memory utilization (4)",
1694 "Memory utilization (5)", "Memory utilization (6)"};
1695 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1696 "Swap utilization (3)"};
1697 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1698 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1699 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1701 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1703 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1704 static double *spmin, *spmax;
1706 static int *outsize;
1710 unsigned long long nousedmem;
1712 if (action & F_BEGIN) {
1714 * Allocate arrays that will contain the graphs data
1715 * and the min/max values.
1717 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1720 if (action & F_MAIN) {
1721 /* Check for min/max values */
1722 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1723 itv, spmin, spmax, g_fields);
1724 /* Compute %memused min/max values */
1725 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1726 if (nousedmem > smc->tlmkb) {
1727 nousedmem = smc->tlmkb;
1729 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1730 if (tval > *(spmax + 3)) {
1731 *(spmax + 3) = tval;
1733 if (tval < *(spmin + 3)) {
1734 *(spmin + 3) = tval;
1736 /* Compute %commit min/max values */
1737 tval = (smc->tlmkb + smc->tlskb) ?
1738 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1739 if (tval > *(spmax + 7)) {
1740 *(spmax + 7) = tval;
1742 if (tval < *(spmin + 7)) {
1743 *(spmin + 7) = tval;
1745 /* Compute %swpused min/max values */
1747 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1748 if (tval > *(spmax + 19)) {
1749 *(spmax + 19) = tval;
1751 if (tval < *(spmin + 19)) {
1752 *(spmin + 19) = tval;
1754 /* Compute %swpcad min/max values */
1755 tval = (smc->tlskb - smc->frskb) ?
1756 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1757 if (tval > *(spmax + 20)) {
1758 *(spmax + 20) = tval;
1760 if (tval < *(spmin + 20)) {
1761 *(spmin + 20) = tval;
1763 /* Compute memused min/max values in MB */
1764 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1765 if (tval > *(spmax + 2)) {
1766 *(spmax + 2) = tval;
1768 if (tval < *(spmin + 2)) {
1769 *(spmin + 2) = tval;
1771 /* Compute swpused min/max values in MB */
1772 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1773 if (tval > *(spmax + 17)) {
1774 *(spmax + 17) = tval;
1776 if (tval < *(spmin + 17)) {
1777 *(spmin + 17) = tval;
1781 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1782 ((double) smc->frmkb) / 1024,
1783 out, outsize, svg_p->restart);
1785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1786 ((double) (smc->tlmkb - nousedmem)) / 1024,
1787 out + 2, outsize + 2, svg_p->restart);
1789 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1790 ((double) smc->availablekb) / 1024,
1791 out + 1, outsize + 1, svg_p->restart);
1793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1794 ((double) smc->bufkb) / 1024,
1795 out + 4, outsize + 4, svg_p->restart);
1797 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1798 ((double) smc->camkb) / 1024,
1799 out + 5, outsize + 5, svg_p->restart);
1801 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1802 ((double) smc->frskb) / 1024,
1803 out + 16, outsize + 16, svg_p->restart);
1805 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1806 ((double) (smc->tlskb - smc->frskb)) / 1024,
1807 out + 17, outsize + 17, svg_p->restart);
1809 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1810 ((double) smc->caskb) / 1024,
1811 out + 18, outsize + 18, svg_p->restart);
1813 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1814 ((double) smc->comkb) / 1024,
1815 out + 6, outsize + 6, svg_p->restart);
1817 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1818 ((double) smc->activekb) / 1024,
1819 out + 8, outsize + 8, svg_p->restart);
1821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1822 ((double) smc->inactkb) / 1024,
1823 out + 9, outsize + 9, svg_p->restart);
1825 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1826 ((double) smc->dirtykb) / 1024,
1827 out + 10, outsize + 10, svg_p->restart);
1829 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1830 ((double) smc->anonpgkb) / 1024,
1831 out + 11, outsize + 11, svg_p->restart);
1833 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1834 ((double) smc->slabkb) / 1024,
1835 out + 12, outsize + 12, svg_p->restart);
1837 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1838 ((double) smc->kstackkb) / 1024,
1839 out + 13, outsize + 13, svg_p->restart);
1841 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1842 ((double) smc->pgtblkb) / 1024,
1843 out + 14, outsize + 14, svg_p->restart);
1845 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1846 ((double) smc->vmusedkb) / 1024,
1847 out + 15, outsize + 15, svg_p->restart);
1849 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1852 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1853 out + 3, outsize + 3, svg_p->dt);
1855 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1857 (smc->tlmkb + smc->tlskb) ?
1858 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1859 out + 7, outsize + 7, svg_p->dt);
1861 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1864 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1865 out + 19, outsize + 19, svg_p->dt);
1867 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1869 (smc->tlskb - smc->frskb) ?
1870 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1871 out + 20, outsize + 20, svg_p->dt);
1874 if (action & F_END) {
1876 /* Conversion kB -> MB */
1877 for (i = 0; i < 17; i++) {
1878 *(spmin + g_fields[i]) /= 1024;
1879 *(spmax + g_fields[i]) /= 1024;
1882 if (DISPLAY_MEMORY(a->opt_flags)) {
1883 if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1884 g_type1, title1, g_title1, NULL, group1,
1885 spmin, spmax, out, outsize, svg_p, record_hdr,
1886 FALSE, a->id, xid)) {
1891 if (DISPLAY_SWAP(a->opt_flags)) {
1892 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1893 spmin + 16, spmax + 16, out + 16, outsize + 16,
1894 svg_p, record_hdr, FALSE, a->id, xid);
1897 /* Free remaining structures */
1898 free_graphs(out, outsize, spmin, spmax);
1903 ***************************************************************************
1904 * Display kernel tables statistics in SVG.
1907 * @a Activity structure with statistics.
1908 * @curr Index in array for current sample statistics.
1909 * @action Action expected from current function.
1910 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1911 * flag indicating that a restart record has been previously
1912 * found (.@restart) and time used for the X axis origin
1914 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1915 * @record_hdr Pointer on record header of current stats sample.
1916 ***************************************************************************
1918 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1919 unsigned long long itv, struct record_header *record_hdr)
1921 struct stats_ktables
1922 *skc = (struct stats_ktables *) a->buf[curr];
1923 int group[] = {3, 1};
1924 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1925 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1926 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1928 int g_fields[] = {1, 2, 0, 3};
1929 static double *spmin, *spmax;
1931 static int *outsize;
1933 if (action & F_BEGIN) {
1935 * Allocate arrays that will contain the graphs data
1936 * and the min/max values.
1938 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1941 if (action & F_MAIN) {
1942 /* Check for min/max values */
1943 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1944 itv, spmin, spmax, g_fields);
1946 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1947 (unsigned long long) skc->dentry_stat,
1948 out, outsize, svg_p->restart);
1950 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1951 (unsigned long long) skc->file_used,
1952 out + 1, outsize + 1, svg_p->restart);
1954 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1955 (unsigned long long) skc->inode_used,
1956 out + 2, outsize + 2, svg_p->restart);
1958 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1959 (unsigned long long) skc->pty_nr,
1960 out + 3, outsize + 3, svg_p->restart);
1963 if (action & F_END) {
1964 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1965 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1967 /* Free remaining structures */
1968 free_graphs(out, outsize, spmin, spmax);
1973 ***************************************************************************
1974 * Display queue and load statistics in SVG.
1977 * @a Activity structure with statistics.
1978 * @curr Index in array for current sample statistics.
1979 * @action Action expected from current function.
1980 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1981 * flag indicating that a restart record has been previously
1982 * found (.@restart) and time used for the X axis origin
1984 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1985 * @record_hdr Pointer on record header of current stats sample.
1986 ***************************************************************************
1988 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1989 unsigned long long itv, struct record_header *record_hdr)
1992 *sqc = (struct stats_queue *) a->buf[curr];
1993 int group[] = {2, 1, 3};
1994 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1995 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
1996 char *g_title[] = {"~runq-sz", "~blocked",
1998 "ldavg-1", "ldavg-5", "ldavg-15"};
1999 int g_fields[] = {0, 1, 2, 3, 4, 5};
2000 static double *spmin, *spmax;
2002 static int *outsize;
2004 if (action & F_BEGIN) {
2006 * Allocate arrays that will contain the graphs data
2007 * and the min/max values.
2009 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2012 if (action & F_MAIN) {
2013 /* Check for min/max values */
2014 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2015 itv, spmin, spmax, g_fields);
2017 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2018 (unsigned long long) sqc->nr_running,
2019 out, outsize, svg_p->restart);
2021 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2022 (unsigned long long) sqc->procs_blocked,
2023 out + 1, outsize + 1, svg_p->restart);
2025 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2026 (unsigned long long) sqc->nr_threads,
2027 out + 2, outsize + 2, svg_p->restart);
2029 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2030 (double) sqc->load_avg_1 / 100,
2031 out + 3, outsize + 3, svg_p->restart);
2033 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2034 (double) sqc->load_avg_5 / 100,
2035 out + 4, outsize + 4, svg_p->restart);
2037 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2038 (double) sqc->load_avg_15 / 100,
2039 out + 5, outsize + 5, svg_p->restart);
2042 if (action & F_END) {
2043 /* Fix min/max values for load average */
2044 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2045 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2046 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2048 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2049 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2051 /* Free remaining structures */
2052 free_graphs(out, outsize, spmin, spmax);
2057 ***************************************************************************
2058 * Display disk statistics in SVG.
2061 * @a Activity structure with statistics.
2062 * @curr Index in array for current sample statistics.
2063 * @action Action expected from current function.
2064 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2065 * flag indicating that a restart record has been previously
2066 * found (.@restart) and time used for the X axis origin
2068 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2069 * @record_hdr Pointer on record header of current stats sample.
2070 ***************************************************************************
2072 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2073 unsigned long long itv, struct record_header *record_hdr)
2075 struct stats_disk *sdc, *sdp, sdpzero;
2076 struct ext_disk_stats xds;
2077 int group[] = {1, 3, 2, 1, 1};
2078 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2079 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2080 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2081 "Block devices statistics (3)", "Block devices statistics (4)",
2082 "Block devices statistics (5)"};
2083 char *g_title[] = {"tps",
2084 "rkB/s", "wkB/s", "dkB/s",
2085 "areq-sz", "aqu-sz",
2088 int g_fields[] = {0, 1, 2};
2090 unsigned int local_types_nr[] = {1, 0, 0};
2091 static double *spmin, *spmax;
2093 static int *outsize;
2094 char *dev_name, *item_name;
2095 double rkB, wkB, dkB, aqusz;
2096 int i, j, k, pos, restart, *unregistered;
2098 if (action & F_BEGIN) {
2100 * Allocate arrays (#0..7) that will contain the graphs data
2101 * and the min/max values.
2102 * Also allocate one additional array (#8) for each disk device:
2103 * out + 8 will contain the device name (WWN id, pretty name or devm-n),
2104 * outsize + 8 will contain a positive value (TRUE) if the device
2105 * has either still not been registered, or has been unregistered.
2107 out = allocate_graph_lines(nr_arrays * a->item_list_sz, &outsize, &spmin, &spmax);
2110 if (action & F_MAIN) {
2111 memset(&sdpzero, 0, STATS_DISK_SIZE);
2112 restart = svg_p->restart;
2114 * Mark previously registered devices as now
2115 * possibly unregistered for all graphs.
2117 for (k = 0; k < a->item_list_sz; k++) {
2118 unregistered = outsize + k * nr_arrays + 8;
2119 if (*unregistered == FALSE) {
2120 *unregistered = MAYBE;
2124 /* For each device structure */
2125 for (i = 0; i < a->nr[curr]; i++) {
2126 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2128 /* Get device name */
2129 dev_name = get_sa_devname(sdc->major, sdc->minor,
2130 sdc->wwn, sdc->part_nr, flags);
2132 if (a->item_list != NULL) {
2133 /* A list of devices has been entered on the command line */
2134 if (!search_list_item(a->item_list, dev_name))
2135 /* Device not found */
2139 /* Look for corresponding graph */
2140 for (k = 0; k < a->item_list_sz; k++) {
2141 item_name = *(out + k * nr_arrays + 8);
2142 if (!strcmp(dev_name, item_name))
2146 if (k == a->item_list_sz) {
2147 /* Graph not found: Look for first free entry */
2148 for (k = 0; k < a->item_list_sz; k++) {
2149 item_name = *(out + k * nr_arrays + 8);
2150 if (!strcmp(item_name, ""))
2153 if (k == a->item_list_sz) {
2154 /* No free graph entry: Ignore it (should never happen) */
2156 fprintf(stderr, "%s: Name=%s major=%d minor=%d\n",
2157 __FUNCTION__, dev_name, sdc->major, sdc->minor);
2162 pos = k * nr_arrays;
2163 unregistered = outsize + pos + 8;
2166 * If current device was marked as previously unregistered,
2167 * then set restart variable to TRUE so that the graph will be
2168 * discontinuous, and mark it as now registered.
2170 if (*unregistered == TRUE) {
2173 *unregistered = FALSE;
2175 item_name = *(out + pos + 8);
2176 if (!item_name[0]) {
2177 /* Save device name (WWN id or pretty name) if not already done */
2178 strncpy(item_name, dev_name, CHUNKSIZE);
2179 item_name[CHUNKSIZE - 1] = '\0';
2182 j = check_disk_reg(a, curr, !curr, i);
2184 /* This is a newly registered interface. Previous stats are zero */
2188 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2191 /* Check for min/max values */
2192 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2193 itv, spmin + pos, spmax + pos, g_fields);
2195 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2196 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2197 dkB = S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2;
2198 if (rkB < *(spmin + pos + 1)) {
2199 *(spmin + pos + 1) = rkB;
2201 if (rkB > *(spmax + pos + 1)) {
2202 *(spmax + pos + 1) = rkB;
2204 if (wkB < *(spmin + pos + 2)) {
2205 *(spmin + pos + 2) = wkB;
2207 if (wkB > *(spmax + pos + 2)) {
2208 *(spmax + pos + 2) = wkB;
2210 if (dkB < *(spmin + pos + 3)) {
2211 *(spmin + pos + 3) = dkB;
2213 if (dkB > *(spmax + pos + 3)) {
2214 *(spmax + pos + 3) = dkB;
2217 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2218 if ((xds.arqsz / 2) < *(spmin + pos + 4)) {
2219 *(spmin + pos + 4) = xds.arqsz / 2;
2221 if ((xds.arqsz / 2) > *(spmax + pos + 4)) {
2222 *(spmax + pos + 4) = xds.arqsz / 2;
2224 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2225 if (aqusz < *(spmin + pos + 5)) {
2226 *(spmin + pos + 5) = aqusz;
2228 if (aqusz > *(spmax + pos + 5)) {
2229 *(spmax + pos + 5) = aqusz;
2231 if (xds.await < *(spmin + pos + 6)) {
2232 *(spmin + pos + 6) = xds.await;
2234 if (xds.await > *(spmax + pos + 6)) {
2235 *(spmax + pos + 6) = xds.await;
2237 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2238 *(spmin + pos + 7) = xds.util / 10.0;
2240 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2241 *(spmax + pos + 7) = xds.util / 10.0;
2245 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2246 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2247 out + pos, outsize + pos, restart);
2249 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2250 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2251 out + pos + 1, outsize + pos + 1, restart);
2253 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2254 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2255 out + pos + 2, outsize + pos + 2, restart);
2257 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2258 S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2,
2259 out + pos + 3, outsize + pos + 3, restart);
2261 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2263 out + pos + 4, outsize + pos + 4, restart);
2265 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2267 out + pos + 5, outsize + pos + 5, restart);
2269 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2271 out + pos + 6, outsize + pos + 6, restart);
2273 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2274 0.0, xds.util / 10.0,
2275 out + pos + 7, outsize + pos + 7, svg_p->dt);
2278 /* Mark devices not seen here as now unregistered */
2279 for (k = 0; k < a->item_list_sz; k++) {
2280 unregistered = outsize + k * nr_arrays + 8;
2281 if (*unregistered != FALSE) {
2282 *unregistered = TRUE;
2287 if (action & F_END) {
2290 for (i = 0; i < a->item_list_sz; i++) {
2291 /* Check if there is something to display */
2292 pos = i * nr_arrays;
2296 item_name = *(out + pos + 8);
2297 if (draw_activity_graphs(a->g_nr, g_type,
2298 title, g_title, item_name, group,
2299 spmin + pos, spmax + pos, out + pos, outsize + pos,
2300 svg_p, record_hdr, FALSE, a->id, xid)) {
2305 /* Free remaining structures */
2306 free_graphs(out, outsize, spmin, spmax);
2311 ***************************************************************************
2312 * Display network interfaces statistics in SVG.
2315 * @a Activity structure with statistics.
2316 * @curr Index in array for current sample statistics.
2317 * @action Action expected from current function.
2318 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2319 * flag indicating that a restart record has been previously
2320 * found (.@restart) and time used for the X axis origin
2322 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2323 * @record_hdr Pointer on record header of current stats sample.
2324 ***************************************************************************
2326 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2327 unsigned long long itv, struct record_header *record_hdr)
2329 struct stats_net_dev *sndc, *sndp, sndzero;
2330 int group[] = {2, 2, 3, 1};
2331 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2333 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2334 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2335 char *g_title[] = {"rxpck/s", "txpck/s",
2337 "rxcmp/s", "txcmp/s", "rxmcst/s",
2339 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2340 unsigned int local_types_nr[] = {7, 0, 0};
2341 static double *spmin, *spmax;
2343 static int *outsize;
2345 double rxkb, txkb, ifutil;
2346 int i, j, k, pos, restart, *unregistered;
2348 if (action & F_BEGIN) {
2350 * Allocate arrays (#0..7) that will contain the graphs data
2351 * and the min/max values.
2352 * Also allocate one additional array (#8) for each interface:
2353 * out + 8 will contain the interface name,
2354 * outsize + 8 will contain a positive value (TRUE) if the interface
2355 * has either still not been registered, or has been unregistered.
2357 out = allocate_graph_lines(9 * a->item_list_sz, &outsize, &spmin, &spmax);
2360 if (action & F_MAIN) {
2361 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2362 restart = svg_p->restart;
2364 * Mark previously registered interfaces as now
2365 * possibly unregistered for all graphs.
2367 for (k = 0; k < a->item_list_sz; k++) {
2368 unregistered = outsize + k * 9 + 8;
2369 if (*unregistered == FALSE) {
2370 *unregistered = MAYBE;
2374 /* For each network interfaces structure */
2375 for (i = 0; i < a->nr[curr]; i++) {
2376 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2378 if (a->item_list != NULL) {
2379 /* A list of devices has been entered on the command line */
2380 if (!search_list_item(a->item_list, sndc->interface))
2381 /* Device not found */
2385 /* Look for corresponding graph */
2386 for (k = 0; k < a->item_list_sz; k++) {
2387 item_name = *(out + k * 9 + 8);
2388 if (!strcmp(sndc->interface, item_name))
2392 if (k == a->item_list_sz) {
2393 /* Graph not found: Look for first free entry */
2394 for (k = 0; k < a->item_list_sz; k++) {
2395 item_name = *(out + k * 9 + 8);
2396 if (!strcmp(item_name, ""))
2399 if (k == a->item_list_sz) {
2400 /* No free graph entry: Ignore it (should never happen) */
2402 fprintf(stderr, "%s: Name=%s\n",
2403 __FUNCTION__, sndc->interface);
2409 unregistered = outsize + pos + 8;
2411 j = check_net_dev_reg(a, curr, !curr, i);
2413 /* This is a newly registered interface. Previous stats are zero */
2417 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2421 * If current interface was marked as previously unregistered,
2422 * then set restart variable to TRUE so that the graph will be
2423 * discontinuous, and mark it as now registered.
2425 if (*unregistered == TRUE) {
2428 *unregistered = FALSE;
2430 item_name = *(out + pos + 8);
2431 if (!item_name[0]) {
2432 /* Save network interface name (if not already done) */
2433 strncpy(item_name, sndc->interface, CHUNKSIZE);
2434 item_name[CHUNKSIZE - 1] = '\0';
2437 /* Check for min/max values */
2438 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2439 itv, spmin + pos, spmax + pos, g_fields);
2441 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2442 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2443 ifutil = compute_ifutil(sndc, rxkb, txkb);
2444 if (ifutil < *(spmin + pos + 7)) {
2445 *(spmin + pos + 7) = ifutil;
2447 if (ifutil > *(spmax + pos + 7)) {
2448 *(spmax + pos + 7) = ifutil;
2452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2453 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2454 out + pos, outsize + pos, restart);
2456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2457 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2458 out + pos + 1, outsize + pos + 1, restart);
2460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2462 out + pos + 2, outsize + pos + 2, restart);
2464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2466 out + pos + 3, outsize + pos + 3, restart);
2468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2469 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2470 out + pos + 4, outsize + pos + 4, restart);
2472 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2473 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2474 out + pos + 5, outsize + pos + 5, restart);
2476 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2477 S_VALUE(sndp->multicast, sndc->multicast, itv),
2478 out + pos + 6, outsize + pos + 6, restart);
2480 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2482 out + pos + 7, outsize + pos + 7, svg_p->dt);
2485 /* Mark interfaces not seen here as now unregistered */
2486 for (k = 0; k < a->item_list_sz; k++) {
2487 unregistered = outsize + k * 9 + 8;
2488 if (*unregistered != FALSE) {
2489 *unregistered = TRUE;
2494 if (action & F_END) {
2497 for (i = 0; i < a->item_list_sz; i++) {
2499 * Check if there is something to display.
2500 * Don't test sndc->interface because maybe the network
2501 * interface has been registered later.
2507 /* Recalculate min and max values in kB, not in B */
2508 *(spmin + pos + 2) /= 1024;
2509 *(spmax + pos + 2) /= 1024;
2510 *(spmin + pos + 3) /= 1024;
2511 *(spmax + pos + 3) /= 1024;
2513 item_name = *(out + pos + 8);
2514 if (draw_activity_graphs(a->g_nr, g_type,
2515 title, g_title, item_name, group,
2516 spmin + pos, spmax + pos, out + pos, outsize + pos,
2517 svg_p, record_hdr, FALSE, a->id, xid)) {
2522 /* Free remaining structures */
2523 free_graphs(out, outsize, spmin, spmax);
2528 ***************************************************************************
2529 * Display network interfaces errors statistics in SVG.
2532 * @a Activity structure with statistics.
2533 * @curr Index in array for current sample statistics.
2534 * @action Action expected from current function.
2535 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2536 * flag indicating that a restart record has been previously
2537 * found (.@restart) and time used for the X axis origin
2539 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2540 * @record_hdr Pointer on record header of current stats sample.
2541 ***************************************************************************
2543 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2544 unsigned long long itv, struct record_header *record_hdr)
2546 struct stats_net_edev *snedc, *snedp, snedzero;
2547 int group[] = {2, 2, 2, 3};
2548 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2550 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2551 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2552 char *g_title[] = {"rxerr/s", "txerr/s",
2553 "rxdrop/s", "txdrop/s",
2554 "rxfifo/s", "txfifo/s",
2555 "coll/s", "txcarr/s", "rxfram/s"};
2556 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2557 static double *spmin, *spmax;
2559 static int *outsize;
2561 int i, j, k, pos, restart, *unregistered;
2563 if (action & F_BEGIN) {
2565 * Allocate arrays (#0..8) that will contain the graphs data
2566 * and the min/max values.
2567 * Also allocate one additional array (#9) for each interface:
2568 * out + 9 will contain the interface name,
2569 * outsize + 9 will contain a positive value (TRUE) if the interface
2570 * has either still not been registered, or has been unregistered.
2572 out = allocate_graph_lines(10 * a->item_list_sz, &outsize, &spmin, &spmax);
2575 if (action & F_MAIN) {
2576 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2577 restart = svg_p->restart;
2579 * Mark previously registered interfaces as now
2580 * possibly unregistered for all graphs.
2582 for (k = 0; k < a->item_list_sz; k++) {
2583 unregistered = outsize + k * 10 + 9;
2584 if (*unregistered == FALSE) {
2585 *unregistered = MAYBE;
2589 /* For each network interfaces structure */
2590 for (i = 0; i < a->nr[curr]; i++) {
2591 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2592 if (!strcmp(snedc->interface, ""))
2593 /* Empty structure: This is the end of the list */
2596 if (a->item_list != NULL) {
2597 /* A list of devices has been entered on the command line */
2598 if (!search_list_item(a->item_list, snedc->interface))
2599 /* Device not found */
2603 /* Look for corresponding graph */
2604 for (k = 0; k < a->item_list_sz; k++) {
2605 item_name = *(out + k * 10 + 9);
2606 if (!strcmp(snedc->interface, item_name))
2610 if (k == a->item_list_sz) {
2611 /* Graph not found: Look for first free entry */
2612 for (k = 0; k < a->item_list_sz; k++) {
2613 item_name = *(out + k * 10 + 9);
2614 if (!strcmp(item_name, ""))
2617 if (k == a->item_list_sz) {
2618 /* No free graph entry: Ignore it (should never happen) */
2620 fprintf(stderr, "%s: Name=%s\n",
2621 __FUNCTION__, snedc->interface);
2628 unregistered = outsize + pos + 9;
2630 j = check_net_edev_reg(a, curr, !curr, i);
2632 /* This is a newly registered interface. Previous stats are zero */
2636 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2640 * If current interface was marked as previously unregistered,
2641 * then set restart variable to TRUE so that the graph will be
2642 * discontinuous, and mark it as now registered.
2644 if (*unregistered == TRUE) {
2647 *unregistered = FALSE;
2649 item_name = *(out + pos + 9);
2650 if (!item_name[0]) {
2651 /* Save network interface name (if not already done) */
2652 strncpy(item_name, snedc->interface, CHUNKSIZE);
2653 item_name[CHUNKSIZE - 1] = '\0';
2656 /* Check for min/max values */
2657 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2658 itv, spmin + pos, spmax + pos, g_fields);
2661 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2662 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2663 out + pos, outsize + pos, restart);
2665 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2666 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2667 out + pos + 1, outsize + pos + 1, restart);
2669 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2670 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2671 out + pos + 2, outsize + pos + 2, restart);
2673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2674 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2675 out + pos + 3, outsize + pos + 3, restart);
2677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2678 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2679 out + pos + 4, outsize + pos + 4, restart);
2681 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2682 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2683 out + pos + 5, outsize + pos + 5, restart);
2685 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2686 S_VALUE(snedp->collisions, snedc->collisions, itv),
2687 out + pos + 6, outsize + pos + 6, restart);
2689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2690 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2691 out + pos + 7, outsize + pos + 7, restart);
2693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2694 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2695 out + pos + 8, outsize + pos + 8, restart);
2698 /* Mark interfaces not seen here as now unregistered */
2699 for (k = 0; k < a->item_list_sz; k++) {
2700 unregistered = outsize + k * 10 + 9;
2701 if (*unregistered != FALSE) {
2702 *unregistered = TRUE;
2707 if (action & F_END) {
2710 for (i = 0; i < a->item_list_sz; i++) {
2712 * Check if there is something to display.
2713 * Don't test snedc->interface because maybe the network
2714 * interface has been registered later.
2720 item_name = *(out + pos + 9);
2721 if (draw_activity_graphs(a->g_nr, g_type,
2722 title, g_title, item_name, group,
2723 spmin + pos, spmax + pos, out + pos, outsize + pos,
2724 svg_p, record_hdr, FALSE, a->id, xid)) {
2729 /* Free remaining structures */
2730 free_graphs(out, outsize, spmin, spmax);
2735 ***************************************************************************
2736 * Display NFS client statistics in SVG.
2739 * @a Activity structure with statistics.
2740 * @curr Index in array for current sample statistics.
2741 * @action Action expected from current function.
2742 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2743 * flag indicating that a restart record has been previously
2744 * found (.@restart) and time used for the X axis origin
2746 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2747 * @record_hdr Pointer on record header of current stats sample.
2748 ***************************************************************************
2750 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2751 unsigned long long itv, struct record_header *record_hdr)
2753 struct stats_net_nfs
2754 *snnc = (struct stats_net_nfs *) a->buf[curr],
2755 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2756 int group[] = {2, 2, 2};
2757 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2758 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2759 "NFS client statistics (3)"};
2760 char *g_title[] = {"call/s", "retrans/s",
2761 "read/s", "write/s",
2762 "access/s", "getatt/s"};
2763 int g_fields[] = {0, 1, 2, 3, 4, 5};
2764 static double *spmin, *spmax;
2766 static int *outsize;
2768 if (action & F_BEGIN) {
2770 * Allocate arrays that will contain the graphs data
2771 * and the min/max values.
2773 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2776 if (action & F_MAIN) {
2777 /* Check for min/max values */
2778 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2779 itv, spmin, spmax, g_fields);
2782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2783 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2784 out, outsize, svg_p->restart);
2786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2787 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2788 out + 1, outsize + 1, svg_p->restart);
2790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2791 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2792 out + 2, outsize + 2, svg_p->restart);
2794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2795 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2796 out + 3, outsize + 3, svg_p->restart);
2798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2799 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2800 out + 4, outsize + 4, svg_p->restart);
2802 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2803 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2804 out + 5, outsize + 5, svg_p->restart);
2807 if (action & F_END) {
2808 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2809 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2811 /* Free remaining structures */
2812 free_graphs(out, outsize, spmin, spmax);
2817 ***************************************************************************
2818 * Display NFS server statistics in SVG.
2821 * @a Activity structure with statistics.
2822 * @curr Index in array for current sample statistics.
2823 * @action Action expected from current function.
2824 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2825 * flag indicating that a restart record has been previously
2826 * found (.@restart) and time used for the X axis origin
2828 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2829 * @record_hdr Pointer on record header of current stats sample.
2830 ***************************************************************************
2832 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2833 unsigned long long itv, struct record_header *record_hdr)
2835 struct stats_net_nfsd
2836 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2837 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2838 int group[] = {2, 3, 2, 2, 2};
2839 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2840 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2841 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2842 "NFS server statistics (3)", "NFS server statistics (4)",
2843 "NFS server statistics (5)"};
2844 char *g_title[] = {"scall/s", "badcall/s",
2845 "packet/s", "udp/s", "tcp/s",
2847 "sread/s", "swrite/s",
2848 "saccess/s", "sgetatt/s"};
2849 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2850 static double *spmin, *spmax;
2852 static int *outsize;
2854 if (action & F_BEGIN) {
2856 * Allocate arrays that will contain the graphs data
2857 * and the min/max values.
2859 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2862 if (action & F_MAIN) {
2863 /* Check for min/max values */
2864 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2865 itv, spmin, spmax, g_fields);
2868 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2869 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2870 out, outsize, svg_p->restart);
2872 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2873 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2874 out + 1, outsize + 1, svg_p->restart);
2876 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2877 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2878 out + 2, outsize + 2, svg_p->restart);
2880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2881 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2882 out + 3, outsize + 3, svg_p->restart);
2884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2885 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2886 out + 4, outsize + 4, svg_p->restart);
2888 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2889 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2890 out + 5, outsize + 5, svg_p->restart);
2892 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2893 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2894 out + 6, outsize + 6, svg_p->restart);
2896 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2897 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2898 out + 7, outsize + 7, svg_p->restart);
2900 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2901 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2902 out + 8, outsize + 8, svg_p->restart);
2904 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2905 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2906 out + 9, outsize + 9, svg_p->restart);
2908 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2909 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2910 out + 10, outsize + 10, svg_p->restart);
2913 if (action & F_END) {
2914 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2915 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2917 /* Free remaining structures */
2918 free_graphs(out, outsize, spmin, spmax);
2923 ***************************************************************************
2924 * Display socket statistics in SVG.
2927 * @a Activity structure with statistics.
2928 * @curr Index in array for current sample statistics.
2929 * @action Action expected from current function.
2930 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2931 * flag indicating that a restart record has been previously
2932 * found (.@restart) and time used for the X axis origin
2934 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2935 * @record_hdr Pointer on record header of current stats sample.
2936 ***************************************************************************
2938 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2939 unsigned long long itv, struct record_header *record_hdr)
2941 struct stats_net_sock
2942 *snsc = (struct stats_net_sock *) a->buf[curr];
2943 int group[] = {1, 5};
2944 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2945 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2946 char *g_title[] = {"~totsck",
2947 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2948 int g_fields[] = {0, 1, 5, 2, 3, 4};
2949 static double *spmin, *spmax;
2951 static int *outsize;
2953 if (action & F_BEGIN) {
2955 * Allocate arrays that will contain the graphs data
2956 * and the min/max values.
2958 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2961 if (action & F_MAIN) {
2962 /* Check for min/max values */
2963 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2964 itv, spmin, spmax, g_fields);
2966 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2967 (unsigned long long) snsc->sock_inuse,
2968 out, outsize, svg_p->restart);
2970 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2971 (unsigned long long) snsc->tcp_inuse,
2972 out + 1, outsize + 1, svg_p->restart);
2974 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2975 (unsigned long long) snsc->udp_inuse,
2976 out + 2, outsize + 2, svg_p->restart);
2978 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2979 (unsigned long long) snsc->raw_inuse,
2980 out + 3, outsize + 3, svg_p->restart);
2982 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2983 (unsigned long long) snsc->frag_inuse,
2984 out + 4, outsize + 4, svg_p->restart);
2986 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2987 (unsigned long long) snsc->tcp_tw,
2988 out + 5, outsize + 5, svg_p->restart);
2991 if (action & F_END) {
2992 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2993 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2995 /* Free remaining structures */
2996 free_graphs(out, outsize, spmin, spmax);
3001 ***************************************************************************
3002 * Display IPv4 traffic statistics in SVG.
3005 * @a Activity structure with statistics.
3006 * @curr Index in array for current sample statistics.
3007 * @action Action expected from current function.
3008 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3009 * flag indicating that a restart record has been previously
3010 * found (.@restart) and time used for the X axis origin
3012 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3013 * @record_hdr Pointer on record header of current stats sample.
3014 ***************************************************************************
3016 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3017 unsigned long long itv, struct record_header *record_hdr)
3020 *snic = (struct stats_net_ip *) a->buf[curr],
3021 *snip = (struct stats_net_ip *) a->buf[!curr];
3022 int group[] = {4, 2, 2};
3023 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3024 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
3025 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
3026 "asmrq/s", "asmok/s",
3027 "fragok/s", "fragcrt/s"};
3028 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3029 static double *spmin, *spmax;
3031 static int *outsize;
3033 if (action & F_BEGIN) {
3035 * Allocate arrays that will contain the graphs data
3036 * and the min/max values.
3038 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3041 if (action & F_MAIN) {
3042 /* Check for min/max values */
3043 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3044 itv, spmin, spmax, g_fields);
3047 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3048 S_VALUE(snip->InReceives, snic->InReceives, itv),
3049 out, outsize, svg_p->restart);
3051 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3052 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
3053 out + 1, outsize + 1, svg_p->restart);
3055 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3056 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
3057 out + 2, outsize + 2, svg_p->restart);
3059 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3060 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3061 out + 3, outsize + 3, svg_p->restart);
3063 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3064 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3065 out + 4, outsize + 4, svg_p->restart);
3067 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3068 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3069 out + 5, outsize + 5, svg_p->restart);
3071 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3072 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3073 out + 6, outsize + 6, svg_p->restart);
3075 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3076 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3077 out + 7, outsize + 7, svg_p->restart);
3080 if (action & F_END) {
3081 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3082 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3084 /* Free remaining structures */
3085 free_graphs(out, outsize, spmin, spmax);
3090 ***************************************************************************
3091 * Display IPv4 traffic errors statistics in SVG.
3094 * @a Activity structure with statistics.
3095 * @curr Index in array for current sample statistics.
3096 * @action Action expected from current function.
3097 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3098 * flag indicating that a restart record has been previously
3099 * found (.@restart) and time used for the X axis origin
3101 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3102 * @record_hdr Pointer on record header of current stats sample.
3103 ***************************************************************************
3105 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3106 unsigned long long itv, struct record_header *record_hdr)
3108 struct stats_net_eip
3109 *sneic = (struct stats_net_eip *) a->buf[curr],
3110 *sneip = (struct stats_net_eip *) a->buf[!curr];
3111 int group[] = {3, 2, 3};
3112 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3113 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3114 "IPv4 traffic errors statistics (3)"};
3115 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3116 "idisc/s", "odisc/s",
3117 "onort/s", "asmf/s", "fragf/s"};
3118 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3119 static double *spmin, *spmax;
3121 static int *outsize;
3123 if (action & F_BEGIN) {
3125 * Allocate arrays that will contain the graphs data
3126 * and the min/max values.
3128 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3131 if (action & F_MAIN) {
3132 /* Check for min/max values */
3133 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3134 itv, spmin, spmax, g_fields);
3137 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3138 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3139 out, outsize, svg_p->restart);
3141 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3142 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3143 out + 1, outsize + 1, svg_p->restart);
3145 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3146 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3147 out + 2, outsize + 2, svg_p->restart);
3149 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3150 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3151 out + 3, outsize + 3, svg_p->restart);
3153 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3154 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3155 out + 4, outsize + 4, svg_p->restart);
3157 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3158 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3159 out + 5, outsize + 5, svg_p->restart);
3161 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3162 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3163 out + 6, outsize + 6, svg_p->restart);
3165 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3166 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3167 out + 7, outsize + 7, svg_p->restart);
3170 if (action & F_END) {
3171 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3172 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3174 /* Free remaining structures */
3175 free_graphs(out, outsize, spmin, spmax);
3180 ***************************************************************************
3181 * Display ICMPv4 traffic statistics in SVG.
3184 * @a Activity structure with statistics.
3185 * @curr Index in array for current sample statistics.
3186 * @action Action expected from current function.
3187 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3188 * flag indicating that a restart record has been previously
3189 * found (.@restart) and time used for the X axis origin
3191 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3192 * @record_hdr Pointer on record header of current stats sample.
3193 ***************************************************************************
3195 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3196 unsigned long long itv, struct record_header *record_hdr)
3198 struct stats_net_icmp
3199 *snic = (struct stats_net_icmp *) a->buf[curr],
3200 *snip = (struct stats_net_icmp *) a->buf[!curr];
3201 int group[] = {2, 4, 4, 4};
3202 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3204 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3205 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3206 char *g_title[] = {"imsg/s", "omsg/s",
3207 "iech/s", "iechr/s", "oech/s", "oechr/s",
3208 "itm/s", "itmr/s", "otm/s", "otmr/s",
3209 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3210 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3211 static double *spmin, *spmax;
3213 static int *outsize;
3215 if (action & F_BEGIN) {
3217 * Allocate arrays that will contain the graphs data
3218 * and the min/max values.
3220 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3223 if (action & F_MAIN) {
3224 /* Check for min/max values */
3225 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3226 itv, spmin, spmax, g_fields);
3229 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3230 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3231 out, outsize, svg_p->restart);
3233 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3234 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3235 out + 1, outsize + 1, svg_p->restart);
3237 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3238 S_VALUE(snip->InEchos, snic->InEchos, itv),
3239 out + 2, outsize + 2, svg_p->restart);
3241 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3242 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3243 out + 3, outsize + 3, svg_p->restart);
3245 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3246 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3247 out + 4, outsize + 4, svg_p->restart);
3249 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3250 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3251 out + 5, outsize + 5, svg_p->restart);
3253 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3254 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3255 out + 6, outsize + 6, svg_p->restart);
3257 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3258 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3259 out + 7, outsize + 7, svg_p->restart);
3261 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3262 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3263 out + 8, outsize + 8, svg_p->restart);
3265 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3266 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3267 out + 9, outsize + 9, svg_p->restart);
3269 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3270 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3271 out + 10, outsize + 10, svg_p->restart);
3273 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3274 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3275 out + 11, outsize + 11, svg_p->restart);
3277 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3278 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3279 out + 12, outsize + 12, svg_p->restart);
3281 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3282 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3283 out + 13, outsize + 13, svg_p->restart);
3286 if (action & F_END) {
3287 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3288 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3290 /* Free remaining structures */
3291 free_graphs(out, outsize, spmin, spmax);
3296 ***************************************************************************
3297 * Display ICMPv4 traffic errors statistics in SVG.
3300 * @a Activity structure with statistics.
3301 * @curr Index in array for current sample statistics.
3302 * @action Action expected from current function.
3303 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3304 * flag indicating that a restart record has been previously
3305 * found (.@restart) and time used for the X axis origin
3307 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3308 * @record_hdr Pointer on record header of current stats sample.
3309 ***************************************************************************
3311 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3312 unsigned long long itv, struct record_header *record_hdr)
3314 struct stats_net_eicmp
3315 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3316 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3317 int group[] = {2, 2, 2, 2, 2, 2};
3318 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3319 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3320 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3321 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3322 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3323 char *g_title[] = {"ierr/s", "oerr/s",
3324 "idstunr/s", "odstunr/s",
3325 "itmex/s", "otmex/s",
3326 "iparmpb/s", "oparmpb/s",
3327 "isrcq/s", "osrcq/s",
3328 "iredir/s", "oredir/s"};
3329 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3330 static double *spmin, *spmax;
3332 static int *outsize;
3334 if (action & F_BEGIN) {
3336 * Allocate arrays that will contain the graphs data
3337 * and the min/max values.
3339 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3342 if (action & F_MAIN) {
3343 /* Check for min/max values */
3344 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3345 itv, spmin, spmax, g_fields);
3348 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3349 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3350 out, outsize, svg_p->restart);
3352 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3353 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3354 out + 1, outsize + 1, svg_p->restart);
3356 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3357 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3358 out + 2, outsize + 2, svg_p->restart);
3360 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3361 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3362 out + 3, outsize + 3, svg_p->restart);
3364 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3365 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3366 out + 4, outsize + 4, svg_p->restart);
3368 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3369 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3370 out + 5, outsize + 5, svg_p->restart);
3372 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3373 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3374 out + 6, outsize + 6, svg_p->restart);
3376 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3377 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3378 out + 7, outsize + 7, svg_p->restart);
3380 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3381 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3382 out + 8, outsize + 8, svg_p->restart);
3384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3385 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3386 out + 9, outsize + 9, svg_p->restart);
3388 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3389 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3390 out + 10, outsize + 10, svg_p->restart);
3392 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3393 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3394 out + 11, outsize + 11, svg_p->restart);
3397 if (action & F_END) {
3398 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3399 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3401 /* Free remaining structures */
3402 free_graphs(out, outsize, spmin, spmax);
3407 ***************************************************************************
3408 * Display TCPv4 traffic statistics in SVG.
3411 * @a Activity structure with statistics.
3412 * @curr Index in array for current sample statistics.
3413 * @action Action expected from current function.
3414 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3415 * flag indicating that a restart record has been previously
3416 * found (.@restart) and time used for the X axis origin
3418 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3419 * @record_hdr Pointer on record header of current stats sample.
3420 ***************************************************************************
3422 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3423 unsigned long long itv, struct record_header *record_hdr)
3425 struct stats_net_tcp
3426 *sntc = (struct stats_net_tcp *) a->buf[curr],
3427 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3428 int group[] = {2, 2};
3429 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3430 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3431 char *g_title[] = {"active/s", "passive/s",
3432 "iseg/s", "oseg/s"};
3433 int g_fields[] = {0, 1, 2, 3};
3434 static double *spmin, *spmax;
3436 static int *outsize;
3438 if (action & F_BEGIN) {
3440 * Allocate arrays that will contain the graphs data
3441 * and the min/max values.
3443 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3446 if (action & F_MAIN) {
3447 /* Check for min/max values */
3448 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3449 itv, spmin, spmax, g_fields);
3452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3453 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3454 out, outsize, svg_p->restart);
3456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3457 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3458 out + 1, outsize + 1, svg_p->restart);
3460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3461 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3462 out + 2, outsize + 2, svg_p->restart);
3464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3465 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3466 out + 3, outsize + 3, svg_p->restart);
3469 if (action & F_END) {
3470 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3471 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3473 /* Free remaining structures */
3474 free_graphs(out, outsize, spmin, spmax);
3479 ***************************************************************************
3480 * Display TCPv4 traffic errors statistics in SVG.
3483 * @a Activity structure with statistics.
3484 * @curr Index in array for current sample statistics.
3485 * @action Action expected from current function.
3486 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3487 * flag indicating that a restart record has been previously
3488 * found (.@restart) and time used for the X axis origin
3490 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3491 * @record_hdr Pointer on record header of current stats sample.
3492 ***************************************************************************
3494 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3495 unsigned long long itv, struct record_header *record_hdr)
3497 struct stats_net_etcp
3498 *snetc = (struct stats_net_etcp *) a->buf[curr],
3499 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3500 int group[] = {2, 3};
3501 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3502 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3503 char *g_title[] = {"atmptf/s", "estres/s",
3504 "retrans/s", "isegerr/s", "orsts/s"};
3505 int g_fields[] = {0, 1, 2, 3, 4};
3506 static double *spmin, *spmax;
3508 static int *outsize;
3510 if (action & F_BEGIN) {
3512 * Allocate arrays that will contain the graphs data
3513 * and the min/max values.
3515 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3518 if (action & F_MAIN) {
3519 /* Check for min/max values */
3520 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3521 itv, spmin, spmax, g_fields);
3524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3525 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3526 out, outsize, svg_p->restart);
3528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3529 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3530 out + 1, outsize + 1, svg_p->restart);
3532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3533 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3534 out + 2, outsize + 2, svg_p->restart);
3536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3537 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3538 out + 3, outsize + 3, svg_p->restart);
3540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3541 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3542 out + 4, outsize + 4, svg_p->restart);
3545 if (action & F_END) {
3546 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3547 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3549 /* Free remaining structures */
3550 free_graphs(out, outsize, spmin, spmax);
3555 ***************************************************************************
3556 * Display UDPv4 traffic statistics in SVG.
3559 * @a Activity structure with statistics.
3560 * @curr Index in array for current sample statistics.
3561 * @action Action expected from current function.
3562 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3563 * flag indicating that a restart record has been previously
3564 * found (.@restart) and time used for the X axis origin
3566 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3567 * @record_hdr Pointer on record header of current stats sample.
3568 ***************************************************************************
3570 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3571 unsigned long long itv, struct record_header *record_hdr)
3573 struct stats_net_udp
3574 *snuc = (struct stats_net_udp *) a->buf[curr],
3575 *snup = (struct stats_net_udp *) a->buf[!curr];
3576 int group[] = {2, 2};
3577 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3578 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3579 char *g_title[] = {"idgm/s", "odgm/s",
3580 "noport/s", "idgmerr/s"};
3581 int g_fields[] = {0, 1, 2, 3};
3582 static double *spmin, *spmax;
3584 static int *outsize;
3586 if (action & F_BEGIN) {
3588 * Allocate arrays that will contain the graphs data
3589 * and the min/max values.
3591 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3594 if (action & F_MAIN) {
3595 /* Check for min/max values */
3596 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3597 itv, spmin, spmax, g_fields);
3600 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3601 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3602 out, outsize, svg_p->restart);
3604 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3605 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3606 out + 1, outsize + 1, svg_p->restart);
3608 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3609 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3610 out + 2, outsize + 2, svg_p->restart);
3612 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3613 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3614 out + 3, outsize + 3, svg_p->restart);
3617 if (action & F_END) {
3618 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3619 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3621 /* Free remaining structures */
3622 free_graphs(out, outsize, spmin, spmax);
3627 ***************************************************************************
3628 * Display IPV6 socket statistics in SVG.
3631 * @a Activity structure with statistics.
3632 * @curr Index in array for current sample statistics.
3633 * @action Action expected from current function.
3634 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3635 * flag indicating that a restart record has been previously
3636 * found (.@restart) and time used for the X axis origin
3638 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3639 * @record_hdr Pointer on record header of current stats sample.
3640 ***************************************************************************
3642 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3643 unsigned long long itv, struct record_header *record_hdr)
3645 struct stats_net_sock6
3646 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3648 int g_type[] = {SVG_LINE_GRAPH};
3649 char *title[] = {"IPv6 sockets statistics"};
3650 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3651 int g_fields[] = {0, 1, 2, 3};
3652 static double *spmin, *spmax;
3654 static int *outsize;
3656 if (action & F_BEGIN) {
3658 * Allocate arrays that will contain the graphs data
3659 * and the min/max values.
3661 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3664 if (action & F_MAIN) {
3665 /* Check for min/max values */
3666 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3667 itv, spmin, spmax, g_fields);
3669 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3670 (unsigned long long) snsc->tcp6_inuse,
3671 out, outsize, svg_p->restart);
3673 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3674 (unsigned long long) snsc->udp6_inuse,
3675 out + 1, outsize + 1, svg_p->restart);
3677 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3678 (unsigned long long) snsc->raw6_inuse,
3679 out + 2, outsize + 2, svg_p->restart);
3681 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3682 (unsigned long long) snsc->frag6_inuse,
3683 out + 3, outsize + 3, svg_p->restart);
3686 if (action & F_END) {
3687 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3688 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3690 /* Free remaining structures */
3691 free_graphs(out, outsize, spmin, spmax);
3696 ***************************************************************************
3697 * Display IPv6 traffic statistics in SVG.
3700 * @a Activity structure with statistics.
3701 * @curr Index in array for current sample statistics.
3702 * @action Action expected from current function.
3703 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3704 * flag indicating that a restart record has been previously
3705 * found (.@restart) and time used for the X axis origin
3707 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3708 * @record_hdr Pointer on record header of current stats sample.
3709 ***************************************************************************
3711 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3712 unsigned long long itv, struct record_header *record_hdr)
3714 struct stats_net_ip6
3715 *snic = (struct stats_net_ip6 *) a->buf[curr],
3716 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3717 int group[] = {4, 2, 2, 2};
3718 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3720 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3721 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3722 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3723 "asmrq6/s", "asmok6/s",
3724 "imcpck6/s", "omcpck6/s",
3725 "fragok6/s", "fragcr6/s"};
3726 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3727 static double *spmin, *spmax;
3729 static int *outsize;
3731 if (action & F_BEGIN) {
3733 * Allocate arrays that will contain the graphs data
3734 * and the min/max values.
3736 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3739 if (action & F_MAIN) {
3740 /* Check for min/max values */
3741 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3742 itv, spmin, spmax, g_fields);
3745 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3746 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3747 out, outsize, svg_p->restart);
3749 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3750 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3751 out + 1, outsize + 1, svg_p->restart);
3753 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3754 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3755 out + 2, outsize + 2, svg_p->restart);
3757 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3758 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3759 out + 3, outsize + 3, svg_p->restart);
3761 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3762 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3763 out + 4, outsize + 4, svg_p->restart);
3765 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3766 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3767 out + 5, outsize + 5, svg_p->restart);
3769 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3770 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3771 out + 6, outsize + 6, svg_p->restart);
3773 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3774 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3775 out + 7, outsize + 7, svg_p->restart);
3777 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3778 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3779 out + 8, outsize + 8, svg_p->restart);
3781 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3782 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3783 out + 9, outsize + 9, svg_p->restart);
3786 if (action & F_END) {
3787 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3788 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3790 /* Free remaining structures */
3791 free_graphs(out, outsize, spmin, spmax);
3796 ***************************************************************************
3797 * Display IPv6 traffic errors statistics in SVG.
3800 * @a Activity structure with statistics.
3801 * @curr Index in array for current sample statistics.
3802 * @action Action expected from current function.
3803 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3804 * flag indicating that a restart record has been previously
3805 * found (.@restart) and time used for the X axis origin
3807 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3808 * @record_hdr Pointer on record header of current stats sample.
3809 ***************************************************************************
3811 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3812 unsigned long long itv, struct record_header *record_hdr)
3814 struct stats_net_eip6
3815 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3816 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3817 int group[] = {4, 2, 2, 3};
3818 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3820 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3821 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3822 "IPv6 traffic errors statistics (5)"};
3823 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3824 "idisc6/s", "odisc6/s",
3825 "inort6/s", "onort6/s",
3826 "asmf6/s", "fragf6/s", "itrpck6/s"};
3827 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3828 static double *spmin, *spmax;
3830 static int *outsize;
3832 if (action & F_BEGIN) {
3834 * Allocate arrays that will contain the graphs data
3835 * and the min/max values.
3837 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3840 if (action & F_MAIN) {
3841 /* Check for min/max values */
3842 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3843 itv, spmin, spmax, g_fields);
3846 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3847 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3848 out, outsize, svg_p->restart);
3850 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3851 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3852 out + 1, outsize + 1, svg_p->restart);
3854 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3855 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3856 out + 2, outsize + 2, svg_p->restart);
3858 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3859 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3860 out + 3, outsize + 3, svg_p->restart);
3862 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3863 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3864 out + 4, outsize + 4, svg_p->restart);
3866 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3867 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3868 out + 5, outsize + 5, svg_p->restart);
3870 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3871 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3872 out + 6, outsize + 6, svg_p->restart);
3874 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3875 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3876 out + 7, outsize + 7, svg_p->restart);
3878 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3879 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3880 out + 8, outsize + 8, svg_p->restart);
3882 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3883 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3884 out + 9, outsize + 9, svg_p->restart);
3886 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3887 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3888 out + 10, outsize + 10, svg_p->restart);
3891 if (action & F_END) {
3892 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3893 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3895 /* Free remaining structures */
3896 free_graphs(out, outsize, spmin, spmax);
3901 ***************************************************************************
3902 * Display ICMPv6 traffic statistics in SVG.
3905 * @a Activity structure with statistics.
3906 * @curr Index in array for current sample statistics.
3907 * @action Action expected from current function.
3908 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3909 * flag indicating that a restart record has been previously
3910 * found (.@restart) and time used for the X axis origin
3912 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3913 * @record_hdr Pointer on record header of current stats sample.
3914 ***************************************************************************
3916 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3917 unsigned long long itv, struct record_header *record_hdr)
3919 struct stats_net_icmp6
3920 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3921 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3922 int group[] = {2, 3, 5, 3, 4};
3923 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3924 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3925 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3926 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3927 "ICMPv6 traffic statistics (5)"};
3928 char *g_title[] = {"imsg6/s", "omsg6/s",
3929 "iech6/s", "iechr6/s", "oechr6/s",
3930 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3931 "irtsol6/s", "ortsol6/s", "irtad6/s",
3932 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3933 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3934 static double *spmin, *spmax;
3936 static int *outsize;
3938 if (action & F_BEGIN) {
3940 * Allocate arrays that will contain the graphs data
3941 * and the min/max values.
3943 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3946 if (action & F_MAIN) {
3947 /* Check for min/max values */
3948 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3949 itv, spmin, spmax, g_fields);
3952 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3953 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3954 out, outsize, svg_p->restart);
3956 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3957 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3958 out + 1, outsize + 1, svg_p->restart);
3960 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3961 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3962 out + 2, outsize + 2, svg_p->restart);
3964 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3965 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3966 out + 3, outsize + 3, svg_p->restart);
3968 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3969 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3970 out + 4, outsize + 4, svg_p->restart);
3972 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3973 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3974 out + 5, outsize + 5, svg_p->restart);
3976 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3977 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3978 out + 6, outsize + 6, svg_p->restart);
3980 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3981 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3982 out + 7, outsize + 7, svg_p->restart);
3984 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3985 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3986 out + 8, outsize + 8, svg_p->restart);
3988 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3989 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3990 out + 9, outsize + 9, svg_p->restart);
3992 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3993 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3994 out + 10, outsize + 10, svg_p->restart);
3996 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3997 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3998 out + 11, outsize + 11, svg_p->restart);
4000 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4001 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
4002 out + 12, outsize + 12, svg_p->restart);
4004 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4005 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
4006 out + 13, outsize + 13, svg_p->restart);
4008 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4009 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
4010 out + 14, outsize + 14, svg_p->restart);
4012 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4013 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
4014 out + 15, outsize + 15, svg_p->restart);
4016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4017 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
4018 out + 16, outsize + 16, svg_p->restart);
4021 if (action & F_END) {
4022 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4023 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4025 /* Free remaining structures */
4026 free_graphs(out, outsize, spmin, spmax);
4031 ***************************************************************************
4032 * Display ICMPv6 traffic errors statistics in SVG.
4035 * @a Activity structure with statistics.
4036 * @curr Index in array for current sample statistics.
4037 * @action Action expected from current function.
4038 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4039 * flag indicating that a restart record has been previously
4040 * found (.@restart) and time used for the X axis origin
4042 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4043 * @record_hdr Pointer on record header of current stats sample.
4044 ***************************************************************************
4046 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4047 unsigned long long itv, struct record_header *record_hdr)
4049 struct stats_net_eicmp6
4050 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
4051 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
4052 int group[] = {1, 2, 2, 2, 2, 2};
4053 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4054 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4055 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
4056 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
4057 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
4058 char *g_title[] = {"ierr6/s",
4059 "idtunr6/s", "odtunr6/s",
4060 "itmex6/s", "otmex6/s",
4061 "iprmpb6/s", "oprmpb6/s",
4062 "iredir6/s", "oredir6/s",
4063 "ipck2b6/s", "opck2b6/s"};
4064 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4065 static double *spmin, *spmax;
4067 static int *outsize;
4069 if (action & F_BEGIN) {
4071 * Allocate arrays that will contain the graphs data
4072 * and the min/max values.
4074 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4077 if (action & F_MAIN) {
4078 /* Check for min/max values */
4079 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4080 itv, spmin, spmax, g_fields);
4083 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4084 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4085 out, outsize, svg_p->restart);
4087 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4088 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4089 out + 1, outsize + 1, svg_p->restart);
4091 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4092 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4093 out + 2, outsize + 2, svg_p->restart);
4095 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4096 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4097 out + 3, outsize + 3, svg_p->restart);
4099 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4100 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4101 out + 4, outsize + 4, svg_p->restart);
4103 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4104 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4105 out + 5, outsize + 5, svg_p->restart);
4107 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4108 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4109 out + 6, outsize + 6, svg_p->restart);
4111 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4112 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4113 out + 7, outsize + 7, svg_p->restart);
4115 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4116 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4117 out + 8, outsize + 8, svg_p->restart);
4119 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4120 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4121 out + 9, outsize + 9, svg_p->restart);
4123 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4124 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4125 out + 10, outsize + 10, svg_p->restart);
4128 if (action & F_END) {
4129 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4130 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4132 /* Free remaining structures */
4133 free_graphs(out, outsize, spmin, spmax);
4138 ***************************************************************************
4139 * Display UDPv6 traffic statistics in SVG.
4142 * @a Activity structure with statistics.
4143 * @curr Index in array for current sample statistics.
4144 * @action Action expected from current function.
4145 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4146 * flag indicating that a restart record has been previously
4147 * found (.@restart) and time used for the X axis origin
4149 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4150 * @record_hdr Pointer on record header of current stats sample.
4151 ***************************************************************************
4153 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4154 unsigned long long itv, struct record_header *record_hdr)
4156 struct stats_net_udp6
4157 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4158 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4159 int group[] = {2, 2};
4160 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4161 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4162 char *g_title[] = {"idgm6/s", "odgm6/s",
4163 "noport6/s", "idgmer6/s"};
4164 int g_fields[] = {0, 1, 2, 3};
4165 static double *spmin, *spmax;
4167 static int *outsize;
4169 if (action & F_BEGIN) {
4171 * Allocate arrays that will contain the graphs data
4172 * and the min/max values.
4174 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4177 if (action & F_MAIN) {
4178 /* Check for min/max values */
4179 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4180 itv, spmin, spmax, g_fields);
4183 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4184 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4185 out, outsize, svg_p->restart);
4187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4188 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4189 out + 1, outsize + 1, svg_p->restart);
4191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4192 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4193 out + 2, outsize + 2, svg_p->restart);
4195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4196 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4197 out + 3, outsize + 3, svg_p->restart);
4200 if (action & F_END) {
4201 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4202 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4204 /* Free remaining structures */
4205 free_graphs(out, outsize, spmin, spmax);
4210 ***************************************************************************
4211 * Display CPU frequency statistics in SVG.
4214 * @a Activity structure with statistics.
4215 * @curr Index in array for current sample statistics.
4216 * @action Action expected from current function.
4217 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4218 * flag indicating that a restart record has been previously
4219 * found (.@restart) and time used for the X axis origin
4221 * @itv Interval of time in 1/100th of a second (unused here).
4222 * @record_hdr Pointer on record header of current stats sample.
4223 ***************************************************************************
4225 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4226 unsigned long long itv, struct record_header *record_hdr)
4228 struct stats_pwr_cpufreq *spc, *spp;
4230 int g_type[] = {SVG_LINE_GRAPH};
4231 char *title[] = {"CPU clock frequency"};
4232 char *g_title[] = {"MHz"};
4233 static double *spmin, *spmax;
4235 static int *outsize;
4239 if (action & F_BEGIN) {
4241 * Allocate arrays that will contain the graphs data
4242 * and the min/max values.
4244 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4247 if (action & F_MAIN) {
4249 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4251 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4252 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4254 /* Should current CPU (including CPU "all") be displayed? */
4255 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4260 * Note: Don't skip offline CPU here as it is needed
4261 * to make the graph go though 0.
4265 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4266 ((double) spp->cpufreq) / 100,
4267 ((double) spc->cpufreq) / 100,
4268 out + i, outsize + i, svg_p->restart, svg_p->dt,
4269 spmin + i, spmax + i);
4273 if (action & F_END) {
4276 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
4278 /* Should current CPU (including CPU "all") be displayed? */
4279 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4284 /* This is CPU "all" */
4285 strcpy(item_name, "all");
4289 * If the maximum frequency reached by the CPU is 0, then
4290 * the CPU has been offline on the whole period.
4291 * => Don't display it.
4293 if (*(spmax + i) == 0)
4296 sprintf(item_name, "%d", i - 1);
4299 if (draw_activity_graphs(a->g_nr, g_type,
4300 title, g_title, item_name, group,
4301 spmin + i, spmax + i, out + i, outsize + i,
4302 svg_p, record_hdr, i, a->id, xid)) {
4307 /* Free remaining structures */
4308 free_graphs(out, outsize, spmin, spmax);
4313 ***************************************************************************
4314 * Display fan statistics in SVG.
4317 * @a Activity structure with statistics.
4318 * @curr Index in array for current sample statistics.
4319 * @action Action expected from current function.
4320 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4321 * flag indicating that a restart record has been previously
4322 * found (.@restart) and time used for the X axis origin
4324 * @itv Interval of time in 1/100th of a second (unused here).
4325 * @record_hdr Pointer on record header of current stats sample.
4326 ***************************************************************************
4328 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4329 unsigned long long itv, struct record_header *record_hdr)
4331 struct stats_pwr_fan *spc, *spp;
4333 int g_type[] = {SVG_LINE_GRAPH};
4334 char *title[] = {"Fans speed"};
4335 char *g_title[] = {"~rpm"};
4336 static double *spmin, *spmax;
4338 static int *outsize;
4339 char item_name[MAX_SENSORS_DEV_LEN + 8];
4342 if (action & F_BEGIN) {
4344 * Allocate arrays that will contain the graphs data
4345 * and the min/max values.
4347 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4350 if (action & F_MAIN) {
4352 for (i = 0; i < a->nr[curr]; i++) {
4354 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4355 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4358 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4361 out + i, outsize + i, svg_p->restart, svg_p->dt,
4362 spmin + i, spmax + i);
4366 if (action & F_END) {
4369 for (i = 0; i < a->item_list_sz; i++) {
4371 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4373 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4374 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4376 if (draw_activity_graphs(a->g_nr, g_type,
4377 title, g_title, item_name, group,
4378 spmin + i, spmax + i, out + i, outsize + i,
4379 svg_p, record_hdr, FALSE, a->id, xid)) {
4384 /* Free remaining structures */
4385 free_graphs(out, outsize, spmin, spmax);
4390 ***************************************************************************
4391 * Display temperature statistics in SVG.
4394 * @a Activity structure with statistics.
4395 * @curr Index in array for current sample statistics.
4396 * @action Action expected from current function.
4397 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4398 * flag indicating that a restart record has been previously
4399 * found (.@restart) and time used for the X axis origin
4401 * @itv Interval of time in 1/100th of a second (unused here).
4402 * @record_hdr Pointer on record header of current stats sample.
4403 ***************************************************************************
4405 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4406 unsigned long long itv, struct record_header *record_hdr)
4408 struct stats_pwr_temp *spc;
4409 int group[] = {1, 1};
4410 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4411 char *title[] = {"Devices temperature (1)",
4412 "Devices temperature (2)"};
4413 char *g_title[] = {"~degC",
4415 static double *spmin, *spmax;
4417 static int *outsize;
4418 char item_name[MAX_SENSORS_DEV_LEN + 8];
4422 if (action & F_BEGIN) {
4424 * Allocate arrays that will contain the graphs data
4425 * and the min/max values.
4427 out = allocate_graph_lines(2 * a->item_list_sz, &outsize, &spmin, &spmax);
4430 if (action & F_MAIN) {
4431 /* For each temperature sensor */
4432 for (i = 0; i < a->nr[curr]; i++) {
4434 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4436 /* Look for min/max values */
4437 if (spc->temp < *(spmin + 2 * i)) {
4438 *(spmin + 2 * i) = spc->temp;
4440 if (spc->temp > *(spmax + 2 * i)) {
4441 *(spmax + 2 * i) = spc->temp;
4443 tval = (spc->temp_max - spc->temp_min) ?
4444 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4446 if (tval < *(spmin + 2 * i + 1)) {
4447 *(spmin + 2 * i + 1) = tval;
4449 if (tval > *(spmax + 2 * i + 1)) {
4450 *(spmax + 2 * i + 1) = tval;
4454 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4456 out + 2 * i, outsize + 2 * i, svg_p->restart);
4458 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4460 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4464 if (action & F_END) {
4467 for (i = 0; i < a->item_list_sz; i++) {
4469 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4471 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4472 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4474 if (draw_activity_graphs(a->g_nr, g_type,
4475 title, g_title, item_name, group,
4476 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4477 svg_p, record_hdr, FALSE, a->id, xid)) {
4482 /* Free remaining structures */
4483 free_graphs(out, outsize, spmin, spmax);
4488 ***************************************************************************
4489 * Display voltage inputs statistics in SVG.
4492 * @a Activity structure with statistics.
4493 * @curr Index in array for current sample statistics.
4494 * @action Action expected from current function.
4495 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4496 * flag indicating that a restart record has been previously
4497 * found (.@restart) and time used for the X axis origin
4499 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4500 * @record_hdr Pointer on record header of current stats sample.
4501 ***************************************************************************
4503 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4504 unsigned long long itv, struct record_header *record_hdr)
4506 struct stats_pwr_in *spc;
4507 int group[] = {1, 1};
4508 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4509 char *title[] = {"Voltage inputs statistics (1)",
4510 "Voltage inputs statistics (2)"};
4511 char *g_title[] = {"inV",
4513 static double *spmin, *spmax;
4515 static int *outsize;
4516 char item_name[MAX_SENSORS_DEV_LEN + 8];
4520 if (action & F_BEGIN) {
4522 * Allocate arrays that will contain the graphs data
4523 * and the min/max values.
4525 out = allocate_graph_lines(2 * a->item_list_sz, &outsize, &spmin, &spmax);
4528 if (action & F_MAIN) {
4529 /* For each voltage input sensor */
4530 for (i = 0; i < a->nr[curr]; i++) {
4532 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4534 /* Look for min/max values */
4535 if (spc->in < *(spmin + 2 * i)) {
4536 *(spmin + 2 * i) = spc->in;
4538 if (spc->in > *(spmax + 2 * i)) {
4539 *(spmax + 2 * i) = spc->in;
4541 tval = (spc->in_max - spc->in_min) ?
4542 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4544 if (tval < *(spmin + 2 * i + 1)) {
4545 *(spmin + 2 * i + 1) = tval;
4547 if (tval > *(spmax + 2 * i + 1)) {
4548 *(spmax + 2 * i + 1) = tval;
4552 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4554 out + 2 * i, outsize + 2 * i, svg_p->restart);
4556 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4558 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4562 if (action & F_END) {
4565 for (i = 0; i < a->item_list_sz; i++) {
4567 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4569 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4570 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4572 if (draw_activity_graphs(a->g_nr, g_type,
4573 title, g_title, item_name, group,
4574 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4575 svg_p, record_hdr, FALSE, a->id, xid)) {
4580 /* Free remaining structures */
4581 free_graphs(out, outsize, spmin, spmax);
4586 ***************************************************************************
4587 * Display huge pages statistics in SVG.
4590 * @a Activity structure with statistics.
4591 * @curr Index in array for current sample statistics.
4592 * @action Action expected from current function.
4593 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4594 * flag indicating that a restart record has been previously
4595 * found (.@restart) and time used for the X axis origin
4597 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4598 * @record_hdr Pointer on record header of current stats sample.
4599 ***************************************************************************
4601 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4602 unsigned long long itv, struct record_header *record_hdr)
4605 *smc = (struct stats_huge *) a->buf[curr];
4606 int group[] = {4, 1};
4607 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4608 char *title[] = {"Huge pages utilization (1)",
4609 "Huge pages utilization (2)"};
4610 char *g_title[] = {"~kbhugfree", "~kbhugused", "~kbhugrsvd", "~kbhugsurp",
4612 int g_fields[] = {0, 5, 2, 3};
4613 static double *spmin, *spmax;
4615 static int *outsize;
4618 if (action & F_BEGIN) {
4620 * Allocate arrays that will contain the graphs data
4621 * and the min/max values.
4622 * Allocate one additional array (#5) to save min/max
4623 * values for tlhkb (unused).
4625 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
4628 if (action & F_MAIN) {
4629 /* Check for min/max values */
4630 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
4631 itv, spmin, spmax, g_fields);
4633 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4634 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4636 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4637 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4639 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4640 if (tval < *(spmin + 4)) {
4641 *(spmin + 4) = tval;
4643 if (tval > *(spmax + 4)) {
4644 *(spmax + 4) = tval;
4648 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4649 (unsigned long long) smc->frhkb,
4650 out, outsize, svg_p->restart);
4652 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4653 (unsigned long long) smc->tlhkb - smc->frhkb,
4654 out + 1, outsize + 1, svg_p->restart);
4656 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4657 (unsigned long long) smc->rsvdhkb,
4658 out + 2, outsize + 2, svg_p->restart);
4660 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4661 (unsigned long long) smc->surphkb,
4662 out + 3, outsize + 3, svg_p->restart);
4664 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4666 out + 4, outsize + 4, svg_p->dt);
4669 if (action & F_END) {
4670 draw_activity_graphs(a->g_nr, g_type,
4671 title, g_title, NULL, group,
4672 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4674 /* Free remaining structures */
4675 free_graphs(out, outsize, spmin, spmax);
4680 ***************************************************************************
4681 * Display filesystem statistics in SVG.
4684 * @a Activity structure with statistics.
4685 * @curr Index in array for current sample statistics.
4686 * @action Action expected from current function.
4687 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4688 * flag indicating that a restart record has been previously
4689 * found (.@restart) and time used for the X axis origin
4691 * @itv Interval of time in 1/100th of a second (unused here).
4692 * @record_hdr Pointer on record header of current stats sample.
4693 ***************************************************************************
4695 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4696 unsigned long long itv, struct record_header *record_hdr)
4698 struct stats_filesystem *sfc, *sfp;
4699 int group[] = {2, 2, 2, 1};
4700 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4701 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4702 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4703 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4704 char *g_title[] = {"~MBfsfree", "~MBfsused",
4705 "%ufsused", "%fsused",
4706 "Ifree/1000", "Iused/1000",
4708 static double *spmin, *spmax;
4710 static int *outsize;
4713 int i, k, pos, restart;
4715 if (action & F_BEGIN) {
4717 * Allocate arrays (#0..6) that will contain the graphs data
4718 * and the min/max values.
4719 * Also allocate two additional arrays (#7..8) for each filesystem:
4720 * out + 7 will contain the filesystem name,
4721 * out + 8 will contain the mount point.
4723 out = allocate_graph_lines(9 * a->item_list_sz, &outsize, &spmin, &spmax);
4726 if (action & F_MAIN) {
4727 /* For each filesystem structure */
4728 for (i = 0; i < a->nr[curr]; i++) {
4729 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4731 if (a->item_list != NULL) {
4732 /* A list of devices has been entered on the command line */
4733 if (!search_list_item(a->item_list,
4734 DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name))
4735 /* Device not found */
4739 /* Look for corresponding graph */
4740 for (k = 0; k < a->item_list_sz; k++) {
4741 item_name = *(out + k * 9 + 7);
4742 if (!strcmp(sfc->fs_name, item_name))
4747 if (k == a->item_list_sz) {
4748 /* Graph not found: Look for first free entry */
4749 for (k = 0; k < a->item_list_sz; k++) {
4750 item_name = *(out + k * 9 + 7);
4751 if (!strcmp(item_name, ""))
4754 if (k == a->item_list_sz) {
4755 /* No free graph entry: Ignore it (should never happen) */
4757 fprintf(stderr, "%s: Name=%s\n",
4758 __FUNCTION__, sfc->fs_name);
4766 item_name = *(out + pos + 7);
4767 if (!item_name[0]) {
4768 /* Save filesystem name and mount point (if not already done) */
4769 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4770 item_name[CHUNKSIZE - 1] = '\0';
4771 item_name = *(out + pos + 8);
4772 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4773 item_name[CHUNKSIZE - 1] = '\0';
4777 for (k = 0; k < a->nr[!curr]; k++) {
4778 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4779 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4780 /* Filesystem found in previous sample */
4781 restart = svg_p->restart;
4785 /* Check for min/max values */
4787 /* Compute fsfree min/max values */
4788 tval = (double) sfc->f_bfree;
4789 if (tval > *(spmax + pos)) {
4790 *(spmax + pos) = tval;
4792 if (tval < *(spmin + pos)) {
4793 *(spmin + pos) = tval;
4795 /* Compute fsused min/max values */
4796 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4797 if (tval > *(spmax + pos + 1)) {
4798 *(spmax + pos + 1) = tval;
4800 if (tval < *(spmin + pos + 1)) {
4801 *(spmin + pos + 1) = tval;
4803 /* Compute %ufsused min/max values */
4804 tval = sfc->f_blocks ?
4805 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4806 if (tval > *(spmax + pos + 2)) {
4807 *(spmax + pos + 2) = tval;
4809 if (tval < *(spmin + pos + 2)) {
4810 *(spmin + pos + 2) = tval;
4812 /* Compute %fsused min/max values */
4813 tval = sfc->f_blocks ?
4814 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4815 if (tval > *(spmax + pos + 3)) {
4816 *(spmax + pos + 3) = tval;
4818 if (tval < *(spmin + pos + 3)) {
4819 *(spmin + pos + 3) = tval;
4821 /* Compute Ifree min/max values */
4822 tval = (double) sfc->f_ffree;
4823 if (tval > *(spmax + pos + 4)) {
4824 *(spmax + pos + 4) = tval;
4826 if (tval < *(spmin + pos + 4)) {
4827 *(spmin + pos + 4) = tval;
4829 /* Compute Iused min/max values */
4830 tval = (double) (sfc->f_files - sfc->f_ffree);
4831 if (tval > *(spmax + pos + 5)) {
4832 *(spmax + pos + 5) = tval;
4834 if (tval < *(spmin + pos + 5)) {
4835 *(spmin + pos + 5) = tval;
4837 /* Compute %Iused min/max values */
4838 tval = sfc->f_files ?
4839 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4840 if (tval > *(spmax + pos + 6)) {
4841 *(spmax + pos + 6) = tval;
4843 if (tval < *(spmin + pos + 6)) {
4844 *(spmin + pos + 6) = tval;
4848 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4849 (double) sfc->f_bfree / 1024 / 1024,
4850 out + pos, outsize + pos, restart);
4852 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4853 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4854 out + pos + 1, outsize + pos + 1, restart);
4856 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4859 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4860 out + pos + 2, outsize + pos + 2, svg_p->dt);
4862 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4865 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4866 out + pos + 3, outsize + pos + 3, svg_p->dt);
4868 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4869 ((double) sfc->f_ffree) / 1000,
4870 out + pos + 4, outsize + pos + 4, restart);
4872 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4873 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4874 out + pos + 5, outsize + pos + 5, restart);
4876 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4879 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4880 out + pos + 6, outsize + pos + 6, svg_p->dt);
4884 if (action & F_END) {
4887 for (i = 0; i < a->item_list_sz; i++) {
4889 /* Check if there is something to display */
4894 /* Conversion B -> MB and inodes/1000 */
4895 for (k = 0; k < 2; k++) {
4896 *(spmin + pos + k) /= (1024 * 1024);
4897 *(spmax + pos + k) /= (1024 * 1024);
4898 *(spmin + pos + 4 + k) /= 1000;
4899 *(spmax + pos + 4 + k) /= 1000;
4902 if (DISPLAY_MOUNT(a->opt_flags)) {
4903 item_name = *(out + pos + 8);
4906 item_name = *(out + pos + 7);
4909 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4910 spmin + pos, spmax + pos, out + pos, outsize + pos,
4911 svg_p, record_hdr, FALSE, a->id, xid)) {
4916 /* Free remaining structures */
4917 free_graphs(out, outsize, spmin, spmax);
4922 ***************************************************************************
4923 * Display Fibre Channel HBA statistics in SVG.
4926 * @a Activity structure with statistics.
4927 * @curr Index in array for current sample statistics.
4928 * @action Action expected from current function.
4929 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4930 * flag indicating that a restart record has been previously
4931 * found (.@restart) and time used for the X axis origin
4933 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4934 * @record_hdr Pointer on record header of current stats sample.
4935 ***************************************************************************
4937 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4938 unsigned long long itv, struct record_header *record_hdr)
4940 struct stats_fchost *sfcc, *sfcp, sfczero;
4941 int group[] = {2, 2};
4942 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4943 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4944 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4945 "fch_rxw/s", "fch_txw/s"};
4946 int g_fields[] = {0, 1, 2, 3};
4947 static double *spmin, *spmax;
4949 static int *outsize;
4951 int i, j, j0, k, found, pos, restart, *unregistered;
4953 if (action & F_BEGIN) {
4955 * Allocate arrays (#0..3) that will contain the graphs data
4956 * and the min/max values.
4957 * Also allocate one additional array (#4) that will contain
4958 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4959 * has either still not been registered, or has been unregistered
4962 out = allocate_graph_lines(5 * a->item_list_sz, &outsize, &spmin, &spmax);
4965 if (action & F_MAIN) {
4966 memset(&sfczero, 0, sizeof(struct stats_fchost));
4967 restart = svg_p->restart;
4969 * Mark previously registered interfaces as now
4970 * possibly unregistered for all graphs.
4972 for (k = 0; k < a->item_list_sz; k++) {
4973 unregistered = outsize + k * 5 + 4;
4974 if (*unregistered == FALSE) {
4975 *unregistered = MAYBE;
4979 /* For each FC HBA */
4980 for (i = 0; i < a->nr[curr]; i++) {
4983 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4985 /* Look for corresponding graph */
4986 for (k = 0; k < a->item_list_sz; k++) {
4987 item_name = *(out + k * 5 + 4);
4988 if (!strcmp(sfcc->fchost_name, item_name))
4992 if (k == a->item_list_sz) {
4993 /* Graph not found: Look for first free entry */
4994 for (k = 0; k < a->item_list_sz; k++) {
4995 item_name = *(out + k * 5 + 4);
4996 if (!strcmp(item_name, ""))
4999 if (k == a->item_list_sz) {
5000 /* No free graph entry: Ignore it (should never happen) */
5002 fprintf(stderr, "%s: Name=%s\n",
5003 __FUNCTION__, sfcc->fchost_name);
5010 unregistered = outsize + pos + 4;
5012 if (a->nr[!curr] > 0) {
5013 /* Look for corresponding structure in previous iteration */
5016 if (j >= a->nr[!curr]) {
5017 j = a->nr[!curr] - 1;
5023 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
5024 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
5028 if (++j >= a->nr[!curr]) {
5036 /* This is a newly registered host */
5041 * If current interface was marked as previously unregistered,
5042 * then set restart variable to TRUE so that the graph will be
5043 * discontinuous, and mark it as now registered.
5045 if (*unregistered == TRUE) {
5048 *unregistered = FALSE;
5050 item_name = *(out + pos + 4);
5051 if (!item_name[0]) {
5052 /* Save FC HBA name */
5053 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
5054 item_name[CHUNKSIZE - 1] = '\0';
5057 /* Look for min/max values */
5058 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
5059 itv, spmin + pos, spmax + pos, g_fields);
5062 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5063 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5064 out + pos, outsize + pos, restart);
5066 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5067 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5068 out + pos + 1, outsize + pos + 1, restart);
5070 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5071 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5072 out + pos + 2, outsize + pos + 2, restart);
5074 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5075 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5076 out + pos + 3, outsize + pos + 3, restart);
5079 /* Mark interfaces not seen here as now unregistered */
5080 for (k = 0; k < a->item_list_sz; k++) {
5081 unregistered = outsize + k * 5 + 4;
5082 if (*unregistered != FALSE) {
5083 *unregistered = TRUE;
5088 if (action & F_END) {
5089 for (i = 0; i < a->item_list_sz; i++) {
5091 /* Check if there is something to display */
5096 item_name = *(out + pos + 4);
5097 draw_activity_graphs(a->g_nr, g_type,
5098 title, g_title, item_name, group,
5099 spmin + pos, spmax + pos, out + pos, outsize + pos,
5100 svg_p, record_hdr, FALSE, a->id, i);
5103 /* Free remaining structures */
5104 free_graphs(out, outsize, spmin, spmax);
5109 ***************************************************************************
5110 * Display softnet statistics in SVG.
5113 * @a Activity structure with statistics.
5114 * @curr Index in array for current sample statistics.
5115 * @action Action expected from current function.
5116 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5117 * flag indicating that a restart record has been previously
5118 * found (.@restart) and time used for the X axis origin
5120 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5121 * @record_hdr Pointer on record header of current stats sample.
5122 ***************************************************************************
5124 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5125 unsigned long long itv, struct record_header *record_hdr)
5127 struct stats_softnet *ssnc, *ssnp, ssnczero;
5128 int group[] = {2, 3};
5129 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5130 char *title[] = {"Software-based network processing statistics (1)",
5131 "Software-based network processing statistics (2)"};
5132 char *g_title[] = {"total/s", "dropd/s",
5133 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5134 int g_fields[] = {0, 1, 2, 3, 4};
5135 static double *spmin, *spmax;
5137 static int *outsize;
5139 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5140 int i, pos, restart;
5142 if (action & F_BEGIN) {
5144 * Allocate arrays that will contain the graphs data
5145 * and the min/max values.
5147 out = allocate_graph_lines(5 * a->item_list_sz, &outsize, &spmin, &spmax);
5150 if (action & F_MAIN) {
5151 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5153 /* @nr[curr] cannot normally be greater than @nr_ini */
5154 if (a->nr[curr] > a->nr_ini) {
5155 a->nr_ini = a->nr[curr];
5158 /* Compute statistics for CPU "all" */
5159 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5162 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5163 restart = svg_p->restart;
5165 /* Should current CPU (including CPU "all") be displayed? */
5166 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5170 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5171 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5173 /* Is current CPU marked offline? */
5174 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5176 * Yes and it doesn't follow a RESTART record.
5177 * To add a discontinuity in graph, we simulate
5181 if (svg_p->restart) {
5183 * CPU is offline and it follows a real
5184 * RESTART record. Ignore its current value
5185 * (no previous sample).
5192 /* Check for min/max values */
5193 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5194 itv, spmin + pos, spmax + pos, g_fields);
5197 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5198 S_VALUE(ssnp->processed, ssnc->processed, itv),
5199 out + pos, outsize + pos, restart);
5201 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5202 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5203 out + pos + 1, outsize + pos + 1, restart);
5205 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5206 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5207 out + pos + 2, outsize + pos + 2, restart);
5209 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5210 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5211 out + pos + 3, outsize + pos + 3, restart);
5213 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5214 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5215 out + pos + 4, outsize + pos + 4, restart);
5219 if (action & F_END) {
5220 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
5222 /* Should current CPU (including CPU "all") be displayed? */
5223 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5230 /* This is CPU "all" */
5231 strcpy(item_name, "all");
5234 sprintf(item_name, "%d", i - 1);
5237 draw_activity_graphs(a->g_nr, g_type,
5238 title, g_title, item_name, group,
5239 spmin + pos, spmax + pos, out + pos, outsize + pos,
5240 svg_p, record_hdr, FALSE, a->id, i);
5243 /* Free remaining structures */
5244 free_graphs(out, outsize, spmin, spmax);
5249 ***************************************************************************
5250 * Display pressure-stall CPU statistics in SVG.
5253 * @a Activity structure with statistics.
5254 * @curr Index in array for current sample statistics.
5255 * @action Action expected from current function.
5256 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5257 * flag indicating that a restart record has been previously
5258 * found (.@restart) and time used for the X axis origin
5260 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5261 * @record_hdr Pointer on record header of current stats sample.
5262 ***************************************************************************
5264 __print_funct_t svg_print_psicpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5265 unsigned long long itv, struct record_header *record_hdr)
5267 struct stats_psi_cpu
5268 *psic = (struct stats_psi_cpu *) a->buf[curr],
5269 *psip = (struct stats_psi_cpu *) a->buf[!curr];
5270 int group[] = {3, 1};
5271 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5272 char *title[] = {"CPU pressure trends (some tasks)", "CPU stall time (some tasks)"};
5273 char *g_title[] = {"%scpu-10", "%scpu-60", "%scpu-300",
5275 static double *spmin, *spmax;
5277 static int *outsize;
5280 if (action & F_BEGIN) {
5282 * Allocate arrays that will contain the graphs data
5283 * and the min/max values.
5285 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
5288 if (action & F_MAIN) {
5289 /* Check for min/max values */
5290 if (psic->some_acpu_10 > *spmax) {
5291 *spmax = psic->some_acpu_10;
5293 if (psic->some_acpu_10 < *spmin) {
5294 *spmin = psic->some_acpu_10;
5296 if (psic->some_acpu_60 > *(spmax + 1)) {
5297 *(spmax + 1) = psic->some_acpu_60;
5299 if (psic->some_acpu_60 < *(spmin + 1)) {
5300 *(spmin + 1) = psic->some_acpu_60;
5302 if (psic->some_acpu_300 > *(spmax + 2)) {
5303 *(spmax + 2) = psic->some_acpu_300;
5305 if (psic->some_acpu_300 < *(spmin + 2)) {
5306 *(spmin + 2) = psic->some_acpu_300;
5308 tval = ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv);
5309 if (tval > *(spmax + 3)) {
5310 *(spmax + 3) = tval;
5312 if (tval < *(spmin + 3)) {
5313 *(spmin + 3) = tval;
5317 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5318 (double) psic->some_acpu_10 / 100,
5319 out, outsize, svg_p->restart);
5321 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5322 (double) psic->some_acpu_60 / 100,
5323 out + 1, outsize + 1, svg_p->restart);
5325 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5326 (double) psic->some_acpu_300 / 100,
5327 out + 2, outsize + 2, svg_p->restart);
5329 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5331 ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv),
5332 out + 3, outsize + 3, svg_p->dt);
5335 if (action & F_END) {
5336 /* Fix min/max values for pressure ratios */
5337 *spmin /= 100; *spmax /= 100;
5338 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5339 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5341 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5342 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5344 /* Free remaining structures */
5345 free_graphs(out, outsize, spmin, spmax);
5350 ***************************************************************************
5351 * Display pressure-stall I/O statistics in SVG.
5354 * @a Activity structure with statistics.
5355 * @curr Index in array for current sample statistics.
5356 * @action Action expected from current function.
5357 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5358 * flag indicating that a restart record has been previously
5359 * found (.@restart) and time used for the X axis origin
5361 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5362 * @record_hdr Pointer on record header of current stats sample.
5363 ***************************************************************************
5365 __print_funct_t svg_print_psiio_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5366 unsigned long long itv, struct record_header *record_hdr)
5369 *psic = (struct stats_psi_io *) a->buf[curr],
5370 *psip = (struct stats_psi_io *) a->buf[!curr];
5371 int group[] = {3, 1, 3, 1};
5372 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5373 char *title[] = {"I/O pressure trends (some tasks)", "I/O stall time (some tasks)",
5374 "I/O pressure trends (full)", "I/O stall time (full)"};
5375 char *g_title[] = {"%sio-10", "%sio-60", "%sio-300",
5377 "%fio-10", "%fio-60", "%fio-300",
5379 static double *spmin, *spmax;
5381 static int *outsize;
5384 if (action & F_BEGIN) {
5386 * Allocate arrays that will contain the graphs data
5387 * and the min/max values.
5389 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5392 if (action & F_MAIN) {
5393 /* Check for min/max values */
5394 if (psic->some_aio_10 > *spmax) {
5395 *spmax = psic->some_aio_10;
5397 if (psic->some_aio_10 < *spmin) {
5398 *spmin = psic->some_aio_10;
5400 if (psic->some_aio_60 > *(spmax + 1)) {
5401 *(spmax + 1) = psic->some_aio_60;
5403 if (psic->some_aio_60 < *(spmin + 1)) {
5404 *(spmin + 1) = psic->some_aio_60;
5406 if (psic->some_aio_300 > *(spmax + 2)) {
5407 *(spmax + 2) = psic->some_aio_300;
5409 if (psic->some_aio_300 < *(spmin + 2)) {
5410 *(spmin + 2) = psic->some_aio_300;
5412 tval = ((double) psic->some_io_total - psip->some_io_total) / (100 * itv);
5413 if (tval > *(spmax + 3)) {
5414 *(spmax + 3) = tval;
5416 if (tval < *(spmin + 3)) {
5417 *(spmin + 3) = tval;
5420 if (psic->full_aio_10 > *(spmax + 4)) {
5421 *(spmax + 4) = psic->full_aio_10;
5423 if (psic->full_aio_10 < *(spmin + 4)) {
5424 *(spmin + 4) = psic->full_aio_10;
5426 if (psic->full_aio_60 > *(spmax + 5)) {
5427 *(spmax + 5) = psic->full_aio_60;
5429 if (psic->full_aio_60 < *(spmin + 5)) {
5430 *(spmin + 5) = psic->full_aio_60;
5432 if (psic->full_aio_300 > *(spmax + 6)) {
5433 *(spmax + 6) = psic->full_aio_300;
5435 if (psic->full_aio_300 < *(spmin + 6)) {
5436 *(spmin + 6) = psic->full_aio_300;
5438 tval = ((double) psic->full_io_total - psip->full_io_total) / (100 * itv);
5439 if (tval > *(spmax + 7)) {
5440 *(spmax + 7) = tval;
5442 if (tval < *(spmin + 7)) {
5443 *(spmin + 7) = tval;
5447 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5448 (double) psic->some_aio_10 / 100,
5449 out, outsize, svg_p->restart);
5451 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5452 (double) psic->some_aio_60 / 100,
5453 out + 1, outsize + 1, svg_p->restart);
5455 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5456 (double) psic->some_aio_300 / 100,
5457 out + 2, outsize + 2, svg_p->restart);
5459 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5461 ((double) psic->some_io_total - psip->some_io_total) / (100 * itv),
5462 out + 3, outsize + 3, svg_p->dt);
5465 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5466 (double) psic->full_aio_10 / 100,
5467 out + 4, outsize + 4, svg_p->restart);
5469 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5470 (double) psic->full_aio_60 / 100,
5471 out + 5, outsize + 5, svg_p->restart);
5473 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5474 (double) psic->full_aio_300 / 100,
5475 out + 6, outsize + 6, svg_p->restart);
5477 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5479 ((double) psic->full_io_total - psip->full_io_total) / (100 * itv),
5480 out + 7, outsize + 7, svg_p->dt);
5483 if (action & F_END) {
5484 /* Fix min/max values for pressure ratios */
5485 *spmin /= 100; *spmax /= 100;
5486 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5487 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5489 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5490 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5491 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5493 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5494 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5496 /* Free remaining structures */
5497 free_graphs(out, outsize, spmin, spmax);
5502 ***************************************************************************
5503 * Display pressure-stall memory statistics in SVG.
5506 * @a Activity structure with statistics.
5507 * @curr Index in array for current sample statistics.
5508 * @action Action expected from current function.
5509 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5510 * flag indicating that a restart record has been previously
5511 * found (.@restart) and time used for the X axis origin
5513 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5514 * @record_hdr Pointer on record header of current stats sample.
5515 ***************************************************************************
5517 __print_funct_t svg_print_psimem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5518 unsigned long long itv, struct record_header *record_hdr)
5520 struct stats_psi_mem
5521 *psic = (struct stats_psi_mem *) a->buf[curr],
5522 *psip = (struct stats_psi_mem *) a->buf[!curr];
5523 int group[] = {3, 1, 3, 1};
5524 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5525 char *title[] = {"Memory pressure trends (some tasks)", "Memory stall time (some tasks)",
5526 "Memory pressure trends (full)", "Memory stall time (full)"};
5527 char *g_title[] = {"%smem-10", "%smem-60", "%smem-300",
5529 "%fmem-10", "%fmem-60", "%fmem-300",
5531 static double *spmin, *spmax;
5533 static int *outsize;
5536 if (action & F_BEGIN) {
5538 * Allocate arrays that will contain the graphs data
5539 * and the min/max values.
5541 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5544 if (action & F_MAIN) {
5545 /* Check for min/max values */
5546 if (psic->some_amem_10 > *spmax) {
5547 *spmax = psic->some_amem_10;
5549 if (psic->some_amem_10 < *spmin) {
5550 *spmin = psic->some_amem_10;
5552 if (psic->some_amem_60 > *(spmax + 1)) {
5553 *(spmax + 1) = psic->some_amem_60;
5555 if (psic->some_amem_60 < *(spmin + 1)) {
5556 *(spmin + 1) = psic->some_amem_60;
5558 if (psic->some_amem_300 > *(spmax + 2)) {
5559 *(spmax + 2) = psic->some_amem_300;
5561 if (psic->some_amem_300 < *(spmin + 2)) {
5562 *(spmin + 2) = psic->some_amem_300;
5564 tval = ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv);
5565 if (tval > *(spmax + 3)) {
5566 *(spmax + 3) = tval;
5568 if (tval < *(spmin + 3)) {
5569 *(spmin + 3) = tval;
5572 if (psic->full_amem_10 > *(spmax + 4)) {
5573 *(spmax + 4) = psic->full_amem_10;
5575 if (psic->full_amem_10 < *(spmin + 4)) {
5576 *(spmin + 4) = psic->full_amem_10;
5578 if (psic->full_amem_60 > *(spmax + 5)) {
5579 *(spmax + 5) = psic->full_amem_60;
5581 if (psic->full_amem_60 < *(spmin + 5)) {
5582 *(spmin + 5) = psic->full_amem_60;
5584 if (psic->full_amem_300 > *(spmax + 6)) {
5585 *(spmax + 6) = psic->full_amem_300;
5587 if (psic->full_amem_300 < *(spmin + 6)) {
5588 *(spmin + 6) = psic->full_amem_300;
5590 tval = ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv);
5591 if (tval > *(spmax + 7)) {
5592 *(spmax + 7) = tval;
5594 if (tval < *(spmin + 7)) {
5595 *(spmin + 7) = tval;
5599 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5600 (double) psic->some_amem_10 / 100,
5601 out, outsize, svg_p->restart);
5603 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5604 (double) psic->some_amem_60 / 100,
5605 out + 1, outsize + 1, svg_p->restart);
5607 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5608 (double) psic->some_amem_300 / 100,
5609 out + 2, outsize + 2, svg_p->restart);
5611 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5613 ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv),
5614 out + 3, outsize + 3, svg_p->dt);
5617 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5618 (double) psic->full_amem_10 / 100,
5619 out + 4, outsize + 4, svg_p->restart);
5621 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5622 (double) psic->full_amem_60 / 100,
5623 out + 5, outsize + 5, svg_p->restart);
5625 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5626 (double) psic->full_amem_300 / 100,
5627 out + 6, outsize + 6, svg_p->restart);
5629 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5631 ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv),
5632 out + 7, outsize + 7, svg_p->dt);
5635 if (action & F_END) {
5636 /* Fix min/max values for pressure ratios */
5637 *spmin /= 100; *spmax /= 100;
5638 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5639 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5641 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5642 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5643 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5645 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5646 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
5648 /* Free remaining structures */
5649 free_graphs(out, outsize, spmin, spmax);