2 * svg_stats.c: Functions used by sadf to display statistics in SVG format.
3 * (C) 2016-2023 by Sebastien GODARD (sysstat <at> orange.fr)
5 ***************************************************************************
6 * This program is free software; you can redistribute it and/or modify it *
7 * under the terms of the GNU General Public License as published by the *
8 * Free Software Foundation; either version 2 of the License, or (at your *
9 * option) any later version. *
11 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * You should have received a copy of the GNU General Public License along *
17 * with this program; if not, write to the Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *
19 ***************************************************************************
30 #include "svg_stats.h"
35 #define _(string) gettext(string)
37 #define _(string) (string)
40 extern uint64_t flags;
43 unsigned int svg_colors[SVG_COL_PALETTE_NR][SVG_COL_PALETTE_SIZE] =
44 {{0x00cc00, 0xff00bf, 0x00ffff, 0xff0000, /* Default palette */
45 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
46 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
47 0xcc3300, 0x50040f, 0xffffbf, 0x193d55,
48 0x000000, 0xffffff, 0x202020, 0xffff00,
49 0xffff00, 0x808080, 0xa52a2a, 0xff0000},
51 {0x000000, 0x1a1aff, 0x1affb2, 0xb21aff, /* Custom color palette */
52 0x1ab2ff, 0xff1a1a, 0xffb31a, 0xb2ff1a,
53 0xefefef, 0x000000, 0x1a1aff, 0x1affb2,
54 0xb21aff, 0x1ab2ff, 0xff1a1a, 0xffb31a,
55 0xffffff, 0x000000, 0xbebebe, 0x000000,
56 0x000000, 0x000000, 0x000000, 0x000000},
58 {0x696969, 0xbebebe, 0x000000, 0xa9a9a9, /* Black & white palette */
59 0x708090, 0xc0c0c0, 0x808080, 0xd3d3d3,
60 0x909090, 0x696969, 0xbebebe, 0x000000,
61 0x000000, 0xa9a9a9, 0xc0c0c0, 0x808080,
62 0xffffff, 0x000000, 0xbebebe, 0x000000,
63 0x000000, 0x000000, 0x000000, 0x000000}};
66 ***************************************************************************
67 * Compare the values of a statistics sample with the max and min values
68 * already found in previous samples for this same activity. If some new
69 * min or max values are found, then save them.
70 * Assume values cannot be negative.
71 * The structure containing the statistics sample is composed of @llu_nr
72 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
73 * followed by @u_nr unsigned int fields.
76 * @types_nr Number of fields whose type is "long long", "long" and "int"
77 * composing the structure.
78 * @cs Pointer on current sample statistics structure.
79 * @ps Pointer on previous sample statistics structure (may be NULL).
80 * @itv Interval of time in 1/100th of a second.
81 * @spmin Array containing min values already found for this activity.
82 * @spmax Array containing max values already found for this activity.
83 * @g_fields Index in spmin/spmax arrays where extrema values for each
84 * activity metric will be saved. As a consequence spmin/spmax
85 * arrays may contain values in a different order than that of
86 * the fields in the statistics structure.
89 * @spmin Array containing the possible new min values for current activity.
90 * @spmax Array containing the possible new max values for current activity.
91 ***************************************************************************
93 void save_extrema(const 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++) {
106 if (g_fields[m] >= 0) {
108 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
112 * If no pointer on previous sample has been given
113 * then the value is not a per-second one.
115 val = (double) *lluc;
117 if (val < *(spmin + g_fields[m])) {
118 *(spmin + g_fields[m]) = val;
120 if (val > *(spmax + g_fields[m])) {
121 *(spmax + g_fields[m]) = val;
124 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
126 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
130 /* Compare unsigned long fields */
131 luc = (unsigned long *) lluc;
132 lup = (unsigned long *) llup;
133 for (i = 0; i < types_nr[1]; i++, m++) {
134 if (g_fields[m] >= 0) {
136 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
141 if (val < *(spmin + g_fields[m])) {
142 *(spmin + g_fields[m]) = val;
144 if (val > *(spmax + g_fields[m])) {
145 *(spmax + g_fields[m]) = val;
148 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
150 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
154 /* Compare unsigned int fields */
155 uc = (unsigned int *) luc;
156 up = (unsigned int *) lup;
157 for (i = 0; i < types_nr[2]; i++, m++) {
158 if (g_fields[m] >= 0) {
160 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
165 if (val < *(spmin + g_fields[m])) {
166 *(spmin + g_fields[m]) = val;
168 if (val > *(spmax + g_fields[m])) {
169 *(spmax + g_fields[m]) = val;
172 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
174 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
180 ***************************************************************************
181 * Find the min and max values of all the graphs that will be drawn in the
182 * same view. The graphs have their own min and max values in
183 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
186 * @pos Position in array for the first graph extrema value.
187 * @n Number of graphs to scan.
188 * @spmin Array containing min values for graphs.
189 * @spmax Array containing max values for graphs.
192 * @gmin Global min value found.
193 * @gmax Global max value found.
194 ***************************************************************************
196 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
197 double *gmin, double *gmax)
201 *gmin = *(spmin + pos);
202 *gmax = *(spmax + pos);
204 for (i = 1; i < n; i++) {
205 if (*(spmin + pos + i) < *gmin) {
206 *gmin = *(spmin + pos + i);
208 if (*(spmax + pos + i) > *gmax) {
209 *gmax = *(spmax + pos + i);
215 ***************************************************************************
216 * Allocate arrays used to save graphs data, min and max values.
217 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
218 * array is returned. This is equivalent to "char data[][n]" where each
219 * element is of indeterminate size and will contain the graph data (eg.
220 * << path d="M12,14 L13,16..." ... >>.
221 * The size of element data[i] is given by outsize[i].
222 * Also allocate an array to save min values (equivalent to "double spmin[n]")
223 * and an array for max values (equivalent to "double spmax[n]").
226 * @n Number of graphs to draw for current activity.
229 * @outsize Array that will contain the sizes of each element in array
230 * of chars. Equivalent to "int outsize[n]" with
231 * outsize[n] = sizeof(data[][n]).
232 * @spmin Array that will contain min values for current activity.
233 * @spmax Array that will contain max values for current activity.
236 * Pointer on array of arrays of chars that will contain the graphs data.
238 * NB: @min and @max arrays contain values in the same order as the fields
239 * in the statistics structure.
240 ***************************************************************************
242 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
249 * Allocate an array of pointers. Each of these pointers will
250 * be an array of chars.
252 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
256 /* Allocate array that will contain the size of each array of chars */
257 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
261 /* Allocate array that will contain the min value of each graph */
262 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
266 /* Allocate array that will contain the max value of each graph */
267 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
271 /* Allocate arrays of chars that will contain graphs data */
272 for (i = 0; i < n; i++) {
273 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
278 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
279 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
280 *(*spmin + i) = DBL_MAX; /* Init min and max values */
281 *(*spmax + i) = -DBL_MAX;
288 ***************************************************************************
289 * Save SVG code for current graph.
292 * @data SVG code to append to current graph definition.
293 * @out Pointer on array of chars for current graph definition.
294 * @outsize Size of array of chars for current graph definition.
297 * @out Pointer on array of chars for current graph definition that
298 * has been updated with the addition of current sample data.
299 * @outsize Array that containing the (possibly new) sizes of each
300 * element in array of chars.
301 ***************************************************************************
303 void save_svg_data(char *data, char **out, int *outsize)
309 /* Determine space left in array */
310 len = *outsize - strlen(out_p) - 1;
311 if (strlen(data) >= len) {
313 * If current array of chars doesn't have enough space left
314 * then reallocate it with CHUNKSIZE more bytes.
316 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
318 *outsize += CHUNKSIZE;
321 strncat(out_p, data, len);
325 ***************************************************************************
326 * Update line graph definition by appending current X,Y coordinates.
329 * @timetag Timestamp in seconds since the epoch for current sample
330 * stats. Will be used as X coordinate.
331 * @value Value of current sample metric. Will be used as Y coordinate.
332 * @out Pointer on array of chars for current graph definition.
333 * @outsize Size of array of chars for current graph definition.
334 * @restart Set to TRUE if a RESTART record has been read since the last
338 * @out Pointer on array of chars for current graph definition that
339 * has been updated with the addition of current sample data.
340 * @outsize Array that containing the (possibly new) sizes of each
341 * element in array of chars.
342 ***************************************************************************
344 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
349 /* Prepare additional graph definition data */
350 snprintf(data, sizeof(data), " %c%llu,%.2f", restart ? 'M' : 'L', timetag, value);
351 data[sizeof(data) - 1] = '\0';
353 save_svg_data(data, out, outsize);
357 ***************************************************************************
358 * Update line graph definition by appending current X,Y coordinates. Use
359 * (unsigned long) integer values here.
362 * @timetag Timestamp in seconds since the epoch for current sample
363 * stats. Will be used as X coordinate.
364 * @value Value of current sample metric. Will be used as Y coordinate.
365 * @out Pointer on array of chars for current graph definition.
366 * @outsize Size of array of chars for current graph definition.
367 * @restart Set to TRUE if a RESTART record has been read since the last
371 * @out Pointer on array of chars for current graph definition that
372 * has been updated with the addition of current sample data.
373 * @outsize Array that containing the (possibly new) sizes of each
374 * element in array of chars.
375 ***************************************************************************
377 void lniappend(unsigned long long timetag, unsigned long long value, char **out,
378 int *outsize, int restart)
382 /* Prepare additional graph definition data */
383 snprintf(data, sizeof(data), " %c%llu,%llu", restart ? 'M' : 'L', timetag, value);
384 data[sizeof(data) - 1] = '\0';
386 save_svg_data(data, out, outsize);
390 ***************************************************************************
391 * Update bar graph definition by adding a new rectangle.
394 * @timetag Timestamp in seconds since the epoch for current sample
395 * stats. Will be used as X coordinate.
396 * @value Value of current sample metric. Will be used as rectangle
398 * @offset Offset for Y coordinate.
399 * @out Pointer on array of chars for current graph definition.
400 * @outsize Size of array of chars for current graph definition.
401 * @dt Interval of time in seconds between current and previous
405 * @out Pointer on array of chars for current graph definition that
406 * has been updated with the addition of current sample data.
407 * @outsize Array that containing the (possibly new) sizes of each
408 * element in array of chars.
409 ***************************************************************************
411 void brappend(unsigned long long timetag, double offset, double value, char **out,
412 int *outsize, unsigned long long dt)
415 unsigned long long t = 0;
417 /* Prepare additional graph definition data */
418 if ((value == 0.0) || (dt == 0))
419 /* Don't draw a flat rectangle! */
425 snprintf(data, sizeof(data), "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
426 t, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
427 data[sizeof(data) - 1] = '\0';
429 save_svg_data(data, out, outsize);
434 ***************************************************************************
435 * Update CPU graph and min/max values for each metric.
438 * @timetag Timestamp in seconds since the epoch for current sample
439 * stats. Will be used as X coordinate.
440 * @offset Offset for Y coordinate.
441 * @value Value of current CPU metric. Will be used as rectangle
443 * @out Pointer on array of chars for current graph definition.
444 * @outsize Size of array of chars for current graph definition.
445 * @dt Interval of time in seconds between current and previous
447 * @spmin Min value already found for this CPU metric.
448 * @spmax Max value already found for this CPU metric.
451 * @offset New offset value, to use to draw next rectangle
452 * @out Pointer on array of chars for current graph definition that
453 * has been updated with the addition of current sample data.
454 * @outsize Array that containing the (possibly new) sizes of each
455 * element in array of chars.
456 ***************************************************************************
458 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
459 int *outsize, unsigned long long dt, double *spmin, double *spmax)
461 /* Save min and max values */
462 if (value < *spmin) {
465 if (value > *spmax) {
468 /* Prepare additional graph definition data */
469 brappend(timetag, *offset, value, out, outsize, dt);
475 ***************************************************************************
476 * Update rectangular graph and min/max values.
479 * @timetag Timestamp in seconds since the epoch for current sample
480 * stats. Will be used as X coordinate.
481 * @p_value Metric value for previous sample
482 * @value Metric value for current sample.
483 * @out Pointer on array of chars for current graph definition.
484 * @outsize Size of array of chars for current graph definition.
485 * @restart Set to TRUE if a RESTART record has been read since the last
487 * @dt Interval of time in seconds between current and previous
489 * @spmin Min value already found for this metric.
490 * @spmax Max value already found for this metric.
493 * @out Pointer on array of chars for current graph definition that
494 * has been updated with the addition of current sample data.
495 * @outsize Array that containing the (possibly new) sizes of each
496 * element in array of chars.
497 * @spmin Min value for this metric.
498 * @spmax Max value for this metric.
499 ***************************************************************************
501 void recappend(unsigned long long timetag, double p_value, double value, char **out,
502 int *outsize, int restart, unsigned long long dt,
503 double *spmin, double *spmax)
505 char data[512], data1[128], data2[128];
506 unsigned long long t = 0;
508 /* Save min and max values */
509 if (value < *spmin) {
512 if (value > *spmax) {
518 /* Prepare additional graph definition data */
520 snprintf(data1, sizeof(data1), " M%llu,%.2f", t, p_value);
521 data1[sizeof(data1) - 1] = '\0';
523 if (p_value != value) {
524 snprintf(data2, sizeof(data2), " L%llu,%.2f", timetag, value);
525 data2[sizeof(data2) - 1] = '\0';
527 snprintf(data, sizeof(data), "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
528 p_value != value ? data2 : "");
529 data[sizeof(data) - 1] = '\0';
531 save_svg_data(data, out, outsize);
535 ***************************************************************************
536 * Calculate 10 raised to the power of n.
539 * @n Power number to use.
542 * 10 raised to the power of n.
543 ***************************************************************************
545 unsigned int pwr10(int n)
550 for (i = 0; i < n; i++) {
558 ***************************************************************************
559 * Compute timestamp for next graduation on the X axis.
562 * @stamp Record header with timestamp for current graduation.
563 * @xpos Number of seconds between two consecutive graduations.
566 * @stamp Record header with timestamp for next graduation that will
567 * be displayed on the X axis of the graph.
568 ***************************************************************************
570 void compute_next_graduation_timestamp(struct record_header *stamp, long int xpos)
572 stamp->ust_time += xpos;
574 if (PRINT_TRUE_TIME(flags)) {
575 unsigned int h = stamp->hour,
579 /* Lines below useful only when option -t used */
582 stamp->second = s % 60;
584 stamp->minute = m % 60;
585 stamp->hour = h % 24;
590 ***************************************************************************
591 * Autoscale graphs of a given view.
594 * @asf_nr (Maximum) number of autoscale factors.
595 * @group Number of graphs in current view.
596 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
597 * @pos Position in array for the first graph in view.
598 * @gmax Global max value for all graphs in view.
599 * @spmax Array containing max values for graphs.
602 * @asfactor Autoscale factors (one for each graph).
603 ***************************************************************************
605 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, enum svg_graph_type g_type,
606 int pos, double gmax, double *spmax)
610 for (j = 0; j < asf_nr; j++) {
611 /* Init autoscale factors */
615 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
619 for (j = 0; (j < group) && (j < asf_nr); j++) {
620 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
623 snprintf(val, sizeof(val), "%u", (unsigned int) (gmax / *(spmax + pos + j)));
624 if (strlen(val) > 0) {
625 asfactor[j] = pwr10(strlen(val) - 1);
632 ***************************************************************************
633 * Display background grid (horizontal lines) and corresponding graduations.
636 * @ypos Gap between two horizontal lines.
637 * @yfactor Scaling factor on Y axis.
638 * @lmax Max value for current view.
639 * @dp Number of decimal places for graduations.
640 ***************************************************************************
642 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
647 /* Print marker in debug mode */
648 if (DISPLAY_DEBUG_MODE(flags)) {
649 printf("<!-- Hgrid -->\n");
653 /* Display horizontal lines (except on X axis) */
655 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
656 "stroke: #%06x\" transform=\"scale(1,%f)\"/>\n",
657 ypos * j, SVG_G_XSIZE, ypos * j,
658 svg_colors[palette][SVG_COL_GRID_IDX],
663 * Display graduations.
664 * Use same rounded value for graduation numbers as for grid lines
665 * to make sure they are properly aligned.
667 sprintf(stmp, "%.2f", ypos * j);
668 printf("<text x=\"0\" y=\"%ld\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
669 "text-anchor: end\">%.*f.</text>\n",
670 (long) (atof(stmp) * yfactor),
671 svg_colors[palette][SVG_COL_AXIS_IDX],
675 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
679 ***************************************************************************
680 * Display background grid (vertical lines) and corresponding graduations.
683 * @xpos Gap between two vertical lines.
684 * @xfactor Scaling factor on X axis.
685 * @v_gridnr Default number of vertical lines to display. The actual
686 * number may vary between this value and 2 times this value.
687 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
688 ***************************************************************************
690 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
692 struct record_header stamp;
693 struct tstamp_ext rectime;
694 char cur_time[TIMESTAMP_LEN];
697 stamp.ust_time = svg_p->ust_time_ref;
698 /* Also set hour, minute and second in case TRUE_TIME (option -t) requested by user */
699 stamp.hour = svg_p->hour;
700 stamp.minute = svg_p->minute;
701 stamp.second = svg_p->second;
703 /* Print marker in debug mode */
704 if (DISPLAY_DEBUG_MODE(flags)) {
705 printf("<!-- Vgrid -->\n");
709 * What really matters to know when we should stop drawing vertical lines
710 * is the time end. v_gridnr is only informative and used to calculate
711 * the gap between two lines.
713 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
715 /* Display vertical lines */
716 if (sa_get_record_timestamp_struct(flags, &stamp, &rectime)) {
718 fprintf(stderr, "%s: ust_time: %llu\n", __FUNCTION__, stamp.ust_time);
722 set_record_timestamp_string(flags, NULL, cur_time, TIMESTAMP_LEN, &rectime);
723 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
724 "stroke: #%06x\" transform=\"scale(%f,1)\"/>\n",
725 xpos * j, xpos * j, -SVG_G_YSIZE,
726 svg_colors[palette][SVG_COL_GRID_IDX],
729 * Display graduations.
730 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
731 * In this case, we should rather display the exact time instead of only the hour.
733 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_time.tm_min == 0)) {
734 printf("<text x=\"%ld\" y=\"15\" style=\"fill: #%06x; stroke: none; font-size: 14px; "
735 "text-anchor: start\">%2d:00</text>\n",
736 (long) (xpos * j * xfactor) - 15,
737 svg_colors[palette][SVG_COL_AXIS_IDX],
738 rectime.tm_time.tm_hour);
741 printf("<text x=\"%ld\" y=\"10\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
742 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
743 (long) (xpos * j * xfactor),
744 svg_colors[palette][SVG_COL_AXIS_IDX],
745 (long) (xpos * j * xfactor), cur_time);
748 /* Compute timestamp for next graduation */
749 compute_next_graduation_timestamp(&stamp, xpos);
752 printf("<text x=\"-10\" y=\"30\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
753 "text-anchor: end\">%s</text>\n",
754 svg_colors[palette][SVG_COL_INFO_IDX],
755 PRINT_LOCAL_TIME(flags) ? svg_p->my_tzname
756 : (PRINT_TRUE_TIME(flags) ? svg_p->file_hdr->sa_tzname
761 ***************************************************************************
762 * Calculate the value on the Y axis between two horizontal lines that will
763 * make the graph background grid.
766 * @lmax Max value reached for this graph.
769 * @dp Number of decimal places for Y graduations.
772 * Value between two horizontal lines.
773 ***************************************************************************
775 double ygrid(double lmax, int *dp)
786 n = (long) (lmax / SVG_H_GRIDNR);
789 return (lmax / SVG_H_GRIDNR);
791 snprintf(val, sizeof(val), "%ld", n);
792 val[sizeof(val) - 1] = '\0';
798 return ((double) (((long) (n / e)) * e));
802 ***************************************************************************
803 * Calculate the value on the X axis between two vertical lines that will
804 * make the graph background grid.
807 * @timestart First data timestamp (X coordinate of the first data point).
808 * @timeend Last data timestamp (X coordinate of the last data point).
809 * @v_gridnr Number of vertical lines to display. Its value is normally
810 * SVG_V_GRIDNR, except when option "oneday" is used, in which
811 * case it is set to 12.
814 * Value between two vertical lines.
815 ***************************************************************************
817 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
819 if ((timeend - timestart) <= v_gridnr)
822 return ((timeend - timestart) / v_gridnr);
826 ***************************************************************************
827 * Free global graphs structures.
830 * @out Pointer on array of chars for each graph definition.
831 * @outsize Size of array of chars for each graph definition.
832 * @spmin Array containing min values for graphs.
833 * @spmax Array containing max values for graphs.
834 ***************************************************************************
836 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
853 ***************************************************************************
854 * Skip current view where all graphs have only zero values. This function
855 * is called when option "skipempty" has been used, or when "No data" have
856 * been found for current view.
859 * @out Pointer on array of chars for each graph definition.
860 * @pos Position of current view in the array of graphs definitions.
861 * @group Number of graphs in current view.
864 * @pos Position of next view in the array of graphs definitions.
865 ***************************************************************************
867 void skip_current_view(char **out, int *pos, int group)
872 for (j = 0; j < group; j++) {
873 out_p = *(out + *pos + j);
875 /* Even if not displayed, current graph data have to be freed */
883 ***************************************************************************
884 * Display all graphs for current activity.
887 * @g_nr Number of views to display.
888 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
889 * @title Titles for each set of graphs.
890 * @g_title Titles for each graph.
891 * @item_name Item (network interface, etc.) name.
892 * @group Indicate how graphs are grouped together to make sets.
893 * @spmin Array containing min values for graphs.
894 * @spmax Array containing max values for graphs.
895 * @out Pointer on array of chars for each graph definition.
896 * @outsize Size of array of chars for each graph definition.
897 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
898 * time for the first sample of stats (.@ust_time_first), and
899 * times used as start and end values on the X axis
900 * (.@ust_time_ref and .@ust_time_end).
901 * @record_hdr Pointer on record header of current stats sample.
902 * @skip_void Set to <> 0 if graphs with no data should be skipped.
903 * This is typicallly used to not display CPU offline on the
905 * @a Current activity structure.
906 * @xid Current activity extra id number.
909 * TRUE if at least one graph has been displayed.
910 ***************************************************************************
912 int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
913 int group[], double *spmin, double *spmax, char **out, int *outsize,
914 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
915 struct activity *a, unsigned int xid)
918 int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE, palpos;
919 int v_gridnr, xv, yv;
920 unsigned int asfactor[16];
922 double lmax, xfactor, yfactor, ypos, gmin, gmax;
923 char val[32], cur_date[TIMESTAMP_LEN];
925 time_t t = svg_p->file_hdr->sa_ust_time;
927 /* Print activity name in debug mode */
928 if (DISPLAY_DEBUG_MODE(flags)) {
929 printf("<!-- Name: %s -->\n", a->name);
932 /* For each view which is part of current activity */
933 for (i = 0; i < g_nr; i++) {
935 /* Print view number in debug mode */
936 if (DISPLAY_DEBUG_MODE(flags)) {
937 printf("<!-- View %d -->\n", i + 1);
940 /* Used as index in color palette */
941 palpos = (palette == SVG_BW_COL_PALETTE ? 0 : pos);
943 /* Get global min and max value for current view */
944 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
946 /* Don't display empty views if requested */
947 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
948 skip_current_view(out, &pos, group[i]);
951 /* Skip void graphs */
952 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
956 /* Translate to proper position for current activity */
957 printf("<g id=\"g%u-%u\" transform=\"translate(0,%d)\">\n",
960 SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
961 SVG_T_YSIZE * svg_p->graph_no);
965 /* Increment number of views actually displayed */
968 /* Compute top left position of view */
969 if (PACK_VIEWS(flags)) {
970 xv = (views_nr - 1) * SVG_T_XSIZE;
975 yv = (views_nr - 1) * SVG_T_YSIZE;
978 /* Graph background */
979 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\" fill=\"#%06x\"/>\n",
980 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE,
981 svg_colors[palette][SVG_COL_BCKGRD_IDX]);
984 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">%s",
986 svg_colors[palette][SVG_COL_TITLE_IDX],
989 printf(" [%s]", item_name);
992 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
993 "(Min, Max values)</tspan>\n</text>\n",
994 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25,
995 svg_colors[palette][SVG_COL_INFO_IDX]);
998 * At least two samples are needed.
999 * And a min and max value should have been found.
1001 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
1002 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
1004 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">No data</text>\n",
1005 xv, yv + SVG_M_YSIZE,
1006 svg_colors[palette][SVG_COL_ERROR_IDX]);
1007 skip_current_view(out, &pos, group[i]);
1012 printf("<polyline points=\"%d,%d %d,%d %d,%d\" style=\"fill: #%06x; stroke: #%06x; stroke-width: 2\"/>\n",
1013 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
1014 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
1015 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
1016 svg_colors[palette][SVG_COL_BCKGRD_IDX],
1017 svg_colors[palette][SVG_COL_AXIS_IDX]);
1019 /* Autoscaling graphs if needed */
1020 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
1023 for (j = 0; j < group[i]; j++) {
1024 /* Set dp to TRUE (1) if current metric is based on integer values */
1025 dp = (g_title[pos + j][0] == '~');
1026 snprintf(val, sizeof(val), "x%u ", asfactor[j]);
1027 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
1028 "%s %s(%.*f, %.*f)</text>\n",
1029 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
1030 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
1031 asfactor[j] == 1 ? "" : val,
1032 !dp * 2, *(spmin + pos + j) * asfactor[j],
1033 !dp * 2, *(spmax + pos + j) * asfactor[j]);
1036 if (DISPLAY_INFO(flags)) {
1037 /* Display additional info (hostname, date) */
1038 printf("<text x=\"%d\" y=\"%d\" "
1039 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
1041 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
1042 svg_colors[palette][SVG_COL_INFO_IDX],
1043 svg_p->file_hdr->sa_nodename);
1045 /* Get report date */
1046 set_report_date(localtime_r(&t, &rectime),
1047 cur_date, sizeof(cur_date));
1048 printf("<tspan x=\"%d\" y=\"%d\" "
1049 "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
1050 "%s</tspan>\n</text>\n",
1051 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
1052 svg_colors[palette][SVG_COL_INFO_IDX],
1056 /* Translate to proper position for current graph within current activity */
1057 printf("<g transform=\"translate(%d,%d)\">\n",
1058 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
1061 if (g_type[i] == SVG_LINE_GRAPH) {
1062 /* For line graphs */
1064 /* If all values are zero then set current max value to 1 */
1070 /* Max value cannot be too small, else Y graduations will be meaningless */
1071 if (lmax < SVG_H_GRIDNR * 0.01) {
1072 lmax = SVG_H_GRIDNR * 0.01;
1074 ypos = ygrid(lmax, &dp);
1077 /* For bar graphs (used for %values) */
1078 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
1079 dp = 0; /* No decimals */
1081 /* Max should be always 100% except for percentage values greater than 100% */
1089 yfactor = (double) -SVG_G_YSIZE / lmax;
1091 /* Display horizontal lines and graduations */
1092 display_hgrid(ypos, yfactor, lmax, dp);
1094 /* Set number of vertical lines to 12 when option "oneday" is used */
1095 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1097 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1098 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1100 /* Display vertical lines and graduations */
1101 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1103 /* Print marker in debug mode */
1104 if (DISPLAY_DEBUG_MODE(flags)) {
1105 printf("<!-- Graphs -->\n");
1108 /* Draw current graphs set */
1109 for (j = 0; j < group[i]; j++) {
1110 out_p = *(out + pos + j);
1111 if (g_type[i] == SVG_LINE_GRAPH) {
1113 printf("<path d=\"%s\" "
1114 "style=\"vector-effect: non-scaling-stroke; "
1115 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1116 "transform=\"scale(%f,%f)\"/>\n",
1118 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK],
1120 yfactor * asfactor[j]);
1122 else if (*out_p) { /* Ignore flat bars */
1124 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1125 svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1126 printf("%s\n", out_p);
1137 /* For next row of views */
1138 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1145 ***************************************************************************
1146 * Display CPU statistics in SVG.
1149 * @a Activity structure with statistics.
1150 * @curr Index in array for current sample statistics.
1151 * @action Action expected from current function.
1152 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1153 * flag indicating that a restart record has been previously
1154 * found (.@restart), and time used for the X axis origin
1156 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1158 * @record_hdr Pointer on record header of current stats sample.
1159 ***************************************************************************
1161 #define CPU_ARRAY_SZ 10
1162 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1163 unsigned long long itv, struct record_header *record_hdr)
1165 struct stats_cpu *scc, *scp;
1166 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1169 int g_type[] = {SVG_BAR_GRAPH};
1170 char *title[] = {"CPU utilization"};
1171 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1172 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1173 static double *spmin, *spmax;
1175 static int *outsize;
1179 if (action & F_BEGIN) {
1181 * Allocate arrays that will contain the graphs data
1182 * and the min/max values.
1184 out = allocate_graph_lines(CPU_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
1187 if (action & F_MAIN) {
1188 unsigned long long deltot_jiffies = 1;
1191 /* @nr[curr] cannot normally be greater than @nr_ini */
1192 if (a->nr[curr] > a->nr_ini) {
1193 a->nr_ini = a->nr[curr];
1197 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1198 * and look for offline CPU.
1200 if (a->nr_ini > 1) {
1201 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1202 flags, offline_cpu_bitmap);
1206 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1208 /* Should current CPU (including CPU "all") be displayed? */
1209 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1210 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1211 /* Don't display CPU */
1214 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1215 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1217 pos = i * CPU_ARRAY_SZ;
1221 /* This is CPU "all" */
1222 if (a->nr_ini == 1) {
1224 * This is a UP machine. In this case
1225 * interval has still not been calculated.
1227 deltot_jiffies = get_per_cpu_interval(scc, scp);
1229 if (!deltot_jiffies) {
1230 /* CPU "all" cannot be tickless */
1236 * Recalculate interval for current proc.
1237 * If result is 0 then current CPU is a tickless one.
1239 deltot_jiffies = get_per_cpu_interval(scc, scp);
1241 if (!deltot_jiffies) { /* Current CPU is tickless */
1243 double val = 100.0; /* Tickless CPU: %idle = 100% */
1245 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1248 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1252 /* Check min/max values for %user, etc. */
1253 for (k = 0; k < j; k++) {
1254 if (0.0 < *(spmin + pos + k)) {
1255 *(spmin + pos + k) = 0.0;
1257 if (0.0 > *(spmax + pos + k)) {
1258 *(spmax + pos + k) = 0.0;
1263 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1265 out + pos + j, outsize + pos + j, svg_p->dt,
1266 spmin + pos + j, spmax + pos + j);
1271 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1273 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1274 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1275 out + pos, outsize + pos, svg_p->dt,
1276 spmin + pos, spmax + pos);
1280 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1282 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1284 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1285 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1286 out + pos, outsize + pos, svg_p->dt,
1287 spmin + pos, spmax + pos);
1290 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1292 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1293 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1294 out + pos + 1, outsize + pos + 1, svg_p->dt,
1295 spmin + pos + 1, spmax + pos + 1);
1299 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1301 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1303 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1304 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1305 out + pos + 1, outsize + pos + 1, svg_p->dt,
1306 spmin + pos + 1, spmax + pos + 1);
1309 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1311 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1313 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1314 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1316 out + pos + 2, outsize + pos + 2, svg_p->dt,
1317 spmin + pos + 2, spmax + pos + 2);
1321 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1322 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1323 out + pos + 2, outsize + pos + 2, svg_p->dt,
1324 spmin + pos + 2, spmax + pos + 2);
1328 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1329 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1330 out + pos + 3, outsize + pos + 3, svg_p->dt,
1331 spmin + pos + 3, spmax + pos + 3);
1333 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1334 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1335 out + pos + 4, outsize + pos + 4, svg_p->dt,
1336 spmin + pos + 4, spmax + pos + 4);
1338 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1340 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1341 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1342 out + pos + 5, outsize + pos + 5, svg_p->dt,
1343 spmin + pos + 5, spmax + pos + 5);
1345 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1346 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1347 out + pos + 6, outsize + pos + 6, svg_p->dt,
1348 spmin + pos + 6, spmax + pos + 6);
1350 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1351 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1352 out + pos + 7, outsize + pos + 7, svg_p->dt,
1353 spmin + pos + 7, spmax + pos + 7);
1355 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1356 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1357 out + pos + 8, outsize + pos + 8, svg_p->dt,
1358 spmin + pos + 8, spmax + pos + 8);
1367 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1369 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1370 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1371 out + pos + j, outsize + pos + j, svg_p->dt,
1372 spmin + pos + j, spmax + pos + j);
1376 if (action & F_END) {
1377 int xid = 0, displayed;
1380 if (DISPLAY_IDLE(flags)) {
1381 /* Include additional %idle field */
1386 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
1388 /* Should current CPU (including CPU "all") be displayed? */
1389 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1393 pos = i * CPU_ARRAY_SZ;
1395 /* This is CPU "all" */
1396 strcpy(item_name, K_LOWERALL);
1399 sprintf(item_name, "%d", i - 1);
1402 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1403 displayed = draw_activity_graphs(a->g_nr, g_type,
1404 title, g_title1, item_name, group1,
1405 spmin + pos, spmax + pos, out + pos, outsize + pos,
1406 svg_p, record_hdr, i, a, xid);
1409 displayed = draw_activity_graphs(a->g_nr, g_type,
1410 title, g_title2, item_name, group2,
1411 spmin + pos, spmax + pos, out + pos, outsize + pos,
1412 svg_p, record_hdr, i, a, xid);
1419 /* Free remaining structures */
1420 free_graphs(out, outsize, spmin, spmax);
1425 ***************************************************************************
1426 * Display task creation and context switch statistics in SVG.
1429 * @a Activity structure with statistics.
1430 * @curr Index in array for current sample statistics.
1431 * @action Action expected from current function.
1432 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1433 * flag indicating that a restart record has been previously
1434 * found (.@restart) and time used for the X axis origin
1436 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1437 * @record_hdr Pointer on record header of current stats sample.
1438 ***************************************************************************
1440 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1441 unsigned long long itv, struct record_header *record_hdr)
1444 *spc = (struct stats_pcsw *) a->buf[curr],
1445 *spp = (struct stats_pcsw *) a->buf[!curr];
1446 int group[] = {1, 1};
1447 int g_fields[] = {1, 0};
1448 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1449 char *title[] = {"Task creation", "Switching activity"};
1450 char *g_title[] = {"proc/s",
1452 static double *spmin, *spmax;
1454 static int *outsize;
1456 if (action & F_BEGIN) {
1458 * Allocate arrays that will contain the graphs data
1459 * and the min/max values.
1461 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1464 if (action & F_MAIN) {
1465 /* Check for min/max values */
1466 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1467 itv, spmin, spmax, g_fields);
1469 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1470 S_VALUE(spp->processes, spc->processes, itv),
1471 out, outsize, svg_p->restart);
1473 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1474 S_VALUE(spp->context_switch, spc->context_switch, itv),
1475 out + 1, outsize + 1, svg_p->restart);
1478 if (action & F_END) {
1479 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1480 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1482 /* Free remaining structures */
1483 free_graphs(out, outsize, spmin, spmax);
1488 ***************************************************************************
1489 * Display swap statistics in SVG.
1492 * @a Activity structure with statistics.
1493 * @curr Index in array for current sample statistics.
1494 * @action Action expected from current function.
1495 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1496 * flag indicating that a restart record has been previously
1497 * found (.@restart) and time used for the X axis origin
1499 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1500 * @record_hdr Pointer on record header of current stats sample.
1501 ***************************************************************************
1503 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1504 unsigned long long itv, struct record_header *record_hdr)
1507 *ssc = (struct stats_swap *) a->buf[curr],
1508 *ssp = (struct stats_swap *) a->buf[!curr];
1510 int g_type[] = {SVG_LINE_GRAPH};
1511 char *title[] = {"Swap activity"};
1512 char *g_title[] = {"pswpin/s", "pswpout/s" };
1513 int g_fields[] = {0, 1};
1514 static double *spmin, *spmax;
1516 static int *outsize;
1518 if (action & F_BEGIN) {
1520 * Allocate arrays that will contain the graphs data
1521 * and the min/max values.
1523 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1526 if (action & F_MAIN) {
1527 /* Check for min/max values */
1528 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1529 itv, spmin, spmax, g_fields);
1531 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1532 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1533 out, outsize, svg_p->restart);
1535 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1536 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1537 out + 1, outsize + 1, svg_p->restart);
1540 if (action & F_END) {
1541 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1542 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1544 /* Free remaining structures */
1545 free_graphs(out, outsize, spmin, spmax);
1550 ***************************************************************************
1551 * Display paging statistics in SVG.
1554 * @a Activity structure with statistics.
1555 * @curr Index in array for current sample statistics.
1556 * @action Action expected from current function.
1557 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1558 * flag indicating that a restart record has been previously
1559 * found (.@restart) and time used for the X axis origin
1561 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1562 * @record_hdr Pointer on record header of current stats sample.
1563 ***************************************************************************
1565 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1566 unsigned long long itv, struct record_header *record_hdr)
1569 *spc = (struct stats_paging *) a->buf[curr],
1570 *spp = (struct stats_paging *) a->buf[!curr];
1571 int group[] = {2, 2, 4};
1572 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1573 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1574 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1575 "fault/s", "majflt/s",
1576 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1577 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1578 static double *spmin, *spmax;
1580 static int *outsize;
1582 if (action & F_BEGIN) {
1584 * Allocate arrays that will contain the graphs data
1585 * and the min/max values.
1587 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1590 if (action & F_MAIN) {
1591 /* Check for min/max values */
1592 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1593 itv, spmin, spmax, g_fields);
1595 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1596 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1597 out, outsize, svg_p->restart);
1599 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1600 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1601 out + 1, outsize + 1, svg_p->restart);
1603 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1604 S_VALUE(spp->pgfault, spc->pgfault, itv),
1605 out + 2, outsize + 2, svg_p->restart);
1607 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1608 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1609 out + 3, outsize + 3, svg_p->restart);
1611 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1612 S_VALUE(spp->pgfree, spc->pgfree, itv),
1613 out + 4, outsize + 4, svg_p->restart);
1615 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1616 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1617 out + 5, outsize + 5, svg_p->restart);
1619 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1620 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1621 out + 6, outsize + 6, svg_p->restart);
1623 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1624 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1625 out + 7, outsize + 7, svg_p->restart);
1628 if (action & F_END) {
1629 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1630 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1632 /* Free remaining structures */
1633 free_graphs(out, outsize, spmin, spmax);
1638 ***************************************************************************
1639 * Display I/O and transfer rate statistics in SVG.
1642 * @a Activity structure with statistics.
1643 * @curr Index in array for current sample statistics.
1644 * @action Action expected from current function.
1645 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1646 * flag indicating that a restart record has been previously
1647 * found (.@restart) and time used for the X axis origin
1649 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1650 * @record_hdr Pointer on record header of current stats sample.
1651 ***************************************************************************
1653 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1654 unsigned long long itv, struct record_header *record_hdr)
1657 *sic = (struct stats_io *) a->buf[curr],
1658 *sip = (struct stats_io *) a->buf[!curr];
1659 int group[] = {4, 3};
1660 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1661 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1662 char *g_title[] = {"tps", "rtps", "wtps", "dtps",
1663 "bread/s", "bwrtn/s", "bdscd/s"};
1665 * tps:0, rtps:1, wtps:2, dtps:3, bread/s:4, bwrtn/s:5, bdscd/s:6
1675 int g_fields[] = {0, 1, 2, 4, 5, 3, 6};
1676 static double *spmin, *spmax;
1678 static int *outsize;
1680 if (action & F_BEGIN) {
1682 * Allocate arrays that will contain the graphs data
1683 * and the min/max values.
1685 out = allocate_graph_lines(7, &outsize, &spmin, &spmax);
1688 if (action & F_MAIN) {
1689 /* Check for min/max values */
1690 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1691 itv, spmin, spmax, g_fields);
1694 * If we get negative values, this is probably because
1695 * one or more devices/filesystems have been unmounted.
1696 * We display 0.0 in this case though we should rather tell
1697 * the user that the value cannot be calculated here.
1700 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1701 sic->dk_drive < sip->dk_drive ? 0.0 :
1702 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1703 out, outsize, svg_p->restart);
1705 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1706 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1707 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1708 out + 1, outsize + 1, svg_p->restart);
1710 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1711 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1712 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1713 out + 2, outsize + 2, svg_p->restart);
1715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1716 sic->dk_drive_dio < sip->dk_drive_dio ? 0.0 :
1717 S_VALUE(sip->dk_drive_dio, sic->dk_drive_dio, itv),
1718 out + 3, outsize + 3, svg_p->restart);
1720 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1721 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1722 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1723 out + 4, outsize + 4, svg_p->restart);
1725 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1726 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1727 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1728 out + 5, outsize + 5, svg_p->restart);
1730 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1731 sic->dk_drive_dblk < sip->dk_drive_dblk ? 0.0 :
1732 S_VALUE(sip->dk_drive_dblk, sic->dk_drive_dblk, itv),
1733 out + 6, outsize + 6, svg_p->restart);
1736 if (action & F_END) {
1737 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1738 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
1740 /* Free remaining structures */
1741 free_graphs(out, outsize, spmin, spmax);
1746 * **************************************************************************
1747 * Display RAM memory utilization in SVG.
1750 * @a Activity structure with statistics.
1751 * @smc Structure with statistics.
1752 * @action Action expected from current function.
1753 * @dispall TRUE if all memory fields should be displayed.
1754 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1755 * flag indicating that a restart record has been previously
1756 * found (.@restart) and time used for the X axis origin
1758 * @record_hdr Pointer on record header of current stats sample.
1759 * @xid Current SVG graph number.
1762 * @xid Next SVG graph number.
1763 ***************************************************************************
1765 void svg_print_ram_memory_stats(struct activity *a, struct stats_memory *smc, int action, int dispall,
1766 struct svg_parm *svg_p, struct record_header *record_hdr, int *xid)
1768 int group[] = {3, 1, 3, 1, 3, 5};
1769 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1770 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1771 char *title[] = {"Memory utilization (1)", "Memory utilization (2)",
1772 "Memory utilization (3)", "Memory utilization (4)",
1773 "Memory utilization (5)", "Memory utilization (6)"};
1774 char *g_title[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1775 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1776 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1778 int g_fields[] = {0, 4, 5, -1, -1, -1, -1, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1779 static double *spmin, *spmax;
1781 static int *outsize;
1783 if (action & F_BEGIN) {
1785 * Allocate arrays that will contain the graphs data
1786 * and the min/max values.
1788 out = allocate_graph_lines(16, &outsize, &spmin, &spmax);
1791 if (action & F_MAIN) {
1792 unsigned long long nousedmem;
1795 /* Check for min/max values */
1796 save_extrema(a->gtypes_nr, (void *) smc, NULL, 0, spmin, spmax, g_fields);
1798 /* Compute %memused min/max values */
1799 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1800 if (nousedmem > smc->tlmkb) {
1801 nousedmem = smc->tlmkb;
1803 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1804 if (tval > *(spmax + 3)) {
1805 *(spmax + 3) = tval;
1807 if (tval < *(spmin + 3)) {
1808 *(spmin + 3) = tval;
1810 /* Compute %commit min/max values */
1811 tval = (smc->tlmkb + smc->tlskb) ?
1812 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1813 if (tval > *(spmax + 7)) {
1814 *(spmax + 7) = tval;
1816 if (tval < *(spmin + 7)) {
1817 *(spmin + 7) = tval;
1819 /* Compute memused min/max values in MB */
1820 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1821 if (tval > *(spmax + 2)) {
1822 *(spmax + 2) = tval;
1824 if (tval < *(spmin + 2)) {
1825 *(spmin + 2) = tval;
1829 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1830 ((double) smc->frmkb) / 1024,
1831 out, outsize, svg_p->restart);
1833 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1834 ((double) (smc->tlmkb - nousedmem)) / 1024,
1835 out + 2, outsize + 2, svg_p->restart);
1837 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1838 ((double) smc->availablekb) / 1024,
1839 out + 1, outsize + 1, svg_p->restart);
1841 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1842 ((double) smc->bufkb) / 1024,
1843 out + 4, outsize + 4, svg_p->restart);
1845 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1846 ((double) smc->camkb) / 1024,
1847 out + 5, outsize + 5, svg_p->restart);
1849 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1850 ((double) smc->comkb) / 1024,
1851 out + 6, outsize + 6, svg_p->restart);
1853 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1854 ((double) smc->activekb) / 1024,
1855 out + 8, outsize + 8, svg_p->restart);
1857 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1858 ((double) smc->inactkb) / 1024,
1859 out + 9, outsize + 9, svg_p->restart);
1861 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1862 ((double) smc->dirtykb) / 1024,
1863 out + 10, outsize + 10, svg_p->restart);
1865 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1866 ((double) smc->anonpgkb) / 1024,
1867 out + 11, outsize + 11, svg_p->restart);
1869 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1870 ((double) smc->slabkb) / 1024,
1871 out + 12, outsize + 12, svg_p->restart);
1873 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1874 ((double) smc->kstackkb) / 1024,
1875 out + 13, outsize + 13, svg_p->restart);
1877 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1878 ((double) smc->pgtblkb) / 1024,
1879 out + 14, outsize + 14, svg_p->restart);
1881 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1882 ((double) smc->vmusedkb) / 1024,
1883 out + 15, outsize + 15, svg_p->restart);
1885 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1887 smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb)
1889 out + 3, outsize + 3, svg_p->dt);
1891 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1893 (smc->tlmkb + smc->tlskb) ? SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb)
1895 out + 7, outsize + 7, svg_p->dt);
1898 if (action & F_END) {
1901 /* Conversion kB -> MB */
1902 for (i = 0; i < 17; i++) {
1903 if (g_fields[i] >= 0) {
1904 *(spmin + g_fields[i]) /= 1024;
1905 *(spmax + g_fields[i]) /= 1024;
1909 if (draw_activity_graphs(dispall ? 6 : 5,
1910 g_type, title, g_title, NULL, group,
1911 spmin, spmax, out, outsize, svg_p, record_hdr,
1916 /* Free remaining structures */
1917 free_graphs(out, outsize, spmin, spmax);
1922 * **************************************************************************
1923 * Display swap memory utilization in SVG.
1926 * @a Activity structure with statistics.
1927 * @smc Structure with statistics.
1928 * @action Action expected from current function.
1929 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1930 * flag indicating that a restart record has been previously
1931 * found (.@restart) and time used for the X axis origin
1933 * @record_hdr Pointer on record header of current stats sample.
1934 * @xid SVG graph number.
1935 ***************************************************************************
1937 __print_funct_t svg_print_swap_memory_stats(struct activity *a, struct stats_memory *smc,
1938 int action, struct svg_parm *svg_p,
1939 struct record_header *record_hdr, int xid)
1941 int group[] = {3, 1, 1};
1942 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1943 char *title[] = {"Swap utilization (1)", "Swap utilization (2)",
1944 "Swap utilization (3)"};
1945 char *g_title[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1947 int g_fields[] = {-1, -1, -1, 5, 0, 6, 2,
1948 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
1949 static double *spmin, *spmax;
1951 static int *outsize;
1953 if (action & F_BEGIN) {
1955 * Allocate arrays that will contain the graphs data
1956 * and the min/max values.
1958 out = allocate_graph_lines(7, &outsize, &spmin, &spmax);
1961 if (action & F_MAIN) {
1964 /* Check for min/max values */
1965 save_extrema(a->gtypes_nr, (void *) smc, NULL, 0, spmin, spmax, g_fields);
1967 /* Compute %swpused min/max values */
1969 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1970 if (tval > *(spmax + 3)) {
1971 *(spmax + 3) = tval;
1973 if (tval < *(spmin + 3)) {
1974 *(spmin + 3) = tval;
1976 /* Compute %swpcad min/max values */
1977 tval = (smc->tlskb - smc->frskb) ?
1978 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1979 if (tval > *(spmax + 4)) {
1980 *(spmax + 4) = tval;
1982 if (tval < *(spmin + 4)) {
1983 *(spmin + 4) = tval;
1985 /* Compute swpused min/max values in MB */
1986 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1987 if (tval > *(spmax + 1)) {
1988 *(spmax + 1) = tval;
1990 if (tval < *(spmin + 1)) {
1991 *(spmin + 1) = tval;
1995 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1996 ((double) smc->frskb) / 1024,
1997 out, outsize, svg_p->restart);
1999 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2000 ((double) (smc->tlskb - smc->frskb)) / 1024,
2001 out + 1, outsize + 1, svg_p->restart);
2003 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2004 ((double) smc->caskb) / 1024,
2005 out + 2, outsize + 2, svg_p->restart);
2007 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2009 smc->tlskb ? SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb)
2011 out + 3, outsize + 3, svg_p->dt);
2013 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2015 (smc->tlskb - smc->frskb) ? SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb)
2017 out + 4, outsize + 4, svg_p->dt);
2020 if (action & F_END) {
2023 /* Conversion kB -> MB */
2024 for (i = 3; i < 7; i++) {
2025 *(spmin + g_fields[i]) /= 1024;
2026 *(spmax + g_fields[i]) /= 1024;
2029 draw_activity_graphs(3, g_type, title, g_title, NULL, group,
2030 spmin, spmax, out, outsize,
2031 svg_p, record_hdr, FALSE, a, xid);
2033 /* Free remaining structures */
2034 free_graphs(out, outsize, spmin, spmax);
2039 * **************************************************************************
2040 * Display memory statistics in SVG.
2043 * @a Activity structure with statistics.
2044 * @curr Index in array for current sample statistics.
2045 * @action Action expected from current function.
2046 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2047 * flag indicating that a restart record has been previously
2048 * found (.@restart) and time used for the X axis origin
2050 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2051 * @record_hdr Pointer on record header of current stats sample.
2052 ***************************************************************************
2054 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2055 unsigned long long itv, struct record_header *record_hdr)
2058 *smc = (struct stats_memory *) a->buf[curr];
2061 if (DISPLAY_MEMORY(a->opt_flags)) {
2062 svg_print_ram_memory_stats(a, smc, action, DISPLAY_MEM_ALL(a->opt_flags),
2063 svg_p, record_hdr, &xid);
2066 if (DISPLAY_SWAP(a->opt_flags)) {
2067 svg_print_swap_memory_stats(a, smc, action, svg_p, record_hdr, xid);
2072 ***************************************************************************
2073 * Display kernel tables statistics in SVG.
2076 * @a Activity structure with statistics.
2077 * @curr Index in array for current sample statistics.
2078 * @action Action expected from current function.
2079 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2080 * flag indicating that a restart record has been previously
2081 * found (.@restart) and time used for the X axis origin
2083 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2084 * @record_hdr Pointer on record header of current stats sample.
2085 ***************************************************************************
2087 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2088 unsigned long long itv, struct record_header *record_hdr)
2090 struct stats_ktables
2091 *skc = (struct stats_ktables *) a->buf[curr];
2092 int group[] = {3, 1};
2093 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2094 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
2095 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
2097 int g_fields[] = {1, 2, 0, 3};
2098 static double *spmin, *spmax;
2100 static int *outsize;
2102 if (action & F_BEGIN) {
2104 * Allocate arrays that will contain the graphs data
2105 * and the min/max values.
2107 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
2110 if (action & F_MAIN) {
2111 /* Check for min/max values */
2112 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2113 itv, spmin, spmax, g_fields);
2115 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2116 (unsigned long long) skc->dentry_stat,
2117 out, outsize, svg_p->restart);
2119 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2120 (unsigned long long) skc->file_used,
2121 out + 1, outsize + 1, svg_p->restart);
2123 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2124 (unsigned long long) skc->inode_used,
2125 out + 2, outsize + 2, svg_p->restart);
2127 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2128 (unsigned long long) skc->pty_nr,
2129 out + 3, outsize + 3, svg_p->restart);
2132 if (action & F_END) {
2133 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2134 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2136 /* Free remaining structures */
2137 free_graphs(out, outsize, spmin, spmax);
2142 ***************************************************************************
2143 * Display queue and load statistics in SVG.
2146 * @a Activity structure with statistics.
2147 * @curr Index in array for current sample statistics.
2148 * @action Action expected from current function.
2149 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2150 * flag indicating that a restart record has been previously
2151 * found (.@restart) and time used for the X axis origin
2153 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2154 * @record_hdr Pointer on record header of current stats sample.
2155 ***************************************************************************
2157 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2158 unsigned long long itv, struct record_header *record_hdr)
2161 *sqc = (struct stats_queue *) a->buf[curr];
2162 int group[] = {2, 1, 3};
2163 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2164 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
2165 char *g_title[] = {"~runq-sz", "~blocked",
2167 "ldavg-1", "ldavg-5", "ldavg-15"};
2168 int g_fields[] = {0, 1, 2, 3, 4, 5};
2169 static double *spmin, *spmax;
2171 static int *outsize;
2173 if (action & F_BEGIN) {
2175 * Allocate arrays that will contain the graphs data
2176 * and the min/max values.
2178 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2181 if (action & F_MAIN) {
2182 /* Check for min/max values */
2183 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2184 itv, spmin, spmax, g_fields);
2186 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2187 (unsigned long long) sqc->nr_running,
2188 out, outsize, svg_p->restart);
2190 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2191 (unsigned long long) sqc->procs_blocked,
2192 out + 1, outsize + 1, svg_p->restart);
2194 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2195 (unsigned long long) sqc->nr_threads,
2196 out + 2, outsize + 2, svg_p->restart);
2198 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2199 (double) sqc->load_avg_1 / 100,
2200 out + 3, outsize + 3, svg_p->restart);
2202 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2203 (double) sqc->load_avg_5 / 100,
2204 out + 4, outsize + 4, svg_p->restart);
2206 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2207 (double) sqc->load_avg_15 / 100,
2208 out + 5, outsize + 5, svg_p->restart);
2211 if (action & F_END) {
2212 /* Fix min/max values for load average */
2213 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2214 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2215 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2217 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2218 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2220 /* Free remaining structures */
2221 free_graphs(out, outsize, spmin, spmax);
2226 ***************************************************************************
2227 * Display disk statistics in SVG.
2230 * @a Activity structure with statistics.
2231 * @curr Index in array for current sample statistics.
2232 * @action Action expected from current function.
2233 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2234 * flag indicating that a restart record has been previously
2235 * found (.@restart) and time used for the X axis origin
2237 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2238 * @record_hdr Pointer on record header of current stats sample.
2239 ***************************************************************************
2241 #define DISK_ARRAY_SZ 9
2242 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2243 unsigned long long itv, struct record_header *record_hdr)
2245 struct stats_disk *sdc, *sdp, sdpzero;
2246 struct ext_disk_stats xds;
2247 int group[] = {1, 3, 2, 1, 1};
2248 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2249 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2250 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2251 "Block devices statistics (3)", "Block devices statistics (4)",
2252 "Block devices statistics (5)"};
2253 char *g_title[] = {"tps",
2254 "rkB/s", "wkB/s", "dkB/s",
2255 "areq-sz", "aqu-sz",
2258 int g_fields[] = {0, 1, 2};
2259 unsigned int local_types_nr[] = {1, 0, 0};
2260 static double *spmin, *spmax;
2262 static int *outsize;
2263 char *dev_name, *item_name;
2264 double rkB, wkB, dkB, aqusz;
2265 int i, j, k, pos, restart, *unregistered;
2267 if (action & F_BEGIN) {
2269 * Allocate arrays (#0..7) that will contain the graphs data
2270 * and the min/max values.
2271 * Also allocate one additional array (#8) for each disk device:
2272 * out + 8 will contain the device name (WWN id, pretty name or devm-n),
2273 * outsize + 8 will contain a positive value (TRUE) if the device
2274 * has either still not been registered, or has been unregistered.
2276 out = allocate_graph_lines(DISK_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2279 if (action & F_MAIN) {
2280 memset(&sdpzero, 0, STATS_DISK_SIZE);
2282 * Mark previously registered devices as now
2283 * possibly unregistered for all graphs.
2285 for (k = 0; k < a->item_list_sz; k++) {
2286 unregistered = outsize + k * DISK_ARRAY_SZ + 8;
2287 if (*unregistered == FALSE) {
2288 *unregistered = MAYBE;
2292 /* For each device structure */
2293 for (i = 0; i < a->nr[curr]; i++) {
2294 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2295 restart = svg_p->restart;
2297 /* Get device name */
2298 dev_name = get_device_name(sdc->major, sdc->minor, sdc->wwn, sdc->part_nr,
2299 DISPLAY_PRETTY(flags), DISPLAY_PERSIST_NAME_S(flags),
2300 USE_STABLE_ID(flags), NULL);
2302 if (a->item_list != NULL) {
2303 /* A list of devices has been entered on the command line */
2304 if (!search_list_item(a->item_list, dev_name))
2305 /* Device not found */
2309 /* Look for corresponding graph */
2310 for (k = 0; k < a->item_list_sz; k++) {
2311 item_name = *(out + k * DISK_ARRAY_SZ + 8);
2312 if (!strcmp(dev_name, item_name))
2316 if (k == a->item_list_sz) {
2317 /* Graph not found: Look for first free entry */
2318 for (k = 0; k < a->item_list_sz; k++) {
2319 item_name = *(out + k * DISK_ARRAY_SZ + 8);
2320 if (!strcmp(item_name, ""))
2323 if (k == a->item_list_sz) {
2324 /* No free graph entry: Ignore it (should never happen) */
2326 fprintf(stderr, "%s: Name=%s major=%u minor=%u\n",
2327 __FUNCTION__, dev_name, sdc->major, sdc->minor);
2332 pos = k * DISK_ARRAY_SZ;
2333 unregistered = outsize + pos + 8;
2336 * If current device was marked as previously unregistered,
2337 * then set restart variable to TRUE so that the graph will be
2338 * discontinuous, and mark it as now registered.
2340 if (*unregistered == TRUE) {
2343 *unregistered = FALSE;
2345 item_name = *(out + pos + 8);
2346 if (!item_name[0]) {
2347 /* Save device name (WWN id or pretty name) if not already done */
2348 strncpy(item_name, dev_name, CHUNKSIZE);
2349 item_name[CHUNKSIZE - 1] = '\0';
2352 j = check_disk_reg(a, curr, !curr, i);
2354 /* This is a newly registered interface. Previous stats are zero */
2359 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2362 /* Check for min/max values */
2363 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2364 itv, spmin + pos, spmax + pos, g_fields);
2366 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2367 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2368 dkB = S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2;
2369 if (rkB < *(spmin + pos + 1)) {
2370 *(spmin + pos + 1) = rkB;
2372 if (rkB > *(spmax + pos + 1)) {
2373 *(spmax + pos + 1) = rkB;
2375 if (wkB < *(spmin + pos + 2)) {
2376 *(spmin + pos + 2) = wkB;
2378 if (wkB > *(spmax + pos + 2)) {
2379 *(spmax + pos + 2) = wkB;
2381 if (dkB < *(spmin + pos + 3)) {
2382 *(spmin + pos + 3) = dkB;
2384 if (dkB > *(spmax + pos + 3)) {
2385 *(spmax + pos + 3) = dkB;
2388 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2389 if ((xds.arqsz / 2) < *(spmin + pos + 4)) {
2390 *(spmin + pos + 4) = xds.arqsz / 2;
2392 if ((xds.arqsz / 2) > *(spmax + pos + 4)) {
2393 *(spmax + pos + 4) = xds.arqsz / 2;
2395 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2396 if (aqusz < *(spmin + pos + 5)) {
2397 *(spmin + pos + 5) = aqusz;
2399 if (aqusz > *(spmax + pos + 5)) {
2400 *(spmax + pos + 5) = aqusz;
2402 if (xds.await < *(spmin + pos + 6)) {
2403 *(spmin + pos + 6) = xds.await;
2405 if (xds.await > *(spmax + pos + 6)) {
2406 *(spmax + pos + 6) = xds.await;
2408 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2409 *(spmin + pos + 7) = xds.util / 10.0;
2411 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2412 *(spmax + pos + 7) = xds.util / 10.0;
2416 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2417 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2418 out + pos, outsize + pos, restart);
2420 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2421 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2422 out + pos + 1, outsize + pos + 1, restart);
2424 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2425 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2426 out + pos + 2, outsize + pos + 2, restart);
2428 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2429 S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2,
2430 out + pos + 3, outsize + pos + 3, restart);
2432 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2434 out + pos + 4, outsize + pos + 4, restart);
2436 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2438 out + pos + 5, outsize + pos + 5, restart);
2440 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2442 out + pos + 6, outsize + pos + 6, restart);
2444 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2445 0.0, xds.util / 10.0,
2446 out + pos + 7, outsize + pos + 7, svg_p->dt);
2449 /* Mark devices not seen here as now unregistered */
2450 for (k = 0; k < a->item_list_sz; k++) {
2451 unregistered = outsize + k * DISK_ARRAY_SZ + 8;
2452 if (*unregistered != FALSE) {
2453 *unregistered = TRUE;
2458 if (action & F_END) {
2461 for (i = 0; i < a->item_list_sz; i++) {
2462 /* Check if there is something to display */
2463 pos = i * DISK_ARRAY_SZ;
2467 item_name = *(out + pos + 8);
2468 if (draw_activity_graphs(a->g_nr, g_type,
2469 title, g_title, item_name, group,
2470 spmin + pos, spmax + pos, out + pos, outsize + pos,
2471 svg_p, record_hdr, FALSE, a, xid)) {
2476 /* Free remaining structures */
2477 free_graphs(out, outsize, spmin, spmax);
2482 ***************************************************************************
2483 * Display network interfaces statistics in SVG.
2486 * @a Activity structure with statistics.
2487 * @curr Index in array for current sample statistics.
2488 * @action Action expected from current function.
2489 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2490 * flag indicating that a restart record has been previously
2491 * found (.@restart) and time used for the X axis origin
2493 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2494 * @record_hdr Pointer on record header of current stats sample.
2495 ***************************************************************************
2497 #define NET_DEV_ARRAY_SZ 9
2498 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2499 unsigned long long itv, struct record_header *record_hdr)
2501 struct stats_net_dev *sndc, *sndp, sndzero;
2502 int group[] = {2, 2, 3, 1};
2503 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2505 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2506 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2507 char *g_title[] = {"rxpck/s", "txpck/s",
2509 "rxcmp/s", "txcmp/s", "rxmcst/s",
2511 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2512 unsigned int local_types_nr[] = {7, 0, 0};
2513 static double *spmin, *spmax;
2515 static int *outsize;
2517 double rxkb, txkb, ifutil;
2518 int i, j, k, pos, restart, *unregistered;
2520 if (action & F_BEGIN) {
2522 * Allocate arrays (#0..7) that will contain the graphs data
2523 * and the min/max values.
2524 * Also allocate one additional array (#8) for each interface:
2525 * out + 8 will contain the interface name,
2526 * outsize + 8 will contain a positive value (TRUE) if the interface
2527 * has either still not been registered, or has been unregistered.
2529 out = allocate_graph_lines(NET_DEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2532 if (action & F_MAIN) {
2533 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2535 * Mark previously registered interfaces as now
2536 * possibly unregistered for all graphs.
2538 for (k = 0; k < a->item_list_sz; k++) {
2539 unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
2540 if (*unregistered == FALSE) {
2541 *unregistered = MAYBE;
2545 /* For each network interfaces structure */
2546 for (i = 0; i < a->nr[curr]; i++) {
2547 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2548 restart = svg_p->restart;
2550 if (a->item_list != NULL) {
2551 /* A list of devices has been entered on the command line */
2552 if (!search_list_item(a->item_list, sndc->interface))
2553 /* Device not found */
2557 /* Look for corresponding graph */
2558 for (k = 0; k < a->item_list_sz; k++) {
2559 item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
2560 if (!strcmp(sndc->interface, item_name))
2564 if (k == a->item_list_sz) {
2565 /* Graph not found: Look for first free entry */
2566 for (k = 0; k < a->item_list_sz; k++) {
2567 item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
2568 if (!strcmp(item_name, ""))
2571 if (k == a->item_list_sz) {
2572 /* No free graph entry: Ignore it (should never happen) */
2574 fprintf(stderr, "%s: Name=%s\n",
2575 __FUNCTION__, sndc->interface);
2580 pos = k * NET_DEV_ARRAY_SZ;
2581 unregistered = outsize + pos + 8;
2583 j = check_net_dev_reg(a, curr, !curr, i);
2585 /* This is a newly registered interface. Previous stats are zero */
2590 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2594 * If current interface was marked as previously unregistered,
2595 * then set restart variable to TRUE so that the graph will be
2596 * discontinuous, and mark it as now registered.
2598 if (*unregistered == TRUE) {
2601 *unregistered = FALSE;
2603 item_name = *(out + pos + 8);
2604 if (!item_name[0]) {
2605 /* Save network interface name (if not already done) */
2606 strncpy(item_name, sndc->interface, CHUNKSIZE);
2607 item_name[CHUNKSIZE - 1] = '\0';
2610 /* Check for min/max values */
2611 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2612 itv, spmin + pos, spmax + pos, g_fields);
2614 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2615 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2616 ifutil = compute_ifutil(sndc, rxkb, txkb);
2617 if (ifutil < *(spmin + pos + 7)) {
2618 *(spmin + pos + 7) = ifutil;
2620 if (ifutil > *(spmax + pos + 7)) {
2621 *(spmax + pos + 7) = ifutil;
2625 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2626 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2627 out + pos, outsize + pos, restart);
2629 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2630 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2631 out + pos + 1, outsize + pos + 1, restart);
2633 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2635 out + pos + 2, outsize + pos + 2, restart);
2637 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2639 out + pos + 3, outsize + pos + 3, restart);
2641 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2642 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2643 out + pos + 4, outsize + pos + 4, restart);
2645 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2646 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2647 out + pos + 5, outsize + pos + 5, restart);
2649 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2650 S_VALUE(sndp->multicast, sndc->multicast, itv),
2651 out + pos + 6, outsize + pos + 6, restart);
2653 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2655 out + pos + 7, outsize + pos + 7, svg_p->dt);
2658 /* Mark interfaces not seen here as now unregistered */
2659 for (k = 0; k < a->item_list_sz; k++) {
2660 unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
2661 if (*unregistered != FALSE) {
2662 *unregistered = TRUE;
2667 if (action & F_END) {
2670 for (i = 0; i < a->item_list_sz; i++) {
2672 * Check if there is something to display.
2673 * Don't test sndc->interface because maybe the network
2674 * interface has been registered later.
2676 pos = i * NET_DEV_ARRAY_SZ;
2680 /* Recalculate min and max values in kB, not in B */
2681 *(spmin + pos + 2) /= 1024;
2682 *(spmax + pos + 2) /= 1024;
2683 *(spmin + pos + 3) /= 1024;
2684 *(spmax + pos + 3) /= 1024;
2686 item_name = *(out + pos + 8);
2687 if (draw_activity_graphs(a->g_nr, g_type,
2688 title, g_title, item_name, group,
2689 spmin + pos, spmax + pos, out + pos, outsize + pos,
2690 svg_p, record_hdr, FALSE, a, xid)) {
2695 /* Free remaining structures */
2696 free_graphs(out, outsize, spmin, spmax);
2701 ***************************************************************************
2702 * Display network interfaces errors statistics in SVG.
2705 * @a Activity structure with statistics.
2706 * @curr Index in array for current sample statistics.
2707 * @action Action expected from current function.
2708 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2709 * flag indicating that a restart record has been previously
2710 * found (.@restart) and time used for the X axis origin
2712 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2713 * @record_hdr Pointer on record header of current stats sample.
2714 ***************************************************************************
2716 #define NET_EDEV_ARRAY_SZ 10
2717 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2718 unsigned long long itv, struct record_header *record_hdr)
2720 struct stats_net_edev *snedc, *snedp, snedzero;
2721 int group[] = {2, 2, 2, 3};
2722 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2724 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2725 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2726 char *g_title[] = {"rxerr/s", "txerr/s",
2727 "rxdrop/s", "txdrop/s",
2728 "rxfifo/s", "txfifo/s",
2729 "coll/s", "txcarr/s", "rxfram/s"};
2730 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2731 static double *spmin, *spmax;
2733 static int *outsize;
2735 int i, j, k, pos, restart, *unregistered;
2737 if (action & F_BEGIN) {
2739 * Allocate arrays (#0..8) that will contain the graphs data
2740 * and the min/max values.
2741 * Also allocate one additional array (#9) for each interface:
2742 * out + 9 will contain the interface name,
2743 * outsize + 9 will contain a positive value (TRUE) if the interface
2744 * has either still not been registered, or has been unregistered.
2746 out = allocate_graph_lines(NET_EDEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
2749 if (action & F_MAIN) {
2750 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2752 * Mark previously registered interfaces as now
2753 * possibly unregistered for all graphs.
2755 for (k = 0; k < a->item_list_sz; k++) {
2756 unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
2757 if (*unregistered == FALSE) {
2758 *unregistered = MAYBE;
2762 /* For each network interfaces structure */
2763 for (i = 0; i < a->nr[curr]; i++) {
2764 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2765 restart = svg_p->restart;
2767 if (a->item_list != NULL) {
2768 /* A list of devices has been entered on the command line */
2769 if (!search_list_item(a->item_list, snedc->interface))
2770 /* Device not found */
2774 /* Look for corresponding graph */
2775 for (k = 0; k < a->item_list_sz; k++) {
2776 item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
2777 if (!strcmp(snedc->interface, item_name))
2781 if (k == a->item_list_sz) {
2782 /* Graph not found: Look for first free entry */
2783 for (k = 0; k < a->item_list_sz; k++) {
2784 item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
2785 if (!strcmp(item_name, ""))
2788 if (k == a->item_list_sz) {
2789 /* No free graph entry: Ignore it (should never happen) */
2791 fprintf(stderr, "%s: Name=%s\n",
2792 __FUNCTION__, snedc->interface);
2798 pos = k * NET_EDEV_ARRAY_SZ;
2799 unregistered = outsize + pos + 9;
2801 j = check_net_edev_reg(a, curr, !curr, i);
2803 /* This is a newly registered interface. Previous stats are zero */
2808 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2812 * If current interface was marked as previously unregistered,
2813 * then set restart variable to TRUE so that the graph will be
2814 * discontinuous, and mark it as now registered.
2816 if (*unregistered == TRUE) {
2819 *unregistered = FALSE;
2821 item_name = *(out + pos + 9);
2822 if (!item_name[0]) {
2823 /* Save network interface name (if not already done) */
2824 strncpy(item_name, snedc->interface, CHUNKSIZE);
2825 item_name[CHUNKSIZE - 1] = '\0';
2828 /* Check for min/max values */
2829 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2830 itv, spmin + pos, spmax + pos, g_fields);
2833 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2834 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2835 out + pos, outsize + pos, restart);
2837 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2838 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2839 out + pos + 1, outsize + pos + 1, restart);
2841 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2842 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2843 out + pos + 2, outsize + pos + 2, restart);
2845 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2846 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2847 out + pos + 3, outsize + pos + 3, restart);
2849 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2850 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2851 out + pos + 4, outsize + pos + 4, restart);
2853 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2854 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2855 out + pos + 5, outsize + pos + 5, restart);
2857 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2858 S_VALUE(snedp->collisions, snedc->collisions, itv),
2859 out + pos + 6, outsize + pos + 6, restart);
2861 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2862 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2863 out + pos + 7, outsize + pos + 7, restart);
2865 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2866 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2867 out + pos + 8, outsize + pos + 8, restart);
2870 /* Mark interfaces not seen here as now unregistered */
2871 for (k = 0; k < a->item_list_sz; k++) {
2872 unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
2873 if (*unregistered != FALSE) {
2874 *unregistered = TRUE;
2879 if (action & F_END) {
2882 for (i = 0; i < a->item_list_sz; i++) {
2884 * Check if there is something to display.
2885 * Don't test snedc->interface because maybe the network
2886 * interface has been registered later.
2888 pos = i * NET_EDEV_ARRAY_SZ;
2892 item_name = *(out + pos + 9);
2893 if (draw_activity_graphs(a->g_nr, g_type,
2894 title, g_title, item_name, group,
2895 spmin + pos, spmax + pos, out + pos, outsize + pos,
2896 svg_p, record_hdr, FALSE, a, xid)) {
2901 /* Free remaining structures */
2902 free_graphs(out, outsize, spmin, spmax);
2907 ***************************************************************************
2908 * Display NFS client statistics in SVG.
2911 * @a Activity structure with statistics.
2912 * @curr Index in array for current sample statistics.
2913 * @action Action expected from current function.
2914 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2915 * flag indicating that a restart record has been previously
2916 * found (.@restart) and time used for the X axis origin
2918 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2919 * @record_hdr Pointer on record header of current stats sample.
2920 ***************************************************************************
2922 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2923 unsigned long long itv, struct record_header *record_hdr)
2925 struct stats_net_nfs
2926 *snnc = (struct stats_net_nfs *) a->buf[curr],
2927 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2928 int group[] = {2, 2, 2};
2929 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2930 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2931 "NFS client statistics (3)"};
2932 char *g_title[] = {"call/s", "retrans/s",
2933 "read/s", "write/s",
2934 "access/s", "getatt/s"};
2935 int g_fields[] = {0, 1, 2, 3, 4, 5};
2936 static double *spmin, *spmax;
2938 static int *outsize;
2940 if (action & F_BEGIN) {
2942 * Allocate arrays that will contain the graphs data
2943 * and the min/max values.
2945 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2948 if (action & F_MAIN) {
2949 /* Check for min/max values */
2950 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2951 itv, spmin, spmax, g_fields);
2954 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2955 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2956 out, outsize, svg_p->restart);
2958 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2959 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2960 out + 1, outsize + 1, svg_p->restart);
2962 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2963 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2964 out + 2, outsize + 2, svg_p->restart);
2966 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2967 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2968 out + 3, outsize + 3, svg_p->restart);
2970 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2971 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2972 out + 4, outsize + 4, svg_p->restart);
2974 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2975 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2976 out + 5, outsize + 5, svg_p->restart);
2979 if (action & F_END) {
2980 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2981 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
2983 /* Free remaining structures */
2984 free_graphs(out, outsize, spmin, spmax);
2989 ***************************************************************************
2990 * Display NFS server statistics in SVG.
2993 * @a Activity structure with statistics.
2994 * @curr Index in array for current sample statistics.
2995 * @action Action expected from current function.
2996 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2997 * flag indicating that a restart record has been previously
2998 * found (.@restart) and time used for the X axis origin
3000 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3001 * @record_hdr Pointer on record header of current stats sample.
3002 ***************************************************************************
3004 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3005 unsigned long long itv, struct record_header *record_hdr)
3007 struct stats_net_nfsd
3008 *snndc = (struct stats_net_nfsd *) a->buf[curr],
3009 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
3010 int group[] = {2, 3, 2, 2, 2};
3011 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3012 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3013 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
3014 "NFS server statistics (3)", "NFS server statistics (4)",
3015 "NFS server statistics (5)"};
3016 char *g_title[] = {"scall/s", "badcall/s",
3017 "packet/s", "udp/s", "tcp/s",
3019 "sread/s", "swrite/s",
3020 "saccess/s", "sgetatt/s"};
3021 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3022 static double *spmin, *spmax;
3024 static int *outsize;
3026 if (action & F_BEGIN) {
3028 * Allocate arrays that will contain the graphs data
3029 * and the min/max values.
3031 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3034 if (action & F_MAIN) {
3035 /* Check for min/max values */
3036 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3037 itv, spmin, spmax, g_fields);
3040 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3041 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
3042 out, outsize, svg_p->restart);
3044 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3045 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
3046 out + 1, outsize + 1, svg_p->restart);
3048 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3049 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
3050 out + 2, outsize + 2, svg_p->restart);
3052 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3053 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
3054 out + 3, outsize + 3, svg_p->restart);
3056 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3057 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
3058 out + 4, outsize + 4, svg_p->restart);
3060 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3061 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
3062 out + 5, outsize + 5, svg_p->restart);
3064 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3065 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
3066 out + 6, outsize + 6, svg_p->restart);
3068 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3069 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
3070 out + 7, outsize + 7, svg_p->restart);
3072 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3073 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
3074 out + 8, outsize + 8, svg_p->restart);
3076 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3077 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
3078 out + 9, outsize + 9, svg_p->restart);
3080 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3081 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
3082 out + 10, outsize + 10, svg_p->restart);
3085 if (action & F_END) {
3086 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3087 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3089 /* Free remaining structures */
3090 free_graphs(out, outsize, spmin, spmax);
3095 ***************************************************************************
3096 * Display socket statistics in SVG.
3099 * @a Activity structure with statistics.
3100 * @curr Index in array for current sample statistics.
3101 * @action Action expected from current function.
3102 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3103 * flag indicating that a restart record has been previously
3104 * found (.@restart) and time used for the X axis origin
3106 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3107 * @record_hdr Pointer on record header of current stats sample.
3108 ***************************************************************************
3110 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3111 unsigned long long itv, struct record_header *record_hdr)
3113 struct stats_net_sock
3114 *snsc = (struct stats_net_sock *) a->buf[curr];
3115 int group[] = {1, 5};
3116 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3117 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
3118 char *g_title[] = {"~totsck",
3119 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
3120 int g_fields[] = {0, 1, 5, 2, 3, 4};
3121 static double *spmin, *spmax;
3123 static int *outsize;
3125 if (action & F_BEGIN) {
3127 * Allocate arrays that will contain the graphs data
3128 * and the min/max values.
3130 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
3133 if (action & F_MAIN) {
3134 /* Check for min/max values */
3135 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3136 itv, spmin, spmax, g_fields);
3138 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3139 (unsigned long long) snsc->sock_inuse,
3140 out, outsize, svg_p->restart);
3142 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3143 (unsigned long long) snsc->tcp_inuse,
3144 out + 1, outsize + 1, svg_p->restart);
3146 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3147 (unsigned long long) snsc->udp_inuse,
3148 out + 2, outsize + 2, svg_p->restart);
3150 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3151 (unsigned long long) snsc->raw_inuse,
3152 out + 3, outsize + 3, svg_p->restart);
3154 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3155 (unsigned long long) snsc->frag_inuse,
3156 out + 4, outsize + 4, svg_p->restart);
3158 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3159 (unsigned long long) snsc->tcp_tw,
3160 out + 5, outsize + 5, svg_p->restart);
3163 if (action & F_END) {
3164 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3165 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3167 /* Free remaining structures */
3168 free_graphs(out, outsize, spmin, spmax);
3173 ***************************************************************************
3174 * Display IPv4 traffic statistics in SVG.
3177 * @a Activity structure with statistics.
3178 * @curr Index in array for current sample statistics.
3179 * @action Action expected from current function.
3180 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3181 * flag indicating that a restart record has been previously
3182 * found (.@restart) and time used for the X axis origin
3184 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3185 * @record_hdr Pointer on record header of current stats sample.
3186 ***************************************************************************
3188 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3189 unsigned long long itv, struct record_header *record_hdr)
3192 *snic = (struct stats_net_ip *) a->buf[curr],
3193 *snip = (struct stats_net_ip *) a->buf[!curr];
3194 int group[] = {4, 2, 2};
3195 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3196 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
3197 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
3198 "asmrq/s", "asmok/s",
3199 "fragok/s", "fragcrt/s"};
3200 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3201 static double *spmin, *spmax;
3203 static int *outsize;
3205 if (action & F_BEGIN) {
3207 * Allocate arrays that will contain the graphs data
3208 * and the min/max values.
3210 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3213 if (action & F_MAIN) {
3214 /* Check for min/max values */
3215 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3216 itv, spmin, spmax, g_fields);
3219 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3220 S_VALUE(snip->InReceives, snic->InReceives, itv),
3221 out, outsize, svg_p->restart);
3223 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3224 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
3225 out + 1, outsize + 1, svg_p->restart);
3227 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3228 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
3229 out + 2, outsize + 2, svg_p->restart);
3231 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3232 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3233 out + 3, outsize + 3, svg_p->restart);
3235 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3236 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3237 out + 4, outsize + 4, svg_p->restart);
3239 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3240 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3241 out + 5, outsize + 5, svg_p->restart);
3243 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3244 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3245 out + 6, outsize + 6, svg_p->restart);
3247 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3248 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3249 out + 7, outsize + 7, svg_p->restart);
3252 if (action & F_END) {
3253 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3254 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3256 /* Free remaining structures */
3257 free_graphs(out, outsize, spmin, spmax);
3262 ***************************************************************************
3263 * Display IPv4 traffic errors statistics in SVG.
3266 * @a Activity structure with statistics.
3267 * @curr Index in array for current sample statistics.
3268 * @action Action expected from current function.
3269 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3270 * flag indicating that a restart record has been previously
3271 * found (.@restart) and time used for the X axis origin
3273 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3274 * @record_hdr Pointer on record header of current stats sample.
3275 ***************************************************************************
3277 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3278 unsigned long long itv, struct record_header *record_hdr)
3280 struct stats_net_eip
3281 *sneic = (struct stats_net_eip *) a->buf[curr],
3282 *sneip = (struct stats_net_eip *) a->buf[!curr];
3283 int group[] = {3, 2, 3};
3284 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3285 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3286 "IPv4 traffic errors statistics (3)"};
3287 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3288 "idisc/s", "odisc/s",
3289 "onort/s", "asmf/s", "fragf/s"};
3290 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3291 static double *spmin, *spmax;
3293 static int *outsize;
3295 if (action & F_BEGIN) {
3297 * Allocate arrays that will contain the graphs data
3298 * and the min/max values.
3300 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3303 if (action & F_MAIN) {
3304 /* Check for min/max values */
3305 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3306 itv, spmin, spmax, g_fields);
3309 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3310 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3311 out, outsize, svg_p->restart);
3313 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3314 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3315 out + 1, outsize + 1, svg_p->restart);
3317 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3318 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3319 out + 2, outsize + 2, svg_p->restart);
3321 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3322 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3323 out + 3, outsize + 3, svg_p->restart);
3325 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3326 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3327 out + 4, outsize + 4, svg_p->restart);
3329 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3330 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3331 out + 5, outsize + 5, svg_p->restart);
3333 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3334 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3335 out + 6, outsize + 6, svg_p->restart);
3337 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3338 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3339 out + 7, outsize + 7, svg_p->restart);
3342 if (action & F_END) {
3343 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3344 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3346 /* Free remaining structures */
3347 free_graphs(out, outsize, spmin, spmax);
3352 ***************************************************************************
3353 * Display ICMPv4 traffic statistics in SVG.
3356 * @a Activity structure with statistics.
3357 * @curr Index in array for current sample statistics.
3358 * @action Action expected from current function.
3359 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3360 * flag indicating that a restart record has been previously
3361 * found (.@restart) and time used for the X axis origin
3363 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3364 * @record_hdr Pointer on record header of current stats sample.
3365 ***************************************************************************
3367 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3368 unsigned long long itv, struct record_header *record_hdr)
3370 struct stats_net_icmp
3371 *snic = (struct stats_net_icmp *) a->buf[curr],
3372 *snip = (struct stats_net_icmp *) a->buf[!curr];
3373 int group[] = {2, 4, 4, 4};
3374 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3376 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3377 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3378 char *g_title[] = {"imsg/s", "omsg/s",
3379 "iech/s", "iechr/s", "oech/s", "oechr/s",
3380 "itm/s", "itmr/s", "otm/s", "otmr/s",
3381 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3382 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3383 static double *spmin, *spmax;
3385 static int *outsize;
3387 if (action & F_BEGIN) {
3389 * Allocate arrays that will contain the graphs data
3390 * and the min/max values.
3392 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3395 if (action & F_MAIN) {
3396 /* Check for min/max values */
3397 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3398 itv, spmin, spmax, g_fields);
3401 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3402 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3403 out, outsize, svg_p->restart);
3405 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3406 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3407 out + 1, outsize + 1, svg_p->restart);
3409 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3410 S_VALUE(snip->InEchos, snic->InEchos, itv),
3411 out + 2, outsize + 2, svg_p->restart);
3413 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3414 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3415 out + 3, outsize + 3, svg_p->restart);
3417 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3418 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3419 out + 4, outsize + 4, svg_p->restart);
3421 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3422 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3423 out + 5, outsize + 5, svg_p->restart);
3425 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3426 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3427 out + 6, outsize + 6, svg_p->restart);
3429 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3430 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3431 out + 7, outsize + 7, svg_p->restart);
3433 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3434 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3435 out + 8, outsize + 8, svg_p->restart);
3437 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3438 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3439 out + 9, outsize + 9, svg_p->restart);
3441 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3442 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3443 out + 10, outsize + 10, svg_p->restart);
3445 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3446 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3447 out + 11, outsize + 11, svg_p->restart);
3449 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3450 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3451 out + 12, outsize + 12, svg_p->restart);
3453 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3454 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3455 out + 13, outsize + 13, svg_p->restart);
3458 if (action & F_END) {
3459 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3460 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3462 /* Free remaining structures */
3463 free_graphs(out, outsize, spmin, spmax);
3468 ***************************************************************************
3469 * Display ICMPv4 traffic errors statistics in SVG.
3472 * @a Activity structure with statistics.
3473 * @curr Index in array for current sample statistics.
3474 * @action Action expected from current function.
3475 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3476 * flag indicating that a restart record has been previously
3477 * found (.@restart) and time used for the X axis origin
3479 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3480 * @record_hdr Pointer on record header of current stats sample.
3481 ***************************************************************************
3483 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3484 unsigned long long itv, struct record_header *record_hdr)
3486 struct stats_net_eicmp
3487 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3488 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3489 int group[] = {2, 2, 2, 2, 2, 2};
3490 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3491 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3492 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3493 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3494 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3495 char *g_title[] = {"ierr/s", "oerr/s",
3496 "idstunr/s", "odstunr/s",
3497 "itmex/s", "otmex/s",
3498 "iparmpb/s", "oparmpb/s",
3499 "isrcq/s", "osrcq/s",
3500 "iredir/s", "oredir/s"};
3501 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3502 static double *spmin, *spmax;
3504 static int *outsize;
3506 if (action & F_BEGIN) {
3508 * Allocate arrays that will contain the graphs data
3509 * and the min/max values.
3511 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3514 if (action & F_MAIN) {
3515 /* Check for min/max values */
3516 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3517 itv, spmin, spmax, g_fields);
3520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3521 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3522 out, outsize, svg_p->restart);
3524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3525 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3526 out + 1, outsize + 1, svg_p->restart);
3528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3529 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3530 out + 2, outsize + 2, svg_p->restart);
3532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3533 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3534 out + 3, outsize + 3, svg_p->restart);
3536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3537 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3538 out + 4, outsize + 4, svg_p->restart);
3540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3541 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3542 out + 5, outsize + 5, svg_p->restart);
3544 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3545 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3546 out + 6, outsize + 6, svg_p->restart);
3548 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3549 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3550 out + 7, outsize + 7, svg_p->restart);
3552 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3553 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3554 out + 8, outsize + 8, svg_p->restart);
3556 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3557 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3558 out + 9, outsize + 9, svg_p->restart);
3560 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3561 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3562 out + 10, outsize + 10, svg_p->restart);
3564 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3565 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3566 out + 11, outsize + 11, svg_p->restart);
3569 if (action & F_END) {
3570 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3571 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3573 /* Free remaining structures */
3574 free_graphs(out, outsize, spmin, spmax);
3579 ***************************************************************************
3580 * Display TCPv4 traffic statistics in SVG.
3583 * @a Activity structure with statistics.
3584 * @curr Index in array for current sample statistics.
3585 * @action Action expected from current function.
3586 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3587 * flag indicating that a restart record has been previously
3588 * found (.@restart) and time used for the X axis origin
3590 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3591 * @record_hdr Pointer on record header of current stats sample.
3592 ***************************************************************************
3594 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3595 unsigned long long itv, struct record_header *record_hdr)
3597 struct stats_net_tcp
3598 *sntc = (struct stats_net_tcp *) a->buf[curr],
3599 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3600 int group[] = {2, 2};
3601 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3602 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3603 char *g_title[] = {"active/s", "passive/s",
3604 "iseg/s", "oseg/s"};
3605 int g_fields[] = {0, 1, 2, 3};
3606 static double *spmin, *spmax;
3608 static int *outsize;
3610 if (action & F_BEGIN) {
3612 * Allocate arrays that will contain the graphs data
3613 * and the min/max values.
3615 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3618 if (action & F_MAIN) {
3619 /* Check for min/max values */
3620 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3621 itv, spmin, spmax, g_fields);
3624 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3625 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3626 out, outsize, svg_p->restart);
3628 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3629 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3630 out + 1, outsize + 1, svg_p->restart);
3632 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3633 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3634 out + 2, outsize + 2, svg_p->restart);
3636 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3637 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3638 out + 3, outsize + 3, svg_p->restart);
3641 if (action & F_END) {
3642 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3643 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3645 /* Free remaining structures */
3646 free_graphs(out, outsize, spmin, spmax);
3651 ***************************************************************************
3652 * Display TCPv4 traffic errors statistics in SVG.
3655 * @a Activity structure with statistics.
3656 * @curr Index in array for current sample statistics.
3657 * @action Action expected from current function.
3658 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3659 * flag indicating that a restart record has been previously
3660 * found (.@restart) and time used for the X axis origin
3662 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3663 * @record_hdr Pointer on record header of current stats sample.
3664 ***************************************************************************
3666 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3667 unsigned long long itv, struct record_header *record_hdr)
3669 struct stats_net_etcp
3670 *snetc = (struct stats_net_etcp *) a->buf[curr],
3671 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3672 int group[] = {2, 3};
3673 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3674 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3675 char *g_title[] = {"atmptf/s", "estres/s",
3676 "retrans/s", "isegerr/s", "orsts/s"};
3677 int g_fields[] = {0, 1, 2, 3, 4};
3678 static double *spmin, *spmax;
3680 static int *outsize;
3682 if (action & F_BEGIN) {
3684 * Allocate arrays that will contain the graphs data
3685 * and the min/max values.
3687 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3690 if (action & F_MAIN) {
3691 /* Check for min/max values */
3692 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3693 itv, spmin, spmax, g_fields);
3696 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3697 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3698 out, outsize, svg_p->restart);
3700 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3701 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3702 out + 1, outsize + 1, svg_p->restart);
3704 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3705 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3706 out + 2, outsize + 2, svg_p->restart);
3708 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3709 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3710 out + 3, outsize + 3, svg_p->restart);
3712 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3713 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3714 out + 4, outsize + 4, svg_p->restart);
3717 if (action & F_END) {
3718 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3719 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3721 /* Free remaining structures */
3722 free_graphs(out, outsize, spmin, spmax);
3727 ***************************************************************************
3728 * Display UDPv4 traffic statistics in SVG.
3731 * @a Activity structure with statistics.
3732 * @curr Index in array for current sample statistics.
3733 * @action Action expected from current function.
3734 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3735 * flag indicating that a restart record has been previously
3736 * found (.@restart) and time used for the X axis origin
3738 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3739 * @record_hdr Pointer on record header of current stats sample.
3740 ***************************************************************************
3742 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3743 unsigned long long itv, struct record_header *record_hdr)
3745 struct stats_net_udp
3746 *snuc = (struct stats_net_udp *) a->buf[curr],
3747 *snup = (struct stats_net_udp *) a->buf[!curr];
3748 int group[] = {2, 2};
3749 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3750 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3751 char *g_title[] = {"idgm/s", "odgm/s",
3752 "noport/s", "idgmerr/s"};
3753 int g_fields[] = {0, 1, 2, 3};
3754 static double *spmin, *spmax;
3756 static int *outsize;
3758 if (action & F_BEGIN) {
3760 * Allocate arrays that will contain the graphs data
3761 * and the min/max values.
3763 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3766 if (action & F_MAIN) {
3767 /* Check for min/max values */
3768 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3769 itv, spmin, spmax, g_fields);
3772 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3773 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3774 out, outsize, svg_p->restart);
3776 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3777 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3778 out + 1, outsize + 1, svg_p->restart);
3780 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3781 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3782 out + 2, outsize + 2, svg_p->restart);
3784 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3785 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3786 out + 3, outsize + 3, svg_p->restart);
3789 if (action & F_END) {
3790 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3791 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3793 /* Free remaining structures */
3794 free_graphs(out, outsize, spmin, spmax);
3799 ***************************************************************************
3800 * Display IPV6 socket statistics in SVG.
3803 * @a Activity structure with statistics.
3804 * @curr Index in array for current sample statistics.
3805 * @action Action expected from current function.
3806 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3807 * flag indicating that a restart record has been previously
3808 * found (.@restart) and time used for the X axis origin
3810 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3811 * @record_hdr Pointer on record header of current stats sample.
3812 ***************************************************************************
3814 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3815 unsigned long long itv, struct record_header *record_hdr)
3817 struct stats_net_sock6
3818 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3820 int g_type[] = {SVG_LINE_GRAPH};
3821 char *title[] = {"IPv6 sockets statistics"};
3822 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3823 int g_fields[] = {0, 1, 2, 3};
3824 static double *spmin, *spmax;
3826 static int *outsize;
3828 if (action & F_BEGIN) {
3830 * Allocate arrays that will contain the graphs data
3831 * and the min/max values.
3833 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3836 if (action & F_MAIN) {
3837 /* Check for min/max values */
3838 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3839 itv, spmin, spmax, g_fields);
3841 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3842 (unsigned long long) snsc->tcp6_inuse,
3843 out, outsize, svg_p->restart);
3845 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3846 (unsigned long long) snsc->udp6_inuse,
3847 out + 1, outsize + 1, svg_p->restart);
3849 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3850 (unsigned long long) snsc->raw6_inuse,
3851 out + 2, outsize + 2, svg_p->restart);
3853 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3854 (unsigned long long) snsc->frag6_inuse,
3855 out + 3, outsize + 3, svg_p->restart);
3858 if (action & F_END) {
3859 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3860 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3862 /* Free remaining structures */
3863 free_graphs(out, outsize, spmin, spmax);
3868 ***************************************************************************
3869 * Display IPv6 traffic statistics in SVG.
3872 * @a Activity structure with statistics.
3873 * @curr Index in array for current sample statistics.
3874 * @action Action expected from current function.
3875 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3876 * flag indicating that a restart record has been previously
3877 * found (.@restart) and time used for the X axis origin
3879 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3880 * @record_hdr Pointer on record header of current stats sample.
3881 ***************************************************************************
3883 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3884 unsigned long long itv, struct record_header *record_hdr)
3886 struct stats_net_ip6
3887 *snic = (struct stats_net_ip6 *) a->buf[curr],
3888 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3889 int group[] = {4, 2, 2, 2};
3890 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3892 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3893 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3894 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3895 "asmrq6/s", "asmok6/s",
3896 "imcpck6/s", "omcpck6/s",
3897 "fragok6/s", "fragcr6/s"};
3898 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3899 static double *spmin, *spmax;
3901 static int *outsize;
3903 if (action & F_BEGIN) {
3905 * Allocate arrays that will contain the graphs data
3906 * and the min/max values.
3908 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3911 if (action & F_MAIN) {
3912 /* Check for min/max values */
3913 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3914 itv, spmin, spmax, g_fields);
3917 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3918 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3919 out, outsize, svg_p->restart);
3921 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3922 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3923 out + 1, outsize + 1, svg_p->restart);
3925 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3926 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3927 out + 2, outsize + 2, svg_p->restart);
3929 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3930 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3931 out + 3, outsize + 3, svg_p->restart);
3933 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3934 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3935 out + 4, outsize + 4, svg_p->restart);
3937 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3938 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3939 out + 5, outsize + 5, svg_p->restart);
3941 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3942 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3943 out + 6, outsize + 6, svg_p->restart);
3945 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3946 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3947 out + 7, outsize + 7, svg_p->restart);
3949 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3950 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3951 out + 8, outsize + 8, svg_p->restart);
3953 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3954 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3955 out + 9, outsize + 9, svg_p->restart);
3958 if (action & F_END) {
3959 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3960 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
3962 /* Free remaining structures */
3963 free_graphs(out, outsize, spmin, spmax);
3968 ***************************************************************************
3969 * Display IPv6 traffic errors statistics in SVG.
3972 * @a Activity structure with statistics.
3973 * @curr Index in array for current sample statistics.
3974 * @action Action expected from current function.
3975 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3976 * flag indicating that a restart record has been previously
3977 * found (.@restart) and time used for the X axis origin
3979 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3980 * @record_hdr Pointer on record header of current stats sample.
3981 ***************************************************************************
3983 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3984 unsigned long long itv, struct record_header *record_hdr)
3986 struct stats_net_eip6
3987 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3988 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3989 int group[] = {4, 2, 2, 3};
3990 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3992 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3993 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3994 "IPv6 traffic errors statistics (5)"};
3995 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3996 "idisc6/s", "odisc6/s",
3997 "inort6/s", "onort6/s",
3998 "asmf6/s", "fragf6/s", "itrpck6/s"};
3999 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4000 static double *spmin, *spmax;
4002 static int *outsize;
4004 if (action & F_BEGIN) {
4006 * Allocate arrays that will contain the graphs data
4007 * and the min/max values.
4009 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4012 if (action & F_MAIN) {
4013 /* Check for min/max values */
4014 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4015 itv, spmin, spmax, g_fields);
4018 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4019 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
4020 out, outsize, svg_p->restart);
4022 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4023 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
4024 out + 1, outsize + 1, svg_p->restart);
4026 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4027 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
4028 out + 2, outsize + 2, svg_p->restart);
4030 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4031 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
4032 out + 3, outsize + 3, svg_p->restart);
4034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4035 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
4036 out + 4, outsize + 4, svg_p->restart);
4038 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4039 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
4040 out + 5, outsize + 5, svg_p->restart);
4042 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4043 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
4044 out + 6, outsize + 6, svg_p->restart);
4046 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4047 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
4048 out + 7, outsize + 7, svg_p->restart);
4050 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4051 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
4052 out + 8, outsize + 8, svg_p->restart);
4054 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4055 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
4056 out + 9, outsize + 9, svg_p->restart);
4058 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4059 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
4060 out + 10, outsize + 10, svg_p->restart);
4063 if (action & F_END) {
4064 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4065 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4067 /* Free remaining structures */
4068 free_graphs(out, outsize, spmin, spmax);
4073 ***************************************************************************
4074 * Display ICMPv6 traffic statistics in SVG.
4077 * @a Activity structure with statistics.
4078 * @curr Index in array for current sample statistics.
4079 * @action Action expected from current function.
4080 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4081 * flag indicating that a restart record has been previously
4082 * found (.@restart) and time used for the X axis origin
4084 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4085 * @record_hdr Pointer on record header of current stats sample.
4086 ***************************************************************************
4088 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4089 unsigned long long itv, struct record_header *record_hdr)
4091 struct stats_net_icmp6
4092 *snic = (struct stats_net_icmp6 *) a->buf[curr],
4093 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
4094 int group[] = {2, 3, 5, 3, 4};
4095 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4096 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4097 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
4098 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
4099 "ICMPv6 traffic statistics (5)"};
4100 char *g_title[] = {"imsg6/s", "omsg6/s",
4101 "iech6/s", "iechr6/s", "oechr6/s",
4102 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
4103 "irtsol6/s", "ortsol6/s", "irtad6/s",
4104 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
4105 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
4106 static double *spmin, *spmax;
4108 static int *outsize;
4110 if (action & F_BEGIN) {
4112 * Allocate arrays that will contain the graphs data
4113 * and the min/max values.
4115 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
4118 if (action & F_MAIN) {
4119 /* Check for min/max values */
4120 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4121 itv, spmin, spmax, g_fields);
4124 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4125 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
4126 out, outsize, svg_p->restart);
4128 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4129 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
4130 out + 1, outsize + 1, svg_p->restart);
4132 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4133 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
4134 out + 2, outsize + 2, svg_p->restart);
4136 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4137 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
4138 out + 3, outsize + 3, svg_p->restart);
4140 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4141 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
4142 out + 4, outsize + 4, svg_p->restart);
4144 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4145 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
4146 out + 5, outsize + 5, svg_p->restart);
4148 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4149 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
4150 out + 6, outsize + 6, svg_p->restart);
4152 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4153 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
4154 out + 7, outsize + 7, svg_p->restart);
4156 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4157 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
4158 out + 8, outsize + 8, svg_p->restart);
4160 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4161 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
4162 out + 9, outsize + 9, svg_p->restart);
4164 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4165 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
4166 out + 10, outsize + 10, svg_p->restart);
4168 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4169 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
4170 out + 11, outsize + 11, svg_p->restart);
4172 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4173 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
4174 out + 12, outsize + 12, svg_p->restart);
4176 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4177 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
4178 out + 13, outsize + 13, svg_p->restart);
4180 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4181 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
4182 out + 14, outsize + 14, svg_p->restart);
4184 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4185 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
4186 out + 15, outsize + 15, svg_p->restart);
4188 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4189 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
4190 out + 16, outsize + 16, svg_p->restart);
4193 if (action & F_END) {
4194 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4195 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4197 /* Free remaining structures */
4198 free_graphs(out, outsize, spmin, spmax);
4203 ***************************************************************************
4204 * Display ICMPv6 traffic errors statistics in SVG.
4207 * @a Activity structure with statistics.
4208 * @curr Index in array for current sample statistics.
4209 * @action Action expected from current function.
4210 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4211 * flag indicating that a restart record has been previously
4212 * found (.@restart) and time used for the X axis origin
4214 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4215 * @record_hdr Pointer on record header of current stats sample.
4216 ***************************************************************************
4218 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4219 unsigned long long itv, struct record_header *record_hdr)
4221 struct stats_net_eicmp6
4222 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
4223 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
4224 int group[] = {1, 2, 2, 2, 2, 2};
4225 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4226 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4227 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
4228 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
4229 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
4230 char *g_title[] = {"ierr6/s",
4231 "idtunr6/s", "odtunr6/s",
4232 "itmex6/s", "otmex6/s",
4233 "iprmpb6/s", "oprmpb6/s",
4234 "iredir6/s", "oredir6/s",
4235 "ipck2b6/s", "opck2b6/s"};
4236 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4237 static double *spmin, *spmax;
4239 static int *outsize;
4241 if (action & F_BEGIN) {
4243 * Allocate arrays that will contain the graphs data
4244 * and the min/max values.
4246 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4249 if (action & F_MAIN) {
4250 /* Check for min/max values */
4251 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4252 itv, spmin, spmax, g_fields);
4255 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4256 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4257 out, outsize, svg_p->restart);
4259 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4260 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4261 out + 1, outsize + 1, svg_p->restart);
4263 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4264 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4265 out + 2, outsize + 2, svg_p->restart);
4267 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4268 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4269 out + 3, outsize + 3, svg_p->restart);
4271 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4272 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4273 out + 4, outsize + 4, svg_p->restart);
4275 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4276 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4277 out + 5, outsize + 5, svg_p->restart);
4279 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4280 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4281 out + 6, outsize + 6, svg_p->restart);
4283 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4284 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4285 out + 7, outsize + 7, svg_p->restart);
4287 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4288 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4289 out + 8, outsize + 8, svg_p->restart);
4291 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4292 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4293 out + 9, outsize + 9, svg_p->restart);
4295 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4296 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4297 out + 10, outsize + 10, svg_p->restart);
4300 if (action & F_END) {
4301 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4302 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4304 /* Free remaining structures */
4305 free_graphs(out, outsize, spmin, spmax);
4310 ***************************************************************************
4311 * Display UDPv6 traffic statistics in SVG.
4314 * @a Activity structure with statistics.
4315 * @curr Index in array for current sample statistics.
4316 * @action Action expected from current function.
4317 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4318 * flag indicating that a restart record has been previously
4319 * found (.@restart) and time used for the X axis origin
4321 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4322 * @record_hdr Pointer on record header of current stats sample.
4323 ***************************************************************************
4325 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4326 unsigned long long itv, struct record_header *record_hdr)
4328 struct stats_net_udp6
4329 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4330 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4331 int group[] = {2, 2};
4332 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4333 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4334 char *g_title[] = {"idgm6/s", "odgm6/s",
4335 "noport6/s", "idgmer6/s"};
4336 int g_fields[] = {0, 1, 2, 3};
4337 static double *spmin, *spmax;
4339 static int *outsize;
4341 if (action & F_BEGIN) {
4343 * Allocate arrays that will contain the graphs data
4344 * and the min/max values.
4346 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4349 if (action & F_MAIN) {
4350 /* Check for min/max values */
4351 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4352 itv, spmin, spmax, g_fields);
4355 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4356 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4357 out, outsize, svg_p->restart);
4359 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4360 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4361 out + 1, outsize + 1, svg_p->restart);
4363 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4364 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4365 out + 2, outsize + 2, svg_p->restart);
4367 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4368 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4369 out + 3, outsize + 3, svg_p->restart);
4372 if (action & F_END) {
4373 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4374 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4376 /* Free remaining structures */
4377 free_graphs(out, outsize, spmin, spmax);
4382 ***************************************************************************
4383 * Display CPU frequency statistics in SVG.
4386 * @a Activity structure with statistics.
4387 * @curr Index in array for current sample statistics.
4388 * @action Action expected from current function.
4389 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4390 * flag indicating that a restart record has been previously
4391 * found (.@restart) and time used for the X axis origin
4393 * @itv Interval of time in 1/100th of a second (unused here).
4394 * @record_hdr Pointer on record header of current stats sample.
4395 ***************************************************************************
4397 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4398 unsigned long long itv, struct record_header *record_hdr)
4400 struct stats_pwr_cpufreq *spc, *spp;
4402 int g_type[] = {SVG_LINE_GRAPH};
4403 char *title[] = {"CPU clock frequency"};
4404 char *g_title[] = {"MHz"};
4405 static double *spmin, *spmax;
4407 static int *outsize;
4410 if (action & F_BEGIN) {
4412 * Allocate arrays that will contain the graphs data
4413 * and the min/max values.
4415 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4418 if (action & F_MAIN) {
4420 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4422 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4423 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4425 /* Should current CPU (including CPU "all") be displayed? */
4426 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4431 * Note: Don't skip offline CPU here as it is needed
4432 * to make the graph go though 0.
4436 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4437 ((double) spp->cpufreq) / 100,
4438 ((double) spc->cpufreq) / 100,
4439 out + i, outsize + i, svg_p->restart, svg_p->dt,
4440 spmin + i, spmax + i);
4444 if (action & F_END) {
4448 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
4450 /* Should current CPU (including CPU "all") be displayed? */
4451 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4456 /* This is CPU "all" */
4457 strcpy(item_name, K_LOWERALL);
4461 * If the maximum frequency reached by the CPU is 0, then
4462 * the CPU has been offline on the whole period.
4463 * => Don't display it.
4465 if (*(spmax + i) == 0)
4468 sprintf(item_name, "%d", i - 1);
4471 if (draw_activity_graphs(a->g_nr, g_type,
4472 title, g_title, item_name, group,
4473 spmin + i, spmax + i, out + i, outsize + i,
4474 svg_p, record_hdr, i, a, xid)) {
4479 /* Free remaining structures */
4480 free_graphs(out, outsize, spmin, spmax);
4485 ***************************************************************************
4486 * Display fan statistics in SVG.
4489 * @a Activity structure with statistics.
4490 * @curr Index in array for current sample statistics.
4491 * @action Action expected from current function.
4492 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4493 * flag indicating that a restart record has been previously
4494 * found (.@restart) and time used for the X axis origin
4496 * @itv Interval of time in 1/100th of a second (unused here).
4497 * @record_hdr Pointer on record header of current stats sample.
4498 ***************************************************************************
4500 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4501 unsigned long long itv, struct record_header *record_hdr)
4503 struct stats_pwr_fan *spc, *spp;
4505 int g_type[] = {SVG_LINE_GRAPH};
4506 char *title[] = {"Fans speed"};
4507 char *g_title[] = {"~rpm"};
4508 static double *spmin, *spmax;
4510 static int *outsize;
4513 if (action & F_BEGIN) {
4515 * Allocate arrays that will contain the graphs data
4516 * and the min/max values.
4518 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4521 if (action & F_MAIN) {
4523 for (i = 0; i < a->nr[curr]; i++) {
4525 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4526 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4529 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4532 out + i, outsize + i, svg_p->restart, svg_p->dt,
4533 spmin + i, spmax + i);
4537 if (action & F_END) {
4538 char item_name[MAX_SENSORS_DEV_LEN + 16];
4541 for (i = 0; i < a->item_list_sz; i++) {
4543 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4545 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4546 item_name[sizeof(item_name) - 1] = '\0';
4548 if (draw_activity_graphs(a->g_nr, g_type,
4549 title, g_title, item_name, group,
4550 spmin + i, spmax + i, out + i, outsize + i,
4551 svg_p, record_hdr, FALSE, a, xid)) {
4556 /* Free remaining structures */
4557 free_graphs(out, outsize, spmin, spmax);
4562 ***************************************************************************
4563 * Display temperature statistics in SVG.
4566 * @a Activity structure with statistics.
4567 * @curr Index in array for current sample statistics.
4568 * @action Action expected from current function.
4569 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4570 * flag indicating that a restart record has been previously
4571 * found (.@restart) and time used for the X axis origin
4573 * @itv Interval of time in 1/100th of a second (unused here).
4574 * @record_hdr Pointer on record header of current stats sample.
4575 ***************************************************************************
4577 #define TEMP_ARRAY_SZ 2
4578 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4579 unsigned long long itv, struct record_header *record_hdr)
4581 struct stats_pwr_temp *spc;
4582 int group[] = {1, 1};
4583 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4584 char *title[] = {"Devices temperature (1)",
4585 "Devices temperature (2)"};
4586 char *g_title[] = {"~degC",
4588 static double *spmin, *spmax;
4590 static int *outsize;
4593 if (action & F_BEGIN) {
4595 * Allocate arrays that will contain the graphs data
4596 * and the min/max values.
4598 out = allocate_graph_lines(TEMP_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4601 if (action & F_MAIN) {
4604 /* For each temperature sensor */
4605 for (i = 0; i < a->nr[curr]; i++) {
4607 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4609 /* Look for min/max values */
4610 if (spc->temp < *(spmin + TEMP_ARRAY_SZ * i)) {
4611 *(spmin + TEMP_ARRAY_SZ * i) = spc->temp;
4613 if (spc->temp > *(spmax + TEMP_ARRAY_SZ * i)) {
4614 *(spmax + TEMP_ARRAY_SZ * i) = spc->temp;
4616 tval = (spc->temp_max - spc->temp_min) ?
4617 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4619 if (tval < *(spmin + TEMP_ARRAY_SZ * i + 1)) {
4620 *(spmin + TEMP_ARRAY_SZ * i + 1) = tval;
4622 if (tval > *(spmax + TEMP_ARRAY_SZ * i + 1)) {
4623 *(spmax + TEMP_ARRAY_SZ * i + 1) = tval;
4627 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4629 out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i, svg_p->restart);
4631 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4633 out + TEMP_ARRAY_SZ * i + 1, outsize + TEMP_ARRAY_SZ * i + 1, svg_p->dt);
4637 if (action & F_END) {
4638 char item_name[MAX_SENSORS_DEV_LEN + 16];
4641 for (i = 0; i < a->item_list_sz; i++) {
4643 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4645 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4646 item_name[sizeof(item_name) - 1] = '\0';
4648 if (draw_activity_graphs(a->g_nr, g_type,
4649 title, g_title, item_name, group,
4650 spmin + TEMP_ARRAY_SZ * i, spmax + TEMP_ARRAY_SZ * i,
4651 out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i,
4652 svg_p, record_hdr, FALSE, a, xid)) {
4657 /* Free remaining structures */
4658 free_graphs(out, outsize, spmin, spmax);
4663 ***************************************************************************
4664 * Display voltage inputs statistics in SVG.
4667 * @a Activity structure with statistics.
4668 * @curr Index in array for current sample statistics.
4669 * @action Action expected from current function.
4670 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4671 * flag indicating that a restart record has been previously
4672 * found (.@restart) and time used for the X axis origin
4674 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4675 * @record_hdr Pointer on record header of current stats sample.
4676 ***************************************************************************
4678 #define IN_ARRAY_SZ 2
4679 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4680 unsigned long long itv, struct record_header *record_hdr)
4682 struct stats_pwr_in *spc;
4683 int group[] = {1, 1};
4684 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4685 char *title[] = {"Voltage inputs statistics (1)",
4686 "Voltage inputs statistics (2)"};
4687 char *g_title[] = {"inV",
4689 static double *spmin, *spmax;
4691 static int *outsize;
4694 if (action & F_BEGIN) {
4696 * Allocate arrays that will contain the graphs data
4697 * and the min/max values.
4699 out = allocate_graph_lines(IN_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4702 if (action & F_MAIN) {
4705 /* For each voltage input sensor */
4706 for (i = 0; i < a->nr[curr]; i++) {
4708 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4710 /* Look for min/max values */
4711 if (spc->in < *(spmin + IN_ARRAY_SZ * i)) {
4712 *(spmin + IN_ARRAY_SZ * i) = spc->in;
4714 if (spc->in > *(spmax + IN_ARRAY_SZ * i)) {
4715 *(spmax + IN_ARRAY_SZ * i) = spc->in;
4717 tval = (spc->in_max - spc->in_min) ?
4718 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4720 if (tval < *(spmin + IN_ARRAY_SZ * i + 1)) {
4721 *(spmin + IN_ARRAY_SZ * i + 1) = tval;
4723 if (tval > *(spmax + IN_ARRAY_SZ * i + 1)) {
4724 *(spmax + IN_ARRAY_SZ * i + 1) = tval;
4728 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4730 out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i, svg_p->restart);
4732 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4734 out + IN_ARRAY_SZ * i + 1, outsize + IN_ARRAY_SZ * i + 1, svg_p->dt);
4738 if (action & F_END) {
4739 char item_name[MAX_SENSORS_DEV_LEN + 16];
4742 for (i = 0; i < a->item_list_sz; i++) {
4744 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4746 snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
4747 item_name[sizeof(item_name) - 1] = '\0';
4749 if (draw_activity_graphs(a->g_nr, g_type,
4750 title, g_title, item_name, group,
4751 spmin + IN_ARRAY_SZ * i, spmax + IN_ARRAY_SZ * i,
4752 out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i,
4753 svg_p, record_hdr, FALSE, a, xid)) {
4758 /* Free remaining structures */
4759 free_graphs(out, outsize, spmin, spmax);
4764 * **************************************************************************
4765 * Display batteries statistics in SVG.
4768 * @a Activity structure with statistics.
4769 * @curr Index in array for current sample statistics.
4770 * @action Action expected from current function.
4771 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4772 * flag indicating that a restart record has been previously
4773 * found (.@restart) and time used for the X axis origin
4775 * @itv Interval of time in 1/100th of a second.
4776 * @record_hdr Pointer on record header of current stats sample.
4777 ***************************************************************************
4779 __print_funct_t svg_print_pwr_bat_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4780 unsigned long long itv, struct record_header *record_hdr)
4782 struct stats_pwr_bat *spbc;
4784 int g_type[] = {SVG_BAR_GRAPH};
4785 char *title[] = {"Batteries capacity"};
4786 char *g_title[] = {"~%cap"};
4787 static double *spmin, *spmax;
4789 static int *outsize;
4792 if (action & F_BEGIN) {
4794 * Allocate arrays that will contain the graphs data
4795 * and the min/max values.
4797 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4800 if (action & F_MAIN) {
4801 /* For each battery */
4802 for (i = 0; i < a->nr[curr]; i++) {
4804 spbc = (struct stats_pwr_bat *) ((char *) a->buf[curr] + i * a->msize);
4806 /* Look for min/max values */
4807 if (spbc->capacity < *(spmin + i)) {
4808 *(spmin + i) = spbc->capacity;
4810 if (spbc->capacity > *(spmax + i)) {
4811 *(spmax + i) = spbc->capacity;
4815 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4817 (unsigned int) spbc->capacity,
4818 out + i, outsize + i,
4823 if (action & F_END) {
4827 for (i = 0; i < a->item_list_sz; i++) {
4829 spbc = (struct stats_pwr_bat *) ((char *) a->buf[curr] + i * a->msize);
4831 snprintf(item_name, sizeof(item_name), "BAT%d", (int) spbc->bat_id);
4832 item_name[sizeof(item_name) - 1] = '\0';
4834 if (draw_activity_graphs(a->g_nr, g_type,
4835 title, g_title, item_name, group,
4836 spmin + i, spmax + i,
4837 out + i, outsize + i,
4838 svg_p, record_hdr, FALSE, a, xid)) {
4843 /* Free remaining structures */
4844 free_graphs(out, outsize, spmin, spmax);
4849 ***************************************************************************
4850 * Display huge pages statistics in SVG.
4853 * @a Activity structure with statistics.
4854 * @curr Index in array for current sample statistics.
4855 * @action Action expected from current function.
4856 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4857 * flag indicating that a restart record has been previously
4858 * found (.@restart) and time used for the X axis origin
4860 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4861 * @record_hdr Pointer on record header of current stats sample.
4862 ***************************************************************************
4864 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4865 unsigned long long itv, struct record_header *record_hdr)
4868 *smc = (struct stats_huge *) a->buf[curr];
4869 int group[] = {4, 1};
4870 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4871 char *title[] = {"Huge pages utilization (1)",
4872 "Huge pages utilization (2)"};
4873 char *g_title[] = {"~kbhugfree", "~kbhugused", "~kbhugrsvd", "~kbhugsurp",
4875 int g_fields[] = {0, 5, 2, 3};
4876 static double *spmin, *spmax;
4878 static int *outsize;
4880 if (action & F_BEGIN) {
4882 * Allocate arrays that will contain the graphs data
4883 * and the min/max values.
4884 * Allocate one additional array (#5) to save min/max
4885 * values for tlhkb (unused).
4887 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
4890 if (action & F_MAIN) {
4893 /* Check for min/max values */
4894 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
4895 itv, spmin, spmax, g_fields);
4897 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4898 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4900 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4901 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4903 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4904 if (tval < *(spmin + 4)) {
4905 *(spmin + 4) = tval;
4907 if (tval > *(spmax + 4)) {
4908 *(spmax + 4) = tval;
4912 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4913 (unsigned long long) smc->frhkb,
4914 out, outsize, svg_p->restart);
4916 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4917 (unsigned long long) smc->tlhkb - smc->frhkb,
4918 out + 1, outsize + 1, svg_p->restart);
4920 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4921 (unsigned long long) smc->rsvdhkb,
4922 out + 2, outsize + 2, svg_p->restart);
4924 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4925 (unsigned long long) smc->surphkb,
4926 out + 3, outsize + 3, svg_p->restart);
4928 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4930 out + 4, outsize + 4, svg_p->dt);
4933 if (action & F_END) {
4934 draw_activity_graphs(a->g_nr, g_type,
4935 title, g_title, NULL, group,
4936 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
4938 /* Free remaining structures */
4939 free_graphs(out, outsize, spmin, spmax);
4944 ***************************************************************************
4945 * Display filesystem statistics in SVG.
4948 * @a Activity structure with statistics.
4949 * @curr Index in array for current sample statistics.
4950 * @action Action expected from current function.
4951 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4952 * flag indicating that a restart record has been previously
4953 * found (.@restart) and time used for the X axis origin
4955 * @itv Interval of time in 1/100th of a second (unused here).
4956 * @record_hdr Pointer on record header of current stats sample.
4957 ***************************************************************************
4959 #define FS_ARRAY_SZ 8
4960 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4961 unsigned long long itv, struct record_header *record_hdr)
4963 struct stats_filesystem *sfc, *sfp;
4964 int group[] = {2, 2, 2, 1};
4965 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4966 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4967 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4968 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4969 char *g_title[] = {"~MBfsfree", "~MBfsused",
4970 "%ufsused", "%fsused",
4971 "Ifree/1000", "Iused/1000",
4973 static double *spmin, *spmax;
4975 static int *outsize;
4976 char *dev_name, *item_name;
4978 int i, k, pos, restart;
4980 if (action & F_BEGIN) {
4982 * Allocate arrays (#0..6) that will contain the graphs data
4983 * and the min/max values.
4984 * Also allocate an additional arrays (#7) for each filesystem:
4985 * out + 7 will contain the persistent or standard fs name, or mount point.
4987 out = allocate_graph_lines(FS_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
4990 if (action & F_MAIN) {
4991 /* For each filesystem structure */
4992 for (i = 0; i < a->nr[curr]; i++) {
4993 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4995 /* Get name to display (persistent or standard fs name, or mount point) */
4996 dev_name = get_fs_name_to_display(a, flags, sfc);
4998 if (a->item_list != NULL) {
4999 /* A list of devices has been entered on the command line */
5000 if (!search_list_item(a->item_list, dev_name))
5001 /* Device not found */
5005 /* Look for corresponding graph */
5006 for (k = 0; k < a->item_list_sz; k++) {
5007 item_name = *(out + k * FS_ARRAY_SZ + 7);
5008 if (!strcmp(dev_name, item_name))
5013 if (k == a->item_list_sz) {
5014 /* Graph not found: Look for first free entry */
5015 for (k = 0; k < a->item_list_sz; k++) {
5016 item_name = *(out + k * FS_ARRAY_SZ + 7);
5017 if (!strcmp(item_name, ""))
5020 if (k == a->item_list_sz) {
5021 /* No free graph entry: Ignore it (should never happen) */
5023 fprintf(stderr, "%s: Name=%s\n",
5024 __FUNCTION__, sfc->fs_name);
5030 pos = k * FS_ARRAY_SZ;
5032 item_name = *(out + pos + 7);
5033 if (!item_name[0]) {
5034 /* Save filesystem name and mount point (if not already done) */
5035 strncpy(item_name, dev_name, CHUNKSIZE);
5036 item_name[CHUNKSIZE - 1] = '\0';
5040 for (k = 0; k < a->nr[!curr]; k++) {
5041 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
5042 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
5043 /* Filesystem found in previous sample */
5044 restart = svg_p->restart;
5048 /* Check for min/max values */
5050 /* Compute fsfree min/max values */
5051 tval = (double) sfc->f_bfree;
5052 if (tval > *(spmax + pos)) {
5053 *(spmax + pos) = tval;
5055 if (tval < *(spmin + pos)) {
5056 *(spmin + pos) = tval;
5058 /* Compute fsused min/max values */
5059 tval = (double) (sfc->f_blocks - sfc->f_bfree);
5060 if (tval > *(spmax + pos + 1)) {
5061 *(spmax + pos + 1) = tval;
5063 if (tval < *(spmin + pos + 1)) {
5064 *(spmin + pos + 1) = tval;
5066 /* Compute %ufsused min/max values */
5067 tval = sfc->f_blocks ?
5068 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
5069 if (tval > *(spmax + pos + 2)) {
5070 *(spmax + pos + 2) = tval;
5072 if (tval < *(spmin + pos + 2)) {
5073 *(spmin + pos + 2) = tval;
5075 /* Compute %fsused min/max values */
5076 tval = sfc->f_blocks ?
5077 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
5078 if (tval > *(spmax + pos + 3)) {
5079 *(spmax + pos + 3) = tval;
5081 if (tval < *(spmin + pos + 3)) {
5082 *(spmin + pos + 3) = tval;
5084 /* Compute Ifree min/max values */
5085 tval = (double) sfc->f_ffree;
5086 if (tval > *(spmax + pos + 4)) {
5087 *(spmax + pos + 4) = tval;
5089 if (tval < *(spmin + pos + 4)) {
5090 *(spmin + pos + 4) = tval;
5092 /* Compute Iused min/max values */
5093 tval = (double) (sfc->f_files - sfc->f_ffree);
5094 if (tval > *(spmax + pos + 5)) {
5095 *(spmax + pos + 5) = tval;
5097 if (tval < *(spmin + pos + 5)) {
5098 *(spmin + pos + 5) = tval;
5100 /* Compute %Iused min/max values */
5101 tval = sfc->f_files ?
5102 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
5103 if (tval > *(spmax + pos + 6)) {
5104 *(spmax + pos + 6) = tval;
5106 if (tval < *(spmin + pos + 6)) {
5107 *(spmin + pos + 6) = tval;
5111 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5112 (double) sfc->f_bfree / 1024 / 1024,
5113 out + pos, outsize + pos, restart);
5115 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5116 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
5117 out + pos + 1, outsize + pos + 1, restart);
5119 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5122 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
5123 out + pos + 2, outsize + pos + 2, svg_p->dt);
5125 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5128 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
5129 out + pos + 3, outsize + pos + 3, svg_p->dt);
5131 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5132 ((double) sfc->f_ffree) / 1000,
5133 out + pos + 4, outsize + pos + 4, restart);
5135 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5136 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
5137 out + pos + 5, outsize + pos + 5, restart);
5139 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5142 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
5143 out + pos + 6, outsize + pos + 6, svg_p->dt);
5147 if (action & F_END) {
5150 for (i = 0; i < a->item_list_sz; i++) {
5152 /* Check if there is something to display */
5153 pos = i * FS_ARRAY_SZ;
5157 /* Conversion B -> MiB and inodes/1000 */
5158 for (k = 0; k < 2; k++) {
5159 *(spmin + pos + k) /= (1024 * 1024);
5160 *(spmax + pos + k) /= (1024 * 1024);
5161 *(spmin + pos + 4 + k) /= 1000;
5162 *(spmax + pos + 4 + k) /= 1000;
5165 item_name = *(out + pos + 7);
5167 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
5168 spmin + pos, spmax + pos, out + pos, outsize + pos,
5169 svg_p, record_hdr, FALSE, a, xid)) {
5174 /* Free remaining structures */
5175 free_graphs(out, outsize, spmin, spmax);
5180 ***************************************************************************
5181 * Display Fibre Channel HBA statistics in SVG.
5184 * @a Activity structure with statistics.
5185 * @curr Index in array for current sample statistics.
5186 * @action Action expected from current function.
5187 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5188 * flag indicating that a restart record has been previously
5189 * found (.@restart) and time used for the X axis origin
5191 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5192 * @record_hdr Pointer on record header of current stats sample.
5193 ***************************************************************************
5195 #define FC_ARRAY_SZ 5
5196 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5197 unsigned long long itv, struct record_header *record_hdr)
5199 struct stats_fchost *sfcc, *sfcp, sfczero;
5200 int group[] = {2, 2};
5201 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5202 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
5203 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
5204 "fch_rxw/s", "fch_txw/s"};
5205 int g_fields[] = {0, 1, 2, 3};
5206 static double *spmin, *spmax;
5208 static int *outsize;
5210 int i, j, j0, k, found, pos, restart, *unregistered;
5212 if (action & F_BEGIN) {
5214 * Allocate arrays (#0..3) that will contain the graphs data
5215 * and the min/max values.
5216 * Also allocate one additional array (#4) that will contain
5217 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
5218 * has either still not been registered, or has been unregistered
5221 out = allocate_graph_lines(FC_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
5224 if (action & F_MAIN) {
5225 memset(&sfczero, 0, sizeof(struct stats_fchost));
5227 * Mark previously registered interfaces as now
5228 * possibly unregistered for all graphs.
5230 for (k = 0; k < a->item_list_sz; k++) {
5231 unregistered = outsize + k * FC_ARRAY_SZ + 4;
5232 if (*unregistered == FALSE) {
5233 *unregistered = MAYBE;
5237 /* For each FC HBA */
5238 for (i = 0; i < a->nr[curr]; i++) {
5241 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
5242 restart = svg_p->restart;
5244 /* Look for corresponding graph */
5245 for (k = 0; k < a->item_list_sz; k++) {
5246 item_name = *(out + k * FC_ARRAY_SZ + 4);
5247 if (!strcmp(sfcc->fchost_name, item_name))
5251 if (k == a->item_list_sz) {
5252 /* Graph not found: Look for first free entry */
5253 for (k = 0; k < a->item_list_sz; k++) {
5254 item_name = *(out + k * FC_ARRAY_SZ + 4);
5255 if (!strcmp(item_name, ""))
5258 if (k == a->item_list_sz) {
5259 /* No free graph entry: Ignore it (should never happen) */
5261 fprintf(stderr, "%s: Name=%s\n",
5262 __FUNCTION__, sfcc->fchost_name);
5268 pos = k * FC_ARRAY_SZ;
5269 unregistered = outsize + pos + 4;
5271 if (a->nr[!curr] > 0) {
5272 /* Look for corresponding structure in previous iteration */
5275 if (j >= a->nr[!curr]) {
5276 j = a->nr[!curr] - 1;
5282 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
5283 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
5287 if (++j >= a->nr[!curr]) {
5295 /* This is a newly registered host */
5301 * If current interface was marked as previously unregistered,
5302 * then set restart variable to TRUE so that the graph will be
5303 * discontinuous, and mark it as now registered.
5305 if (*unregistered == TRUE) {
5308 *unregistered = FALSE;
5310 item_name = *(out + pos + 4);
5311 if (!item_name[0]) {
5312 /* Save FC HBA name */
5313 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
5314 item_name[CHUNKSIZE - 1] = '\0';
5317 /* Look for min/max values */
5318 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
5319 itv, spmin + pos, spmax + pos, g_fields);
5322 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5323 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5324 out + pos, outsize + pos, restart);
5326 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5327 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5328 out + pos + 1, outsize + pos + 1, restart);
5330 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5331 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5332 out + pos + 2, outsize + pos + 2, restart);
5334 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5335 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5336 out + pos + 3, outsize + pos + 3, restart);
5339 /* Mark interfaces not seen here as now unregistered */
5340 for (k = 0; k < a->item_list_sz; k++) {
5341 unregistered = outsize + k * FC_ARRAY_SZ + 4;
5342 if (*unregistered != FALSE) {
5343 *unregistered = TRUE;
5348 if (action & F_END) {
5349 for (i = 0; i < a->item_list_sz; i++) {
5351 /* Check if there is something to display */
5352 pos = i * FC_ARRAY_SZ;
5356 item_name = *(out + pos + 4);
5357 draw_activity_graphs(a->g_nr, g_type,
5358 title, g_title, item_name, group,
5359 spmin + pos, spmax + pos, out + pos, outsize + pos,
5360 svg_p, record_hdr, FALSE, a, i);
5363 /* Free remaining structures */
5364 free_graphs(out, outsize, spmin, spmax);
5369 ***************************************************************************
5370 * Display softnet statistics in SVG.
5373 * @a Activity structure with statistics.
5374 * @curr Index in array for current sample statistics.
5375 * @action Action expected from current function.
5376 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5377 * flag indicating that a restart record has been previously
5378 * found (.@restart) and time used for the X axis origin
5380 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5381 * @record_hdr Pointer on record header of current stats sample.
5382 ***************************************************************************
5384 #define SOFT_ARRAY_SZ 6
5385 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5386 unsigned long long itv, struct record_header *record_hdr)
5388 struct stats_softnet *ssnc, *ssnp, ssnczero;
5389 int group[] = {2, 3, 1};
5390 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5391 char *title[] = {"Software-based network processing statistics (1)",
5392 "Software-based network processing statistics (2)",
5393 "Software-based network processing statistics (3)"};
5394 char *g_title[] = {"total/s", "dropd/s",
5395 "squeezd/s", "rx_rps/s", "flw_lim/s",
5397 int g_fields[] = {0, 1, 2, 3, 4};
5398 unsigned int local_types_nr[] = {0, 0, 5};
5399 static double *spmin, *spmax;
5401 static int *outsize;
5402 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5405 if (action & F_BEGIN) {
5407 * Allocate arrays that will contain the graphs data
5408 * and the min/max values.
5410 out = allocate_graph_lines(SOFT_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
5413 if (action & F_MAIN) {
5416 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5418 /* @nr[curr] cannot normally be greater than @nr_ini */
5419 if (a->nr[curr] > a->nr_ini) {
5420 a->nr_ini = a->nr[curr];
5423 /* Compute statistics for CPU "all" */
5424 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5427 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5428 restart = svg_p->restart;
5430 /* Should current CPU (including CPU "all") be displayed? */
5431 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5435 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5436 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5438 /* Is current CPU marked offline? */
5439 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5441 * Yes and it doesn't follow a RESTART record.
5442 * To add a discontinuity in graph, we simulate
5446 if (svg_p->restart) {
5448 * CPU is offline and it follows a real
5449 * RESTART record. Ignore its current value
5450 * (no previous sample).
5455 pos = i * SOFT_ARRAY_SZ;
5457 /* Check for min/max values */
5458 save_extrema(local_types_nr, (void *) ssnc, (void *) ssnp,
5459 itv, spmin + pos, spmax + pos, g_fields);
5460 if (ssnc->backlog_len < *(spmin + pos + 5)) {
5461 *(spmin + pos + 5) = ssnc->backlog_len;
5463 if (ssnc->backlog_len > *(spmax + pos + 5)) {
5464 *(spmax + pos + 5) = ssnc->backlog_len;
5468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5469 S_VALUE(ssnp->processed, ssnc->processed, itv),
5470 out + pos, outsize + pos, restart);
5472 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5473 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5474 out + pos + 1, outsize + pos + 1, restart);
5476 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5477 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5478 out + pos + 2, outsize + pos + 2, restart);
5480 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5481 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5482 out + pos + 3, outsize + pos + 3, restart);
5484 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5485 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5486 out + pos + 4, outsize + pos + 4, restart);
5488 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
5489 (unsigned long long) ssnc->backlog_len,
5490 out + pos + 5, outsize + pos + 5, restart);
5494 if (action & F_END) {
5497 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
5499 /* Should current CPU (including CPU "all") be displayed? */
5500 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5504 pos = i * SOFT_ARRAY_SZ;
5507 /* This is CPU "all" */
5508 strcpy(item_name, K_LOWERALL);
5511 sprintf(item_name, "%d", i - 1);
5514 draw_activity_graphs(a->g_nr, g_type,
5515 title, g_title, item_name, group,
5516 spmin + pos, spmax + pos, out + pos, outsize + pos,
5517 svg_p, record_hdr, FALSE, a, i);
5520 /* Free remaining structures */
5521 free_graphs(out, outsize, spmin, spmax);
5526 ***************************************************************************
5527 * Display pressure-stall CPU statistics in SVG.
5530 * @a Activity structure with statistics.
5531 * @curr Index in array for current sample statistics.
5532 * @action Action expected from current function.
5533 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5534 * flag indicating that a restart record has been previously
5535 * found (.@restart) and time used for the X axis origin
5537 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5538 * @record_hdr Pointer on record header of current stats sample.
5539 ***************************************************************************
5541 __print_funct_t svg_print_psicpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5542 unsigned long long itv, struct record_header *record_hdr)
5544 struct stats_psi_cpu
5545 *psic = (struct stats_psi_cpu *) a->buf[curr],
5546 *psip = (struct stats_psi_cpu *) a->buf[!curr];
5547 int group[] = {3, 1};
5548 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5549 char *title[] = {"CPU pressure trends (some tasks)", "CPU stall time (some tasks)"};
5550 char *g_title[] = {"%scpu-10", "%scpu-60", "%scpu-300",
5552 static double *spmin, *spmax;
5554 static int *outsize;
5556 if (action & F_BEGIN) {
5558 * Allocate arrays that will contain the graphs data
5559 * and the min/max values.
5561 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
5564 if (action & F_MAIN) {
5567 /* Check for min/max values */
5568 if (psic->some_acpu_10 > *spmax) {
5569 *spmax = psic->some_acpu_10;
5571 if (psic->some_acpu_10 < *spmin) {
5572 *spmin = psic->some_acpu_10;
5574 if (psic->some_acpu_60 > *(spmax + 1)) {
5575 *(spmax + 1) = psic->some_acpu_60;
5577 if (psic->some_acpu_60 < *(spmin + 1)) {
5578 *(spmin + 1) = psic->some_acpu_60;
5580 if (psic->some_acpu_300 > *(spmax + 2)) {
5581 *(spmax + 2) = psic->some_acpu_300;
5583 if (psic->some_acpu_300 < *(spmin + 2)) {
5584 *(spmin + 2) = psic->some_acpu_300;
5586 tval = ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv);
5587 if (tval > *(spmax + 3)) {
5588 *(spmax + 3) = tval;
5590 if (tval < *(spmin + 3)) {
5591 *(spmin + 3) = tval;
5595 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5596 (double) psic->some_acpu_10 / 100,
5597 out, outsize, svg_p->restart);
5599 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5600 (double) psic->some_acpu_60 / 100,
5601 out + 1, outsize + 1, svg_p->restart);
5603 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5604 (double) psic->some_acpu_300 / 100,
5605 out + 2, outsize + 2, svg_p->restart);
5607 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5609 ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv),
5610 out + 3, outsize + 3, svg_p->dt);
5613 if (action & F_END) {
5614 /* Fix min/max values for pressure ratios */
5615 *spmin /= 100; *spmax /= 100;
5616 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5617 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5619 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5620 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5622 /* Free remaining structures */
5623 free_graphs(out, outsize, spmin, spmax);
5628 ***************************************************************************
5629 * Display pressure-stall I/O statistics in SVG.
5632 * @a Activity structure with statistics.
5633 * @curr Index in array for current sample statistics.
5634 * @action Action expected from current function.
5635 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5636 * flag indicating that a restart record has been previously
5637 * found (.@restart) and time used for the X axis origin
5639 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5640 * @record_hdr Pointer on record header of current stats sample.
5641 ***************************************************************************
5643 __print_funct_t svg_print_psiio_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5644 unsigned long long itv, struct record_header *record_hdr)
5647 *psic = (struct stats_psi_io *) a->buf[curr],
5648 *psip = (struct stats_psi_io *) a->buf[!curr];
5649 int group[] = {3, 1, 3, 1};
5650 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5651 char *title[] = {"I/O pressure trends (some tasks)", "I/O stall time (some tasks)",
5652 "I/O pressure trends (full)", "I/O stall time (full)"};
5653 char *g_title[] = {"%sio-10", "%sio-60", "%sio-300",
5655 "%fio-10", "%fio-60", "%fio-300",
5657 static double *spmin, *spmax;
5659 static int *outsize;
5661 if (action & F_BEGIN) {
5663 * Allocate arrays that will contain the graphs data
5664 * and the min/max values.
5666 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5669 if (action & F_MAIN) {
5672 /* Check for min/max values */
5673 if (psic->some_aio_10 > *spmax) {
5674 *spmax = psic->some_aio_10;
5676 if (psic->some_aio_10 < *spmin) {
5677 *spmin = psic->some_aio_10;
5679 if (psic->some_aio_60 > *(spmax + 1)) {
5680 *(spmax + 1) = psic->some_aio_60;
5682 if (psic->some_aio_60 < *(spmin + 1)) {
5683 *(spmin + 1) = psic->some_aio_60;
5685 if (psic->some_aio_300 > *(spmax + 2)) {
5686 *(spmax + 2) = psic->some_aio_300;
5688 if (psic->some_aio_300 < *(spmin + 2)) {
5689 *(spmin + 2) = psic->some_aio_300;
5691 tval = ((double) psic->some_io_total - psip->some_io_total) / (100 * itv);
5692 if (tval > *(spmax + 3)) {
5693 *(spmax + 3) = tval;
5695 if (tval < *(spmin + 3)) {
5696 *(spmin + 3) = tval;
5699 if (psic->full_aio_10 > *(spmax + 4)) {
5700 *(spmax + 4) = psic->full_aio_10;
5702 if (psic->full_aio_10 < *(spmin + 4)) {
5703 *(spmin + 4) = psic->full_aio_10;
5705 if (psic->full_aio_60 > *(spmax + 5)) {
5706 *(spmax + 5) = psic->full_aio_60;
5708 if (psic->full_aio_60 < *(spmin + 5)) {
5709 *(spmin + 5) = psic->full_aio_60;
5711 if (psic->full_aio_300 > *(spmax + 6)) {
5712 *(spmax + 6) = psic->full_aio_300;
5714 if (psic->full_aio_300 < *(spmin + 6)) {
5715 *(spmin + 6) = psic->full_aio_300;
5717 tval = ((double) psic->full_io_total - psip->full_io_total) / (100 * itv);
5718 if (tval > *(spmax + 7)) {
5719 *(spmax + 7) = tval;
5721 if (tval < *(spmin + 7)) {
5722 *(spmin + 7) = tval;
5726 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5727 (double) psic->some_aio_10 / 100,
5728 out, outsize, svg_p->restart);
5730 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5731 (double) psic->some_aio_60 / 100,
5732 out + 1, outsize + 1, svg_p->restart);
5734 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5735 (double) psic->some_aio_300 / 100,
5736 out + 2, outsize + 2, svg_p->restart);
5738 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5740 ((double) psic->some_io_total - psip->some_io_total) / (100 * itv),
5741 out + 3, outsize + 3, svg_p->dt);
5744 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5745 (double) psic->full_aio_10 / 100,
5746 out + 4, outsize + 4, svg_p->restart);
5748 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5749 (double) psic->full_aio_60 / 100,
5750 out + 5, outsize + 5, svg_p->restart);
5752 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5753 (double) psic->full_aio_300 / 100,
5754 out + 6, outsize + 6, svg_p->restart);
5756 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5758 ((double) psic->full_io_total - psip->full_io_total) / (100 * itv),
5759 out + 7, outsize + 7, svg_p->dt);
5762 if (action & F_END) {
5763 /* Fix min/max values for pressure ratios */
5764 *spmin /= 100; *spmax /= 100;
5765 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5766 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5768 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5769 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5770 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5772 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5773 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5775 /* Free remaining structures */
5776 free_graphs(out, outsize, spmin, spmax);
5781 ***************************************************************************
5782 * Display pressure-stall memory statistics in SVG.
5785 * @a Activity structure with statistics.
5786 * @curr Index in array for current sample statistics.
5787 * @action Action expected from current function.
5788 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5789 * flag indicating that a restart record has been previously
5790 * found (.@restart) and time used for the X axis origin
5792 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5793 * @record_hdr Pointer on record header of current stats sample.
5794 ***************************************************************************
5796 __print_funct_t svg_print_psimem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5797 unsigned long long itv, struct record_header *record_hdr)
5799 struct stats_psi_mem
5800 *psic = (struct stats_psi_mem *) a->buf[curr],
5801 *psip = (struct stats_psi_mem *) a->buf[!curr];
5802 int group[] = {3, 1, 3, 1};
5803 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
5804 char *title[] = {"Memory pressure trends (some tasks)", "Memory stall time (some tasks)",
5805 "Memory pressure trends (full)", "Memory stall time (full)"};
5806 char *g_title[] = {"%smem-10", "%smem-60", "%smem-300",
5808 "%fmem-10", "%fmem-60", "%fmem-300",
5810 static double *spmin, *spmax;
5812 static int *outsize;
5814 if (action & F_BEGIN) {
5816 * Allocate arrays that will contain the graphs data
5817 * and the min/max values.
5819 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
5822 if (action & F_MAIN) {
5825 /* Check for min/max values */
5826 if (psic->some_amem_10 > *spmax) {
5827 *spmax = psic->some_amem_10;
5829 if (psic->some_amem_10 < *spmin) {
5830 *spmin = psic->some_amem_10;
5832 if (psic->some_amem_60 > *(spmax + 1)) {
5833 *(spmax + 1) = psic->some_amem_60;
5835 if (psic->some_amem_60 < *(spmin + 1)) {
5836 *(spmin + 1) = psic->some_amem_60;
5838 if (psic->some_amem_300 > *(spmax + 2)) {
5839 *(spmax + 2) = psic->some_amem_300;
5841 if (psic->some_amem_300 < *(spmin + 2)) {
5842 *(spmin + 2) = psic->some_amem_300;
5844 tval = ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv);
5845 if (tval > *(spmax + 3)) {
5846 *(spmax + 3) = tval;
5848 if (tval < *(spmin + 3)) {
5849 *(spmin + 3) = tval;
5852 if (psic->full_amem_10 > *(spmax + 4)) {
5853 *(spmax + 4) = psic->full_amem_10;
5855 if (psic->full_amem_10 < *(spmin + 4)) {
5856 *(spmin + 4) = psic->full_amem_10;
5858 if (psic->full_amem_60 > *(spmax + 5)) {
5859 *(spmax + 5) = psic->full_amem_60;
5861 if (psic->full_amem_60 < *(spmin + 5)) {
5862 *(spmin + 5) = psic->full_amem_60;
5864 if (psic->full_amem_300 > *(spmax + 6)) {
5865 *(spmax + 6) = psic->full_amem_300;
5867 if (psic->full_amem_300 < *(spmin + 6)) {
5868 *(spmin + 6) = psic->full_amem_300;
5870 tval = ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv);
5871 if (tval > *(spmax + 7)) {
5872 *(spmax + 7) = tval;
5874 if (tval < *(spmin + 7)) {
5875 *(spmin + 7) = tval;
5879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5880 (double) psic->some_amem_10 / 100,
5881 out, outsize, svg_p->restart);
5883 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5884 (double) psic->some_amem_60 / 100,
5885 out + 1, outsize + 1, svg_p->restart);
5887 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5888 (double) psic->some_amem_300 / 100,
5889 out + 2, outsize + 2, svg_p->restart);
5891 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5893 ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv),
5894 out + 3, outsize + 3, svg_p->dt);
5897 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5898 (double) psic->full_amem_10 / 100,
5899 out + 4, outsize + 4, svg_p->restart);
5901 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5902 (double) psic->full_amem_60 / 100,
5903 out + 5, outsize + 5, svg_p->restart);
5905 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5906 (double) psic->full_amem_300 / 100,
5907 out + 6, outsize + 6, svg_p->restart);
5909 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
5911 ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv),
5912 out + 7, outsize + 7, svg_p->dt);
5915 if (action & F_END) {
5916 /* Fix min/max values for pressure ratios */
5917 *spmin /= 100; *spmax /= 100;
5918 *(spmin + 1) /= 100; *(spmax + 1) /= 100;
5919 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
5921 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
5922 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
5923 *(spmin + 6) /= 100; *(spmax + 6) /= 100;
5925 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
5926 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
5928 /* Free remaining structures */
5929 free_graphs(out, outsize, spmin, spmax);