2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016 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 ***************************************************************************
31 #include "svg_stats.h"
36 #define _(string) gettext(string)
38 #define _(string) (string)
41 extern unsigned int flags;
42 extern unsigned int dm_major;
44 unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
45 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
46 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
47 0xcc3300, 0xbfbfbf, 0xffffbf, 0xff3300};
48 #define SVG_COLORS_IDX_MASK 0x0f
51 ***************************************************************************
52 * Compare the values of a statistics sample with the max and min values
53 * already found in previous samples for this same activity. If some new
54 * min or max values are found, then save them.
55 * The structure containing the statistics sample is composed of @llu_nr
56 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
57 * followed by @u_nr unsigned int fields.
60 * @llu_nr Number of unsigned long long fields composing the structure.
61 * @lu_nr Number of unsigned long fields composing the structure.
62 * @u_nr Number of unsigned int fields composing the structure.
63 * @cs Pointer on current sample statistics structure.
64 * @ps Pointer on previous sample statistics structure (may be NULL).
65 * @itv Interval of time in jiffies.
66 * @minv Array containing min values already found for this activity.
67 * @maxv Array containing max values already found for this activity.
70 * @minv Array containg the possible new min values for current activity.
71 * @maxv Array containg the possible new max values for current activity.
73 * NB: @minv and @maxv arrays contain values in the same order as the fields
74 * in the statistics structure.
75 ***************************************************************************
77 void save_extrema(int llu_nr, int lu_nr, int u_nr, void *cs, void *ps,
78 unsigned long long itv, double minv[], double maxv[])
80 unsigned long long *lluc, *llup;
81 unsigned long *luc, *lup;
82 unsigned int *uc, *up;
86 /* Compare unsigned long long fields */
87 lluc = (unsigned long long *) cs;
88 llup = (unsigned long long *) ps;
89 for (i = 0; i < llu_nr; i++, m++) {
91 val = S_VALUE(*llup, *lluc, itv);
95 * If no pointer on previous sample has been given
96 * then the value is not a per-second one.
106 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
108 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
112 /* Compare unsigned long fields */
113 luc = (unsigned long *) lluc;
114 lup = (unsigned long *) llup;
115 for (i = 0; i < lu_nr; i++, m++) {
117 val = S_VALUE(*lup, *luc, itv);
128 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
130 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
134 /* Compare unsigned int fields */
135 uc = (unsigned int *) luc;
136 up = (unsigned int *) lup;
137 for (i = 0; i < u_nr; i++, m++) {
139 val = S_VALUE(*up, *uc, itv);
150 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
152 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
158 ***************************************************************************
159 * Find the min and max values of all the graphs that will be drawn in the
160 * same view. The graphs have their own min and max values in
161 * minv[pos...pos+n-1] and maxv[pos...pos+n-1].
164 * @pos Position in array for the first graph extrema value.
165 * @n Number of graphs to scan.
166 * @minv Array containing min values for graphs.
167 * @maxv Array containing max values for graphs.
170 * @gmin Global min value found.
171 * @gmax Global max value found.
172 ***************************************************************************
174 void get_global_extrema(int pos, int n, double minv[], double maxv[], double *gmin, double *gmax)
181 for (i = 1; i < n; i++) {
182 if (minv[pos + i] < *gmin) {
183 *gmin = minv[pos + i];
185 if (maxv[pos + i] > *gmax) {
186 *gmax = maxv[pos + i];
192 ***************************************************************************
193 * Allocate arrays used to save graphs data, min and max values.
194 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
195 * array is returned. This is equivalent to "char data[][n]" where each
196 * element is of indeterminate size and will contain the graph data (eg.
197 * << path d="M12,14 L13,16..." ... >>.
198 * The size of element data[i] is given by outsize[i].
199 * Also allocate an array to save min values (equivalent to "double spmin[n]")
200 * and an array for max values (equivalent to "double spmax[n]").
203 * @n Number of graphs to draw for current activity.
206 * @outsize Array that will contain the sizes of each element in array
207 * of chars. Equivalent to "int outsize[n]" with
208 * outsize[n] = sizeof(data[][n]).
209 * @spmin Array that will contain min values for current activity.
210 * @spmax Array that will contain max values for current activity.
213 * Pointer on array of arrays of chars that will contain the graphs data.
215 * NB: @min and @max arrays contain values in the same order as the fields
216 * in the statistics structure.
217 ***************************************************************************
219 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
226 * Allocate an array of pointers. Each of these pointers will
227 * be an array of chars.
229 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
233 /* Allocate array that will contain the size of each array of chars */
234 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
238 /* Allocate array that will contain the min value of each graph */
239 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
243 /* Allocate array that will contain the max value of each graph */
244 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
248 /* Allocate arrays of chars that will contain graphs data */
249 for (i = 0; i < n; i++) {
250 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
255 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
256 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
257 *(*spmin + i) = DBL_MAX; /* Init min and max values */
258 *(*spmax + i) = -DBL_MAX;
265 ***************************************************************************
266 * Save SVG code for current graph.
269 * @data SVG code to append to current graph definition.
270 * @out Pointer on array of chars for current graph definition.
271 * @outsize Size of array of chars for current graph definition.
274 * @out Pointer on array of chars for current graph definition that
275 * has been updated with the addition of current sample data.
276 * @outsize Array that containing the (possibly new) sizes of each
277 * element in array of chars.
278 ***************************************************************************
280 void save_svg_data(char *data, char **out, int *outsize)
286 /* Determine space left in array */
287 len = *outsize - strlen(out_p) - 1;
288 if (strlen(data) >= len) {
290 * If current array of chars doesn't have enough space left
291 * then reallocate it with CHUNKSIZE more bytes.
293 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
295 *outsize += CHUNKSIZE;
298 strncat(out_p, data, len);
302 ***************************************************************************
303 * Update line graph definition by appending current X,Y coordinates.
306 * @timetag Timestamp in seconds since the epoch for current sample
307 * stats. Will be used as X coordinate.
308 * @value Value of current sample metric. Will be used as Y coordinate.
309 * @out Pointer on array of chars for current graph definition.
310 * @outsize Size of array of chars for current graph definition.
311 * @restart Set to TRUE if a RESTART record has been read since the last
315 * @out Pointer on array of chars for current graph definition that
316 * has been updated with the addition of current sample data.
317 * @outsize Array that containing the (possibly new) sizes of each
318 * element in array of chars.
319 ***************************************************************************
321 void lnappend(unsigned long timetag, double value, char **out, int *outsize, int restart)
325 /* Prepare additional graph definition data */
326 snprintf(data, 128, " %c%lu,%.2f", restart ? 'M' : 'L', timetag, value);
329 save_svg_data(data, out, outsize);
333 ***************************************************************************
334 * Update line graph definition by appending current X,Y coordinates. Use
335 * (unsigned long) integer values here.
338 * @timetag Timestamp in seconds since the epoch for current sample
339 * stats. Will be used as X coordinate.
340 * @value Value of current sample metric. Will be used as Y coordinate.
341 * @out Pointer on array of chars for current graph definition.
342 * @outsize Size of array of chars for current graph definition.
343 * @restart Set to TRUE if a RESTART record has been read since the last
347 * @out Pointer on array of chars for current graph definition that
348 * has been updated with the addition of current sample data.
349 * @outsize Array that containing the (possibly new) sizes of each
350 * element in array of chars.
351 ***************************************************************************
353 void lniappend(unsigned long timetag, unsigned long value, char **out, int *outsize,
358 /* Prepare additional graph definition data */
359 snprintf(data, 128, " %c%lu,%lu", restart ? 'M' : 'L', timetag, value);
362 save_svg_data(data, out, outsize);
366 ***************************************************************************
367 * Update bar graph definition by adding a new rectangle.
370 * @timetag Timestamp in seconds since the epoch for current sample
371 * stats. Will be used as X coordinate.
372 * @value Value of current sample metric. Will be used as rectangle
374 * @offset Offset for Y coordinate.
375 * @out Pointer on array of chars for current graph definition.
376 * @outsize Size of array of chars for current graph definition.
377 * @dt Interval of time in seconds between current and previous
381 * @out Pointer on array of chars for current graph definition that
382 * has been updated with the addition of current sample data.
383 * @outsize Array that containing the (possibly new) sizes of each
384 * element in array of chars.
385 ***************************************************************************
387 void brappend(unsigned long timetag, double offset, double value, char **out, int *outsize,
392 /* Prepare additional graph definition data */
394 /* Dont draw a flat rectangle! */
397 snprintf(data, 128, "<rect x=\"%lu\" y=\"%.2f\" height=\"%.2f\" width=\"%lu\"/>",
398 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
401 save_svg_data(data, out, outsize);
406 ***************************************************************************
407 * Update CPU graph and min/max values for each metric.
410 * @timetag Timestamp in seconds since the epoch for current sample
411 * stats. Will be used as X coordinate.
412 * @offset Offset for Y coordinate.
413 * @value Value of current CPU metric. Will be used as rectangle
415 * @out Pointer on array of chars for current graph definition.
416 * @outsize Size of array of chars for current graph definition.
417 * @dt Interval of time in seconds between current and previous
419 * @spmin Min value already found for this CPU metric.
420 * @spmax Max value already found for this CPU metric.
423 * @offset New offset value, to use to draw next rectangle
424 * @out Pointer on array of chars for current graph definition that
425 * has been updated with the addition of current sample data.
426 * @outsize Array that containing the (possibly new) sizes of each
427 * element in array of chars.
428 ***************************************************************************
430 void cpuappend(unsigned long timetag, double *offset, double value, char **out, int *outsize,
431 unsigned long dt, double *spmin, double *spmax)
433 /* Save min and max values */
434 if (value < *spmin) {
437 if (value > *spmax) {
440 /* Prepare additional graph definition data */
441 brappend(timetag, *offset, value, out, outsize, dt);
447 ***************************************************************************
448 * Update rectangular graph and min/max values.
451 * @timetag Timestamp in seconds since the epoch for current sample
452 * stats. Will be used as X coordinate.
453 * @p_value Metric value for previous sample
454 * @value Metric value for current sample.
455 * @out Pointer on array of chars for current graph definition.
456 * @outsize Size of array of chars for current graph definition.
457 * @restart Set to TRUE if a RESTART record has been read since the last
459 * @dt Interval of time in seconds between current and previous
461 * @spmin Min value already found for this metric.
462 * @spmax Max value already found for this metric.
465 * @out Pointer on array of chars for current graph definition that
466 * has been updated with the addition of current sample data.
467 * @outsize Array that containing the (possibly new) sizes of each
468 * element in array of chars.
469 * @spmin Min value for this metric.
470 * @spmax Max value for this metric.
471 ***************************************************************************
473 void recappend(unsigned long timetag, double p_value, double value, char **out, int *outsize,
474 int restart, unsigned long dt, double *spmin, double *spmax)
476 char data[128], data1[128], data2[128];
478 /* Save min and max values */
479 if (value < *spmin) {
482 if (value > *spmax) {
485 /* Prepare additional graph definition data */
487 snprintf(data1, 128, " M%lu,%.2f", timetag - dt, p_value);
490 if (p_value != value) {
491 snprintf(data2, 128, " L%lu,%.2f", timetag, value);
494 snprintf(data, 128, "%s L%lu,%.2f%s", restart ? data1 : "", timetag, p_value,
495 p_value != value ? data2 : "");
498 save_svg_data(data, out, outsize);
502 ***************************************************************************
503 * Calculate 10 raised to the power of n.
506 * @n Power number to use.
509 * 10 raised to the power of n.
510 ***************************************************************************
512 unsigned int pwr10(int n)
517 for (i = 0; i < n; i++) {
525 ***************************************************************************
526 * Calculate the value on the Y axis between two horizontal lines that will
527 * make the graph background grid.
530 * @lmax Max value reached for this graph.
533 * @dp Number of decimal places for Y graduations.
536 * Value between two horizontal lines.
537 ***************************************************************************
539 double ygrid(double lmax, int *dp)
550 n = (long) (lmax / SVG_H_GRIDNR);
553 return (lmax / SVG_H_GRIDNR);
555 snprintf(val, 32, "%ld", n);
562 return ((double) (((long) (n / e)) * e));
566 ***************************************************************************
567 * Calculate the value on the X axis between two vertical lines that will
568 * make the graph background grid.
571 * @timestart First data timestamp (X coordinate of the first data point).
572 * @timeend Last data timestamp (X coordinate of the last data point).
573 * @v_gridnr Number of vertical lines to display. Its value is normally
574 * SVG_V_GRIDNR, except when option "oneday" is used, in which
575 * case it is set to 12.
578 * Value between two vertical lines.
579 ***************************************************************************
581 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
583 if ((timeend - timestart) <= v_gridnr)
586 return ((timeend - timestart) / v_gridnr);
590 ***************************************************************************
591 * Free global graphs structures.
594 * @out Pointer on array of chars for each graph definition.
595 * @outsize Size of array of chars for each graph definition.
596 * @spmin Array containing min values for graphs.
597 * @spmax Array containing max values for graphs.
598 ***************************************************************************
600 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
617 ***************************************************************************
618 * Skip current view where all graphs have only zero values. This function
619 * is called when option "skipempty" has been used, or when "No data" have
620 * been found for current view.
623 * @out Pointer on array of chars for each graph definition.
624 * @pos Position of current view in the array of graphs definitions.
625 * @group Number of graphs in current view.
628 * @pos Position of next view in the array of graphs definitions.
629 ***************************************************************************
631 void skip_current_graph(char **out, int *pos, int group)
636 for (j = 0; j < group; j++) {
637 out_p = *(out + *pos + j);
639 /* Even if not displayed, current graph data have to be freed */
647 ***************************************************************************
648 * Display all graphs for current activity.
651 * @g_nr Number of sets of graphs (views) to display.
652 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
653 * @title Titles for each set of graphs.
654 * @g_title Titles for each graph.
655 * @item_name Item (network interface, etc.) name.
656 * @group Indicate how graphs are grouped together to make sets.
657 * @spmin Array containing min values for graphs.
658 * @spmax Array containing max values for graphs.
659 * @out Pointer on array of chars for each graph definition.
660 * @outsize Size of array of chars for each graph definition.
661 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
662 * time for the first sample of stats (.@ust_time_first), and
663 * times used as start and end values on the X axis
664 * (.@ust_time_ref and .@ust_time_end).
665 * @record_hdr Pointer on record header of current stats sample.
666 ***************************************************************************
668 void draw_activity_graphs(int g_nr, int g_type, char *title[], char *g_title[], char *item_name,
669 int group[], double *spmin, double *spmax, char **out, int *outsize,
670 struct svg_parm *svg_p, struct record_header *record_hdr)
672 struct record_header stamp;
675 int i, j, dp, pos = 0, views_nr = 0;
677 unsigned int asfactor[16];
679 double lmax, xfactor, yfactor, ypos, gmin, gmax;
680 char cur_time[32], val[32], stmp[32];
682 /* Translate to proper position for current activity */
683 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
685 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
687 /* For each set of graphs which are part of current activity */
688 for (i = 0; i < g_nr; i++) {
690 /* Get global min and max value for current set of graphs */
691 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
693 /* Don't display empty views if requested */
694 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
695 skip_current_graph(out, &pos, group[i]);
698 /* Increment number of views actually displayed */
701 /* Graph background */
702 printf("<rect x=\"0\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
703 (views_nr - 1) * SVG_T_YSIZE,
704 SVG_V_YSIZE, SVG_V_XSIZE);
707 printf("<text x=\"0\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
708 20 + (views_nr - 1) * SVG_T_YSIZE, title[i]);
710 printf(" [%s]", item_name);
713 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
714 "(Min, Max values)</tspan>\n</text>\n",
715 5 + SVG_M_XSIZE + SVG_G_XSIZE,
716 25 + (views_nr - 1) * SVG_T_YSIZE);
719 * At least two samples are needed.
720 * And a min and max value should have been found.
722 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
723 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
725 printf("<text x=\"0\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
726 SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
727 skip_current_graph(out, &pos, group[i]);
732 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
733 SVG_M_XSIZE, SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE,
734 SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE,
735 SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
737 for (j = 0; j < 16; j++) {
738 /* Init autoscale factors */
742 if (AUTOSCALE_ON(flags) && (group[i] > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
744 for (j = 0; (j < group[i]) && (j < 16); j++) {
745 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
748 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
749 if (strlen(val) > 0) {
750 asfactor[j] = pwr10(strlen(val) - 1);
756 for (j = 0; j < group[i]; j++) {
757 /* Set dp to TRUE (1) if current metric is based on integer values */
758 dp = (g_title[pos + j][0] == '~');
759 snprintf(val, 32, "x%u ", asfactor[j]);
760 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
761 "%s %s(%.*f, %.*f)</text>\n",
762 5 + SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE + j * 15,
763 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
764 asfactor[j] == 1 ? "" : val,
765 !dp * 2, *(spmin + pos + j) * asfactor[j],
766 !dp * 2, *(spmax + pos + j) * asfactor[j]);
769 /* Translate to proper position for current graph within current activity */
770 printf("<g transform=\"translate(%d,%d)\">\n",
771 SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
774 if (g_type == SVG_LINE_GRAPH) {
775 /* For line graphs */
777 /* If all values are zero then set current max value to 1 */
783 /* Max value cannot be too small, else Y graduations will be meaningless */
784 if (lmax < SVG_H_GRIDNR * 0.01) {
785 lmax = SVG_H_GRIDNR * 0.01;
787 ypos = ygrid(lmax, &dp);
790 /* For bar graphs (used for %values) */
791 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
792 dp = 0; /* No decimals */
794 /* Max should be always 100% except for percentage values greater than 100% */
802 yfactor = (double) -SVG_G_YSIZE / lmax;
805 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
806 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
807 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
810 while (ypos * j <= lmax);
814 * Use same rounded value for graduation numbers as for grid lines
815 * to make sure they are properly aligned.
817 sprintf(stmp, "%.2f", ypos * j);
819 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
820 "text-anchor: end\">%.*f.</text>\n",
821 (long) (atof(stmp) * yfactor), dp, ypos * j);
824 while (ypos * j <= lmax);
826 /* Set number of vertical lines to 12 when option "oneday" is used */
827 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
829 k = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
830 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
831 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
833 for (j = 0; (j <= v_gridnr) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
834 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
835 set_record_timestamp_string(flags, &stamp, NULL, cur_time, 32, &rectime);
836 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
837 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
838 k * j, k * j, -SVG_G_YSIZE, xfactor);
840 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
841 * In this case, we should rather display the exact time instead of only the hour.
843 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
844 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
845 "text-anchor: start\">%2dH</text>\n",
846 (long) (k * j * xfactor) - 8, rectime.tm_hour);
849 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
850 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
851 (long) (k * j * xfactor), (long) (k * j * xfactor), cur_time);
855 if (!PRINT_LOCAL_TIME(flags)) {
856 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
857 "text-anchor: end\">UTC</text>\n");
860 /* Draw current graphs set */
861 for (j = 0; j < group[i]; j++) {
862 out_p = *(out + pos + j);
863 if (g_type == SVG_LINE_GRAPH) {
865 printf("<path id=\"g%dp%d\" d=\"%s\" "
866 "style=\"vector-effect: non-scaling-stroke; "
867 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
868 "transform=\"scale(%f,%f)\"/>\n",
869 svg_p->graph_no, pos + j, out_p,
870 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
872 yfactor * asfactor[j]);
874 else if (*out_p) { /* Ignore flat bars */
876 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
877 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
878 printf("%s\n", out_p);
889 (svg_p->graph_no) += views_nr;
893 ***************************************************************************
894 * Display CPU statistics in SVG.
897 * @a Activity structure with statistics.
898 * @curr Index in array for current sample statistics.
899 * @action Action expected from current function.
900 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
901 * flag indicating that a restart record has been previously
902 * found (.@restart), and time used for the X axis origin
904 * @itv Interval of time in jiffies (only with F_MAIN action).
905 * @record_hdr Pointer on record header of current stats sample.
906 ***************************************************************************
908 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
909 unsigned long long g_itv, struct record_header *record_hdr)
911 struct stats_cpu *scc, *scp;
914 char *title[] = {"CPU load"};
915 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
916 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
917 static double *spmin, *spmax;
922 int i, j, k, pos, cpu_offline;
924 if (action & F_BEGIN) {
926 * Allocate arrays that will contain the graphs data
927 * and the min/max values.
929 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
932 if (action & F_MAIN) {
934 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
936 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
937 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
939 /* Should current CPU (including CPU "all") be displayed? */
940 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
947 if (i) { /* Don't test CPU "all" here */
949 * If the CPU is offline then it is omited from /proc/stat:
950 * All the fields couldn't have been read and the sum of them is zero.
951 * (Remember that guest/guest_nice times are already included in
954 if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys +
955 scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal +
956 scc->cpu_hardirq + scc->cpu_softirq) == 0) {
958 * Set current struct fields (which have been set to zero)
959 * to values from previous iteration. Hence their values won't
960 * jump from zero when the CPU comes back online.
969 * Recalculate interval for current proc.
970 * If result is 0 then current CPU is a tickless one.
972 g_itv = get_per_cpu_interval(scc, scp);
976 if (!g_itv) { /* Current CPU is offline or tickless */
978 val = (cpu_offline ? 0.0 /* Offline CPU: %idle = 0% */
979 : 100.0); /* Tickless CPU: %idle = 100% */
981 if (DISPLAY_CPU_DEF(a->opt_flags)) {
984 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
988 /* Check min/max values for %user, etc. */
989 for (k = 0; k < j; k++) {
990 if (0.0 < *(spmin + pos + k)) {
991 *(spmin + pos + k) = 0.0;
993 if (0.0 > *(spmax + pos + k)) {
994 *(spmax + pos + k) = 0.0;
999 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1001 out + pos + j, outsize + pos + j, svg_p->dt,
1002 spmin + pos + j, spmax + pos + j);
1007 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1009 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1010 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv),
1011 out + pos, outsize + pos, svg_p->dt,
1012 spmin + pos, spmax + pos);
1016 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1018 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1020 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1021 scc->cpu_user - scc->cpu_guest, g_itv),
1022 out + pos, outsize + pos, svg_p->dt,
1023 spmin + pos, spmax + pos);
1026 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1028 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1029 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv),
1030 out + pos + 1, outsize + pos + 1, svg_p->dt,
1031 spmin + pos + 1, spmax + pos + 1);
1035 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1037 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1039 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1040 scc->cpu_nice - scc->cpu_guest_nice, g_itv),
1041 out + pos + 1, outsize + pos + 1, svg_p->dt,
1042 spmin + pos + 1, spmax + pos + 1);
1045 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1047 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1049 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1050 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1052 out + pos + 2, outsize + pos + 2, svg_p->dt,
1053 spmin + pos + 2, spmax + pos + 2);
1057 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1058 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv),
1059 out + pos + 2, outsize + pos + 2, svg_p->dt,
1060 spmin + pos + 2, spmax + pos + 2);
1064 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1065 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
1066 out + pos + 3, outsize + pos + 3, svg_p->dt,
1067 spmin + pos + 3, spmax + pos + 3);
1070 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1071 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
1072 out + pos + 4, outsize + pos + 4, svg_p->dt,
1073 spmin + pos + 4, spmax + pos + 4);
1075 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1077 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1078 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv),
1079 out + pos + 5, outsize + pos + 5, svg_p->dt,
1080 spmin + pos + 5, spmax + pos + 5);
1083 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1084 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv),
1085 out + pos + 6, outsize + pos + 6, svg_p->dt,
1086 spmin + pos + 6, spmax + pos + 6);
1089 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1090 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv),
1091 out + pos + 7, outsize + pos + 7, svg_p->dt,
1092 spmin + pos + 7, spmax + pos + 7);
1095 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1096 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, g_itv),
1097 out + pos + 8, outsize + pos + 8, svg_p->dt,
1098 spmin + pos + 8, spmax + pos + 8);
1107 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1109 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1110 ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv)),
1111 out + pos + j, outsize + pos + j, svg_p->dt,
1112 spmin + pos + j, spmax + pos + j);
1116 if (action & F_END) {
1117 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1119 /* Should current CPU (including CPU "all") be displayed? */
1120 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1126 /* This is CPU "all" */
1127 strcpy(item_name, "all");
1130 sprintf(item_name, "%d", i - 1);
1133 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1134 draw_activity_graphs(a->g_nr, SVG_BAR_GRAPH,
1135 title, g_title1, item_name, group1,
1136 spmin + pos, spmax + pos, out + pos, outsize + pos,
1140 draw_activity_graphs(a->g_nr, SVG_BAR_GRAPH,
1141 title, g_title2, item_name, group2,
1142 spmin + pos, spmax + pos, out + pos, outsize + pos,
1147 /* Free remaining structures */
1148 free_graphs(out, outsize, spmin, spmax);
1153 ***************************************************************************
1154 * Display task creation and context switch statistics in SVG.
1157 * @a Activity structure with statistics.
1158 * @curr Index in array for current sample statistics.
1159 * @action Action expected from current function.
1160 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1161 * flag indicating that a restart record has been previously
1162 * found (.@restart) and time used for the X axis origin
1164 * @itv Interval of time in jiffies (only with F_MAIN action).
1165 * @record_hdr Pointer on record header of current stats sample.
1166 ***************************************************************************
1168 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1169 unsigned long long itv, struct record_header *record_hdr)
1172 *spc = (struct stats_pcsw *) a->buf[curr],
1173 *spp = (struct stats_pcsw *) a->buf[!curr];
1174 int group[] = {1, 1};
1175 char *title[] = {"Switching activity", "Task creation"};
1176 char *g_title[] = {"cswch/s",
1178 static double *spmin, *spmax;
1180 static int *outsize;
1182 if (action & F_BEGIN) {
1184 * Allocate arrays that will contain the graphs data
1185 * and the min/max values.
1187 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1190 if (action & F_MAIN) {
1191 /* Check for min/max values */
1192 save_extrema(1, 1, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1196 S_VALUE(spp->context_switch, spc->context_switch, itv),
1197 out, outsize, svg_p->restart);
1199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1200 S_VALUE(spp->processes, spc->processes, itv),
1201 out + 1, outsize + 1, svg_p->restart);
1204 if (action & F_END) {
1205 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1206 spmin, spmax, out, outsize, svg_p, record_hdr);
1208 /* Free remaining structures */
1209 free_graphs(out, outsize, spmin, spmax);
1214 ***************************************************************************
1215 * Display swap statistics in SVG.
1218 * @a Activity structure with statistics.
1219 * @curr Index in array for current sample statistics.
1220 * @action Action expected from current function.
1221 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1222 * flag indicating that a restart record has been previously
1223 * found (.@restart) and time used for the X axis origin
1225 * @itv Interval of time in jiffies (only with F_MAIN action).
1226 * @record_hdr Pointer on record header of current stats sample.
1227 ***************************************************************************
1229 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1230 unsigned long long itv, struct record_header *record_hdr)
1233 *ssc = (struct stats_swap *) a->buf[curr],
1234 *ssp = (struct stats_swap *) a->buf[!curr];
1236 char *title[] = {"Swap activity"};
1237 char *g_title[] = {"pswpin/s", "pswpout/s" };
1238 static double *spmin, *spmax;
1240 static int *outsize;
1242 if (action & F_BEGIN) {
1244 * Allocate arrays that will contain the graphs data
1245 * and the min/max values.
1247 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1250 if (action & F_MAIN) {
1251 /* Check for min/max values */
1252 save_extrema(0, 2, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1255 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1256 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1257 out, outsize, svg_p->restart);
1259 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1260 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1261 out + 1, outsize + 1, svg_p->restart);
1264 if (action & F_END) {
1265 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1266 spmin, spmax, out, outsize, svg_p, record_hdr);
1268 /* Free remaining structures */
1269 free_graphs(out, outsize, spmin, spmax);
1274 ***************************************************************************
1275 * Display paging statistics in SVG.
1278 * @a Activity structure with statistics.
1279 * @curr Index in array for current sample statistics.
1280 * @action Action expected from current function.
1281 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1282 * flag indicating that a restart record has been previously
1283 * found (.@restart) and time used for the X axis origin
1285 * @itv Interval of time in jiffies (only with F_MAIN action).
1286 * @record_hdr Pointer on record header of current stats sample.
1287 ***************************************************************************
1289 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1290 unsigned long long itv, struct record_header *record_hdr)
1293 *spc = (struct stats_paging *) a->buf[curr],
1294 *spp = (struct stats_paging *) a->buf[!curr];
1295 int group[] = {2, 2, 4};
1296 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1297 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1298 "fault/s", "majflt/s",
1299 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1300 static double *spmin, *spmax;
1302 static int *outsize;
1304 if (action & F_BEGIN) {
1306 * Allocate arrays that will contain the graphs data
1307 * and the min/max values.
1309 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1312 if (action & F_MAIN) {
1313 /* Check for min/max values */
1314 save_extrema(0, 8, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1317 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1318 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1319 out, outsize, svg_p->restart);
1321 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1322 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1323 out + 1, outsize + 1, svg_p->restart);
1325 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1326 S_VALUE(spp->pgfault, spc->pgfault, itv),
1327 out + 2, outsize + 2, svg_p->restart);
1329 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1330 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1331 out + 3, outsize + 3, svg_p->restart);
1333 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1334 S_VALUE(spp->pgfree, spc->pgfree, itv),
1335 out + 4, outsize + 4, svg_p->restart);
1337 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1338 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1339 out + 5, outsize + 5, svg_p->restart);
1341 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1342 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1343 out + 6, outsize + 6, svg_p->restart);
1345 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1346 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1347 out + 7, outsize + 7, svg_p->restart);
1350 if (action & F_END) {
1351 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1352 spmin, spmax, out, outsize, svg_p, record_hdr);
1354 /* Free remaining structures */
1355 free_graphs(out, outsize, spmin, spmax);
1360 ***************************************************************************
1361 * Display I/O and transfer rate statistics in SVG.
1364 * @a Activity structure with statistics.
1365 * @curr Index in array for current sample statistics.
1366 * @action Action expected from current function.
1367 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1368 * flag indicating that a restart record has been previously
1369 * found (.@restart) and time used for the X axis origin
1371 * @itv Interval of time in jiffies (only with F_MAIN action).
1372 * @record_hdr Pointer on record header of current stats sample.
1373 ***************************************************************************
1375 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1376 unsigned long long itv, struct record_header *record_hdr)
1379 *sic = (struct stats_io *) a->buf[curr],
1380 *sip = (struct stats_io *) a->buf[!curr];
1381 int group[] = {3, 2};
1382 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1383 char *g_title[] = {"tps", "rtps", "wtps",
1384 "bread/s", "bwrtn/s"};
1385 static double *spmin, *spmax;
1387 static int *outsize;
1389 if (action & F_BEGIN) {
1391 * Allocate arrays that will contain the graphs data
1392 * and the min/max values.
1394 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1397 if (action & F_MAIN) {
1398 /* Check for min/max values */
1399 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1403 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1404 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1405 out, outsize, svg_p->restart);
1407 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1408 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1409 out + 1, outsize + 1, svg_p->restart);
1411 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1412 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1413 out + 2, outsize + 2, svg_p->restart);
1415 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1416 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1417 out + 3, outsize + 3, svg_p->restart);
1419 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1420 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1421 out + 4, outsize + 4, svg_p->restart);
1424 if (action & F_END) {
1425 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1426 spmin, spmax, out, outsize, svg_p, record_hdr);
1428 /* Free remaining structures */
1429 free_graphs(out, outsize, spmin, spmax);
1434 ***************************************************************************
1435 * Display memory statistics in SVG.
1438 * @a Activity structure with statistics.
1439 * @curr Index in array for current sample statistics.
1440 * @action Action expected from current function.
1441 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1442 * flag indicating that a restart record has been previously
1443 * found (.@restart) and time used for the X axis origin
1445 * @itv Interval of time in jiffies (only with F_MAIN action).
1446 * @record_hdr Pointer on record header of current stats sample.
1447 ***************************************************************************
1449 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1450 unsigned long long itv, struct record_header *record_hdr)
1453 *smc = (struct stats_memory *) a->buf[curr];
1454 int group1a[] = {2, 2};
1455 int group1b[] = {1, 1};
1456 int group1c[] = {4, 5};
1457 int group2a[] = {3};
1458 int group2b[] = {1, 1};
1459 char *title1a[] = {"Memory utilization (1)", "Memory utilization (2)"};
1460 char *title1b[] = {"Memory utilization (3)", "Memory utilization (4)"};
1461 char *title1c[] = {"Memory utilization (5)", "Memory utilization (6)"};
1462 char *title2a[] = {"Swap utilization (1)"};
1463 char *title2b[] = {"Swap utilization (2)", "Swap utilization (3)"};
1464 char *g_title1a[] = {"MBmemfree", "MBmemused",
1465 "MBcached", "MBbuffers"};
1466 char *g_title1b[] = {"%memused", "%commit"};
1467 char *g_title1c[] = {"MBcommit", "MBactive", "MBinact", "MBdirty",
1468 "MBanonpg", "MBslab", "MBkstack", "MBpgtbl", "MBvmused"};
1469 char *g_title2a[] = {"MBswpfree", "MBswpused", "MBswpcad"};
1470 char *g_title2b[] = {"%swpused", "%swpcad"};
1471 static double *spmin, *spmax;
1473 static int *outsize;
1477 if (action & F_BEGIN) {
1479 * Allocate arrays that will contain the graphs data
1480 * and the min/max values.
1482 out = allocate_graph_lines(22, &outsize, &spmin, &spmax);
1485 if (action & F_MAIN) {
1486 /* Check for min/max values */
1487 save_extrema(0, 16, 0, (void *) a->buf[curr], NULL,
1489 /* Compute %memused min/max values */
1490 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1491 if (tval > *(spmax + 16)) {
1492 *(spmax + 16) = tval;
1494 if (tval < *(spmin + 16)) {
1495 *(spmin + 16) = tval;
1497 /* Compute %commit min/max values */
1498 tval = (smc->tlmkb + smc->tlskb) ?
1499 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1500 if (tval > *(spmax + 17)) {
1501 *(spmax + 17) = tval;
1503 if (tval < *(spmin + 17)) {
1504 *(spmin + 17) = tval;
1506 /* Compute %swpused min/max values */
1508 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1509 if (tval > *(spmax + 18)) {
1510 *(spmax + 18) = tval;
1512 if (tval < *(spmin + 18)) {
1513 *(spmin + 18) = tval;
1515 /* Compute %swpcad min/max values */
1516 tval = (smc->tlskb - smc->frskb) ?
1517 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1518 if (tval > *(spmax + 19)) {
1519 *(spmax + 19) = tval;
1521 if (tval < *(spmin + 19)) {
1522 *(spmin + 19) = tval;
1524 /* Compute memused min/max values in MB */
1525 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1526 if (tval > *(spmax + 20)) {
1527 *(spmax + 20) = tval;
1529 if (tval < *(spmin + 20)) {
1530 *(spmin + 20) = tval;
1532 /* Compute swpused min/max values in MB */
1533 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1534 if (tval > *(spmax + 21)) {
1535 *(spmax + 21) = tval;
1537 if (tval < *(spmin + 21)) {
1538 *(spmin + 21) = tval;
1542 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1543 ((double) smc->frmkb) / 1024,
1544 out, outsize, svg_p->restart);
1546 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1547 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1548 out + 1, outsize + 1, svg_p->restart);
1550 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1551 ((double) smc->camkb) / 1024,
1552 out + 2, outsize + 2, svg_p->restart);
1554 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1555 ((double) smc->bufkb) / 1024,
1556 out + 3, outsize + 3, svg_p->restart);
1558 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1559 ((double) smc->frskb) / 1024,
1560 out + 4, outsize + 4, svg_p->restart);
1562 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1563 ((double) (smc->tlskb - smc->frskb)) / 1024,
1564 out + 5, outsize + 5, svg_p->restart);
1566 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1567 ((double) smc->caskb) / 1024,
1568 out + 6, outsize + 6, svg_p->restart);
1570 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1571 ((double) smc->comkb) / 1024,
1572 out + 7, outsize + 7, svg_p->restart);
1574 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1575 ((double) smc->activekb) / 1024,
1576 out + 8, outsize + 8, svg_p->restart);
1578 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1579 ((double) smc->inactkb) / 1024,
1580 out + 9, outsize + 9, svg_p->restart);
1582 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1583 ((double) smc->dirtykb) / 1024,
1584 out + 10, outsize + 10, svg_p->restart);
1586 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1587 ((double) smc->anonpgkb) / 1024,
1588 out + 11, outsize + 11, svg_p->restart);
1590 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1591 ((double) smc->slabkb) / 1024,
1592 out + 12, outsize + 12, svg_p->restart);
1594 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1595 ((double) smc->kstackkb) / 1024,
1596 out + 13, outsize + 13, svg_p->restart);
1598 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1599 ((double) smc->pgtblkb) / 1024,
1600 out + 14, outsize + 14, svg_p->restart);
1602 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1603 ((double) smc->vmusedkb) / 1024,
1604 out + 15, outsize + 15, svg_p->restart);
1606 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1609 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1610 out + 16, outsize + 16, svg_p->dt);
1612 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1614 (smc->tlmkb + smc->tlskb) ?
1615 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1616 out + 17, outsize + 17, svg_p->dt);
1618 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1621 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1622 out + 18, outsize + 18, svg_p->dt);
1624 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1626 (smc->tlskb - smc->frskb) ?
1627 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1628 out + 19, outsize + 19, svg_p->dt);
1631 if (action & F_END) {
1633 /* Conversion kB -> MB */
1634 for (i = 0; i < 16; i++) {
1635 *(spmin + i) /= 1024;
1636 *(spmax + i) /= 1024;
1639 if (DISPLAY_MEM_AMT(a->opt_flags)) {
1640 /* frmkb and tlmkb should be together because they will be drawn on the same view */
1641 *(spmax + 3) = *(spmax + 1);
1642 *(spmin + 3) = *(spmin + 1);
1643 /* Move memused min/max values */
1644 *(spmax + 1) = *(spmax + 20);
1645 *(spmin + 1) = *(spmin + 20);
1647 draw_activity_graphs(2, SVG_LINE_GRAPH, title1a, g_title1a, NULL, group1a,
1648 spmin, spmax, out, outsize, svg_p, record_hdr);
1649 draw_activity_graphs(2, SVG_BAR_GRAPH, title1b, g_title1b, NULL, group1b,
1650 spmin + 16, spmax + 16, out + 16, outsize + 16, svg_p, record_hdr);
1651 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 2 : 1,
1652 SVG_LINE_GRAPH, title1c, g_title1c, NULL, group1c,
1653 spmin + 7, spmax + 7, out + 7, outsize + 7, svg_p, record_hdr);
1656 if (DISPLAY_SWAP(a->opt_flags)) {
1657 /* Move swpused min/max values */
1658 *(spmax + 5) = *(spmax + 21);
1659 *(spmin + 5) = *(spmin + 21);
1661 draw_activity_graphs(1, SVG_LINE_GRAPH, title2a, g_title2a, NULL, group2a,
1662 spmin + 4, spmax + 4, out + 4, outsize + 4, svg_p, record_hdr);
1663 draw_activity_graphs(2, SVG_BAR_GRAPH, title2b, g_title2b, NULL, group2b,
1664 spmin + 18, spmax + 18, out + 18, outsize + 18, svg_p, record_hdr);
1667 /* Free remaining structures */
1668 free_graphs(out, outsize, spmin, spmax);
1673 ***************************************************************************
1674 * Display kernel tables statistics in SVG.
1677 * @a Activity structure with statistics.
1678 * @curr Index in array for current sample statistics.
1679 * @action Action expected from current function.
1680 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1681 * flag indicating that a restart record has been previously
1682 * found (.@restart) and time used for the X axis origin
1684 * @itv Interval of time in jiffies (only with F_MAIN action).
1685 * @record_hdr Pointer on record header of current stats sample.
1686 ***************************************************************************
1688 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1689 unsigned long long itv, struct record_header *record_hdr)
1691 struct stats_ktables
1692 *skc = (struct stats_ktables *) a->buf[curr];
1693 int group[] = {3, 1};
1694 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1695 char *g_title[] = {"~file-nr", "~inode-nr", "~dentunusd",
1697 static double *spmin, *spmax;
1699 static int *outsize;
1701 if (action & F_BEGIN) {
1703 * Allocate arrays that will contain the graphs data
1704 * and the min/max values.
1706 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1709 if (action & F_MAIN) {
1710 /* Check for min/max values */
1711 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
1714 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1715 (unsigned long) skc->file_used,
1716 out, outsize, svg_p->restart);
1718 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1719 (unsigned long) skc->inode_used,
1720 out + 1, outsize + 1, svg_p->restart);
1722 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1723 (unsigned long) skc->dentry_stat,
1724 out + 2, outsize + 2, svg_p->restart);
1726 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1727 (unsigned long) skc->pty_nr,
1728 out + 3, outsize + 3, svg_p->restart);
1731 if (action & F_END) {
1732 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1733 spmin, spmax, out, outsize, svg_p, record_hdr);
1735 /* Free remaining structures */
1736 free_graphs(out, outsize, spmin, spmax);
1741 ***************************************************************************
1742 * Display queue and load statistics in SVG.
1745 * @a Activity structure with statistics.
1746 * @curr Index in array for current sample statistics.
1747 * @action Action expected from current function.
1748 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1749 * flag indicating that a restart record has been previously
1750 * found (.@restart) and time used for the X axis origin
1752 * @itv Interval of time in jiffies (only with F_MAIN action).
1753 * @record_hdr Pointer on record header of current stats sample.
1754 ***************************************************************************
1756 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1757 unsigned long long itv, struct record_header *record_hdr)
1760 *sqc = (struct stats_queue *) a->buf[curr];
1761 int group[] = {2, 3, 1};
1762 char *title[] = {"Queue length", "Load average", "Task list"};
1763 char *g_title[] = {"~runq-sz", "~blocked",
1764 "ldavg-1", "ldavg-5", "ldavg-15",
1766 static double *spmin, *spmax;
1768 static int *outsize;
1770 if (action & F_BEGIN) {
1772 * Allocate arrays that will contain the graphs data
1773 * and the min/max values.
1775 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1778 if (action & F_MAIN) {
1779 /* Check for min/max values */
1780 save_extrema(0, 2, 4, (void *) a->buf[curr], NULL,
1783 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1784 (unsigned long) sqc->nr_running,
1785 out, outsize, svg_p->restart);
1787 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1788 (unsigned long) sqc->procs_blocked,
1789 out + 1, outsize + 1, svg_p->restart);
1791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1792 (double) sqc->load_avg_1 / 100,
1793 out + 2, outsize + 2, svg_p->restart);
1795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1796 (double) sqc->load_avg_5 / 100,
1797 out + 3, outsize + 3, svg_p->restart);
1799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1800 (double) sqc->load_avg_15 / 100,
1801 out + 4, outsize + 4, svg_p->restart);
1803 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1804 (unsigned long) sqc->nr_threads,
1805 out + 5, outsize + 5, svg_p->restart);
1808 if (action & F_END) {
1809 /* Fix min/max values for load average */
1810 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
1811 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1812 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1814 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1815 spmin, spmax, out, outsize, svg_p, record_hdr);
1817 /* Free remaining structures */
1818 free_graphs(out, outsize, spmin, spmax);
1823 ***************************************************************************
1824 * Display disk statistics in SVG.
1827 * @a Activity structure with statistics.
1828 * @curr Index in array for current sample statistics.
1829 * @action Action expected from current function.
1830 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1831 * flag indicating that a restart record has been previously
1832 * found (.@restart) and time used for the X axis origin
1834 * @itv Interval of time in jiffies (only with F_MAIN action).
1835 * @record_hdr Pointer on record header of current stats sample.
1836 ***************************************************************************
1838 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1839 unsigned long long itv, struct record_header *record_hdr)
1841 struct stats_disk *sdc, *sdp;
1842 struct ext_disk_stats xds;
1843 int group1[] = {1, 2, 2, 2};
1845 char *title1[] = {"Disk statistics (1)", "Disk statistics (2)",
1846 "Disk statistics (3)", "Disk statistics (4)"};
1847 char *title2[] = {"Disk statistics (5)"};
1848 char *g_title1[] = {"tps",
1849 "rd_sec/s", "wr_sec/s",
1850 "avgrq-sz", "avgqu-sz",
1852 char *g_title2[] = {"%util"};
1853 static double *spmin, *spmax;
1855 static int *outsize;
1856 char *item_name, *persist_dev_name;
1858 int i, j, k, pos, restart, *unregistered;
1860 if (action & F_BEGIN) {
1862 * Allocate arrays (#0..7) that will contain the graphs data
1863 * and the min/max values.
1864 * Also allocate one additional array (#8) for each disk device:
1865 * spmax + 8 will contain the device major number,
1866 * spmin + 8 will contain the device minor number,
1867 * outsize + 8 will contain a positive value (TRUE) if the device
1868 * has either still not been registered, or has been unregistered.
1870 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
1873 if (action & F_MAIN) {
1874 restart = svg_p->restart;
1876 * Mark previously registered devices as now
1877 * possibly unregistered for all graphs.
1879 for (k = 0; k < a->nr; k++) {
1880 unregistered = outsize + k * 9 + 8;
1881 if (*unregistered == FALSE) {
1882 *unregistered = MAYBE;
1886 /* For each device structure */
1887 for (i = 0; i < a->nr; i++) {
1888 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
1889 if (!(sdc->major + sdc->minor))
1890 /* Empty structure: Ignore it */
1893 /* Look for corresponding graph */
1894 for (k = 0; k < a->nr; k++) {
1895 if ((sdc->major == *(spmax + k * 9 + 8)) &&
1896 (sdc->minor == *(spmin + k * 9 + 8)))
1901 /* Graph not found: Look for first free entry */
1902 for (k = 0; k < a->nr; k++) {
1903 if (*(spmax + k * 9 + 8) == -DBL_MAX)
1907 /* No free graph entry: Graph for this item won't be drawn */
1911 unregistered = outsize + pos + 8;
1913 j = check_disk_reg(a, curr, !curr, i);
1914 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
1917 * If current device was marked as previously unregistered,
1918 * then set restart variable to TRUE so that the graph will be
1919 * discontinuous, and mark it as now registered.
1921 if (*unregistered == TRUE) {
1924 *unregistered = FALSE;
1926 if (*(spmax + pos + 8) == -DBL_MAX) {
1927 /* Save device major and minor numbers (if not already done) */
1928 *(spmax + pos + 8) = sdc->major;
1929 *(spmin + pos + 8) = sdc->minor;
1932 /* Check for min/max values */
1933 save_extrema(1, 2, 0, (void *) sdc, (void *) sdp,
1934 itv, spmin + pos, spmax + pos);
1936 compute_ext_disk_stats(sdc, sdp, itv, &xds);
1937 if (xds.arqsz < *(spmin + pos + 3)) {
1938 *(spmin + pos + 3) = xds.arqsz;
1940 if (xds.arqsz > *(spmax + pos + 3)) {
1941 *(spmax + pos + 3) = xds.arqsz;
1943 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
1944 if (aqusz < *(spmin + pos + 4)) {
1945 *(spmin + pos + 4) = aqusz;
1947 if (aqusz > *(spmax + pos + 4)) {
1948 *(spmax + pos + 4) = aqusz;
1950 if (xds.await < *(spmin + pos + 5)) {
1951 *(spmin + pos + 5) = xds.await;
1953 if (xds.await > *(spmax + pos + 5)) {
1954 *(spmax + pos + 5) = xds.await;
1956 if (xds.svctm < *(spmin + pos + 6)) {
1957 *(spmin + pos + 6) = xds.svctm;
1959 if (xds.svctm > *(spmax + pos + 6)) {
1960 *(spmax + pos + 6) = xds.svctm;
1962 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
1963 *(spmin + pos + 7) = xds.util / 10.0;
1965 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
1966 *(spmax + pos + 7) = xds.util / 10.0;
1970 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1971 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
1972 out + pos, outsize + pos, restart);
1975 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1976 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv),
1977 out + pos + 1, outsize + pos + 1, restart);
1980 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1981 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv),
1982 out + pos + 2, outsize + pos + 2, restart);
1985 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1987 out + pos + 3, outsize + pos + 3, restart);
1990 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1992 out + pos + 4, outsize + pos + 4, restart);
1995 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1997 out + pos + 5, outsize + pos + 5, restart);
2000 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2002 out + pos + 6, outsize + pos + 6, restart);
2005 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2006 0.0, xds.util / 10.0,
2007 out + pos + 7, outsize + pos + 7, svg_p->dt);
2010 /* Mark devices not seen here as now unregistered */
2011 for (k = 0; k < a->nr; k++) {
2012 unregistered = outsize + k * 9 + 8;
2013 if (*unregistered != FALSE) {
2014 *unregistered = TRUE;
2019 if (action & F_END) {
2020 for (i = 0; i < a->nr; i++) {
2021 /* Check if there is something to display */
2027 persist_dev_name = NULL;
2029 if (DISPLAY_PERSIST_NAME_S(flags)) {
2030 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2034 if (persist_dev_name) {
2035 item_name = persist_dev_name;
2038 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2039 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2043 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2044 USE_PRETTY_OPTION(flags));
2048 draw_activity_graphs(a->g_nr - 1, SVG_LINE_GRAPH,
2049 title1, g_title1, item_name, group1,
2050 spmin + pos, spmax + pos, out + pos, outsize + pos,
2052 draw_activity_graphs(1, SVG_BAR_GRAPH,
2053 title2, g_title2, item_name, group2,
2054 spmin + pos + 7, spmax + pos + 7, out + pos + 7, outsize + pos + 7,
2058 /* Free remaining structures */
2059 free_graphs(out, outsize, spmin, spmax);
2064 ***************************************************************************
2065 * Display network interfaces statistics in SVG.
2068 * @a Activity structure with statistics.
2069 * @curr Index in array for current sample statistics.
2070 * @action Action expected from current function.
2071 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2072 * flag indicating that a restart record has been previously
2073 * found (.@restart) and time used for the X axis origin
2075 * @itv Interval of time in jiffies (only with F_MAIN action).
2076 * @record_hdr Pointer on record header of current stats sample.
2077 ***************************************************************************
2079 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2080 unsigned long long itv, struct record_header *record_hdr)
2082 struct stats_net_dev *sndc, *sndp;
2083 int group1[] = {2, 2, 3};
2085 char *title1[] = {"Network statistics (1)", "Network statistics (2)",
2086 "Network statistics (3)"};
2087 char *title2[] = {"Network statistics (4)"};
2088 char *g_title1[] = {"rxpck/s", "txpck/s",
2090 "rxcmp/s", "txcmp/s", "rxmcst/s"};
2091 char *g_title2[] = {"%ifutil"};
2092 static double *spmin, *spmax;
2094 static int *outsize;
2096 double rxkb, txkb, ifutil;
2097 int i, j, k, pos, restart, *unregistered;
2099 if (action & F_BEGIN) {
2101 * Allocate arrays (#0..7) that will contain the graphs data
2102 * and the min/max values.
2103 * Also allocate one additional array (#8) for each interface:
2104 * out + 8 will contain the interface name,
2105 * outsize + 8 will contain a positive value (TRUE) if the interface
2106 * has either still not been registered, or has been unregistered.
2108 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2111 if (action & F_MAIN) {
2112 restart = svg_p->restart;
2114 * Mark previously registered interfaces as now
2115 * possibly unregistered for all graphs.
2117 for (k = 0; k < a->nr; k++) {
2118 unregistered = outsize + k * 9 + 8;
2119 if (*unregistered == FALSE) {
2120 *unregistered = MAYBE;
2124 /* For each network interfaces structure */
2125 for (i = 0; i < a->nr; i++) {
2126 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2127 if (!strcmp(sndc->interface, ""))
2128 /* Empty structure: Ignore it */
2131 /* Look for corresponding graph */
2132 for (k = 0; k < a->nr; k++) {
2133 item_name = *(out + k * 9 + 8);
2134 if (!strcmp(sndc->interface, item_name))
2139 /* Graph not found: Look for first free entry */
2140 for (k = 0; k < a->nr; k++) {
2141 item_name = *(out + k * 9 + 8);
2142 if (!strcmp(item_name, ""))
2146 /* No free graph entry: Graph for this item won't be drawn */
2151 unregistered = outsize + pos + 8;
2153 j = check_net_dev_reg(a, curr, !curr, i);
2154 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2157 * If current interface was marked as previously unregistered,
2158 * then set restart variable to TRUE so that the graph will be
2159 * discontinuous, and mark it as now registered.
2161 if (*unregistered == TRUE) {
2164 *unregistered = FALSE;
2166 if (!item_name[0]) {
2167 /* Save network interface name (if not already done) */
2168 strncpy(item_name, sndc->interface, CHUNKSIZE);
2169 item_name[CHUNKSIZE - 1] = '\0';
2172 /* Check for min/max values */
2173 save_extrema(7, 0, 0, (void *) sndc, (void *) sndp,
2174 itv, spmin + pos, spmax + pos);
2176 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2177 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2178 ifutil = compute_ifutil(sndc, rxkb, txkb);
2179 if (ifutil < *(spmin + pos + 7)) {
2180 *(spmin + pos + 7) = ifutil;
2182 if (ifutil > *(spmax + pos + 7)) {
2183 *(spmax + pos + 7) = ifutil;
2187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2188 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2189 out + pos, outsize + pos, restart);
2192 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2193 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2194 out + pos + 1, outsize + pos + 1, restart);
2197 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2199 out + pos + 2, outsize + pos + 2, restart);
2202 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2204 out + pos + 3, outsize + pos + 3, restart);
2207 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2208 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2209 out + pos + 4, outsize + pos + 4, restart);
2212 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2213 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2214 out + pos + 5, outsize + pos + 5, restart);
2217 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2218 S_VALUE(sndp->multicast, sndc->multicast, itv),
2219 out + pos + 6, outsize + pos + 6, restart);
2222 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2224 out + pos + 7, outsize + pos + 7, svg_p->dt);
2227 /* Mark interfaces not seen here as now unregistered */
2228 for (k = 0; k < a->nr; k++) {
2229 unregistered = outsize + k * 9 + 8;
2230 if (*unregistered != FALSE) {
2231 *unregistered = TRUE;
2236 if (action & F_END) {
2237 for (i = 0; i < a->nr; i++) {
2239 * Check if there is something to display.
2240 * Don't test sndc->interface because maybe the network
2241 * interface has been registered later.
2247 /* Recalculate min and max values in kB, not in B */
2248 *(spmin + pos + 2) /= 1024;
2249 *(spmax + pos + 2) /= 1024;
2250 *(spmin + pos + 3) /= 1024;
2251 *(spmax + pos + 3) /= 1024;
2253 item_name = *(out + pos + 8);
2254 draw_activity_graphs(a->g_nr - 1, SVG_LINE_GRAPH,
2255 title1, g_title1, item_name, group1,
2256 spmin + pos, spmax + pos, out + pos, outsize + pos,
2258 draw_activity_graphs(1, SVG_BAR_GRAPH,
2259 title2, g_title2, item_name, group2,
2260 spmin + pos + 7, spmax + pos + 7, out + pos + 7, outsize + pos + 7,
2264 /* Free remaining structures */
2265 free_graphs(out, outsize, spmin, spmax);
2270 ***************************************************************************
2271 * Display network interface errors statistics in SVG.
2274 * @a Activity structure with statistics.
2275 * @curr Index in array for current sample statistics.
2276 * @action Action expected from current function.
2277 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2278 * flag indicating that a restart record has been previously
2279 * found (.@restart) and time used for the X axis origin
2281 * @itv Interval of time in jiffies (only with F_MAIN action).
2282 * @record_hdr Pointer on record header of current stats sample.
2283 ***************************************************************************
2285 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2286 unsigned long long itv, struct record_header *record_hdr)
2288 struct stats_net_edev *snedc, *snedp;
2289 int group[] = {2, 2, 2, 3};
2290 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2291 "Network statistics (3)", "Network statistics (4)"};
2292 char *g_title[] = {"rxerr/s", "txerr/s",
2293 "rxdrop/s", "txdrop/s",
2294 "rxfifo/s", "txfifo/s",
2295 "rxfram/s", "txcarr/s", "coll/s"};
2296 static double *spmin, *spmax;
2298 static int *outsize;
2300 double tmpmin, tmpmax;
2301 int i, j, k, pos, restart, *unregistered;
2303 if (action & F_BEGIN) {
2305 * Allocate arrays (#0..8) that will contain the graphs data
2306 * and the min/max values.
2307 * Also allocate one additional array (#9) for each interface:
2308 * out + 9 will contain the interface name,
2309 * outsize + 9 will contain a positive value (TRUE) if the interface
2310 * has either still not been registered, or has been unregistered.
2312 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
2315 if (action & F_MAIN) {
2316 restart = svg_p->restart;
2318 * Mark previously registered interfaces as now
2319 * possibly unregistered for all graphs.
2321 for (k = 0; k < a->nr; k++) {
2322 unregistered = outsize + k * 10 + 9;
2323 if (*unregistered == FALSE) {
2324 *unregistered = MAYBE;
2328 /* For each network interfaces structure */
2329 for (i = 0; i < a->nr; i++) {
2330 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2331 if (!strcmp(snedc->interface, ""))
2332 /* Empty structure: Ignore it */
2335 /* Look for corresponding graph */
2336 for (k = 0; k < a->nr; k++) {
2337 item_name = *(out + k * 10 + 9);
2338 if (!strcmp(snedc->interface, item_name))
2343 /* Graph not found: Look for first free entry */
2344 for (k = 0; k < a->nr; k++) {
2345 item_name = *(out + k * 10 + 9);
2346 if (!strcmp(item_name, ""))
2350 /* No free graph entry: Graph for this item won't be drawn */
2355 unregistered = outsize + pos + 9;
2357 j = check_net_edev_reg(a, curr, !curr, i);
2358 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2361 * If current interface was marked as previously unregistered,
2362 * then set restart variable to TRUE so that the graph will be
2363 * discontinuous, and mark it as now registered.
2365 if (*unregistered == TRUE) {
2368 *unregistered = FALSE;
2370 if (!item_name[0]) {
2371 /* Save network interface name (if not already done) */
2372 strncpy(item_name, snedc->interface, CHUNKSIZE);
2373 item_name[CHUNKSIZE - 1] = '\0';
2376 /* Check for min/max values */
2377 save_extrema(9, 0, 0, (void *) snedc, (void *) snedp,
2378 itv, spmin + pos, spmax + pos);
2381 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2382 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2383 out + pos, outsize + pos, restart);
2386 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2387 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2388 out + pos + 1, outsize + pos + 1, restart);
2391 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2392 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2393 out + pos + 2, outsize + pos + 2, restart);
2396 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2397 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2398 out + pos + 3, outsize + pos + 3, restart);
2401 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2402 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2403 out + pos + 4, outsize + pos + 4, restart);
2406 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2407 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2408 out + pos + 5, outsize + pos + 5, restart);
2411 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2412 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2413 out + pos + 6, outsize + pos + 6, restart);
2416 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2417 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2418 out + pos + 7, outsize + pos + 7, restart);
2421 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2422 S_VALUE(snedp->collisions, snedc->collisions, itv),
2423 out + pos + 8, outsize + pos + 8, restart);
2426 /* Mark interfaces not seen here as now unregistered */
2427 for (k = 0; k < a->nr; k++) {
2428 unregistered = outsize + k * 10 + 9;
2429 if (*unregistered != FALSE) {
2430 *unregistered = TRUE;
2435 if (action & F_END) {
2436 for (i = 0; i < a->nr; i++) {
2438 * Check if there is something to display.
2439 * Don't test snedc->interface because maybe the network
2440 * interface has been registered later.
2447 * Move coll/s min and max values at the end of the list,
2448 * because coll/s graph will be drawn on the last view.
2450 tmpmin = *(spmin + pos);
2451 tmpmax = *(spmax + pos);
2452 for (k = 1; k < 9; k++) {
2453 *(spmin + pos + k - 1) = *(spmin + pos + k);
2454 *(spmax + pos + k - 1) = *(spmax + pos + k);
2456 *(spmin + pos + 8) = tmpmin;
2457 *(spmax + pos + 8) = tmpmax;
2459 item_name = *(out + pos + 9);
2460 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH,
2461 title, g_title, item_name, group,
2462 spmin + pos, spmax + pos, out + pos, outsize + pos,
2466 /* Free remaining structures */
2467 free_graphs(out, outsize, spmin, spmax);
2472 ***************************************************************************
2473 * Display NFS client statistics in SVG.
2476 * @a Activity structure with statistics.
2477 * @curr Index in array for current sample statistics.
2478 * @action Action expected from current function.
2479 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2480 * flag indicating that a restart record has been previously
2481 * found (.@restart) and time used for the X axis origin
2483 * @itv Interval of time in jiffies (only with F_MAIN action).
2484 * @record_hdr Pointer on record header of current stats sample.
2485 ***************************************************************************
2487 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2488 unsigned long long itv, struct record_header *record_hdr)
2490 struct stats_net_nfs
2491 *snnc = (struct stats_net_nfs *) a->buf[curr],
2492 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2493 int group[] = {2, 2, 2};
2494 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)", "NFS client statistics (3)"};
2495 char *g_title[] = {"call/s", "retrans/s",
2496 "read/s", "write/s",
2497 "access/s", "getatt/s"};
2498 static double *spmin, *spmax;
2500 static int *outsize;
2502 if (action & F_BEGIN) {
2504 * Allocate arrays that will contain the graphs data
2505 * and the min/max values.
2507 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2510 if (action & F_MAIN) {
2511 /* Check for min/max values */
2512 save_extrema(0, 0, 6, (void *) a->buf[curr], (void *) a->buf[!curr],
2516 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2517 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2518 out, outsize, svg_p->restart);
2520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2521 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2522 out + 1, outsize + 1, svg_p->restart);
2524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2525 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2526 out + 2, outsize + 2, svg_p->restart);
2528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2529 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2530 out + 3, outsize + 3, svg_p->restart);
2532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2533 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2534 out + 4, outsize + 4, svg_p->restart);
2536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2537 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2538 out + 5, outsize + 5, svg_p->restart);
2541 if (action & F_END) {
2542 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2543 spmin, spmax, out, outsize, svg_p, record_hdr);
2545 /* Free remaining structures */
2546 free_graphs(out, outsize, spmin, spmax);
2551 ***************************************************************************
2552 * Display NFS server statistics in SVG.
2555 * @a Activity structure with statistics.
2556 * @curr Index in array for current sample statistics.
2557 * @action Action expected from current function.
2558 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2559 * flag indicating that a restart record has been previously
2560 * found (.@restart) and time used for the X axis origin
2562 * @itv Interval of time in jiffies (only with F_MAIN action).
2563 * @record_hdr Pointer on record header of current stats sample.
2564 ***************************************************************************
2566 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2567 unsigned long long itv, struct record_header *record_hdr)
2569 struct stats_net_nfsd
2570 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2571 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2572 int group[] = {2, 3, 2, 2, 2};
2573 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)", "NFS server statistics (3)",
2574 "NFS server statistics (4)", "NFS server statistics (5)"};
2575 char *g_title[] = {"scall/s", "badcall/s",
2576 "packet/s", "udp/s", "tcp/s",
2578 "sread/s", "swrite/s",
2579 "saccess/s", "sgetatt/s"};
2580 static double *spmin, *spmax;
2582 static int *outsize;
2584 if (action & F_BEGIN) {
2586 * Allocate arrays that will contain the graphs data
2587 * and the min/max values.
2589 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2592 if (action & F_MAIN) {
2593 /* Check for min/max values */
2594 save_extrema(0, 0, 11, (void *) a->buf[curr], (void *) a->buf[!curr],
2598 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2599 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2600 out, outsize, svg_p->restart);
2602 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2603 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2604 out + 1, outsize + 1, svg_p->restart);
2606 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2607 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2608 out + 2, outsize + 2, svg_p->restart);
2610 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2611 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2612 out + 3, outsize + 3, svg_p->restart);
2614 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2615 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2616 out + 4, outsize + 4, svg_p->restart);
2618 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2619 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2620 out + 5, outsize + 5, svg_p->restart);
2622 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2623 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2624 out + 6, outsize + 6, svg_p->restart);
2626 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2627 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2628 out + 7, outsize + 7, svg_p->restart);
2630 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2631 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2632 out + 8, outsize + 8, svg_p->restart);
2634 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2635 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2636 out + 9, outsize + 9, svg_p->restart);
2638 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2639 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2640 out + 10, outsize + 10, svg_p->restart);
2643 if (action & F_END) {
2644 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2645 spmin, spmax, out, outsize, svg_p, record_hdr);
2647 /* Free remaining structures */
2648 free_graphs(out, outsize, spmin, spmax);
2653 ***************************************************************************
2654 * Display network socket statistics in SVG.
2657 * @a Activity structure with statistics.
2658 * @curr Index in array for current sample statistics.
2659 * @action Action expected from current function.
2660 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2661 * flag indicating that a restart record has been previously
2662 * found (.@restart) and time used for the X axis origin
2664 * @itv Interval of time in jiffies (only with F_MAIN action).
2665 * @record_hdr Pointer on record header of current stats sample.
2666 ***************************************************************************
2668 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2669 unsigned long long itv, struct record_header *record_hdr)
2671 struct stats_net_sock
2672 *snsc = (struct stats_net_sock *) a->buf[curr];
2673 int group[] = {1, 5};
2674 char *title[] = {"Network sockets (1)", "Network sockets (2)"};
2675 char *g_title[] = {"~totsck",
2676 "~tcpsck", "~tcp-tw", "~udpsck", "~rawsck", "~ip-frag"};
2677 static double *spmin, *spmax;
2679 static int *outsize;
2681 if (action & F_BEGIN) {
2683 * Allocate arrays that will contain the graphs data
2684 * and the min/max values.
2686 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2689 if (action & F_MAIN) {
2690 /* Check for min/max values */
2691 save_extrema(0, 0, 6, (void *) a->buf[curr], NULL,
2694 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2695 (unsigned long) snsc->sock_inuse,
2696 out, outsize, svg_p->restart);
2698 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2699 (unsigned long) snsc->tcp_inuse,
2700 out + 1, outsize + 1, svg_p->restart);
2702 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2703 (unsigned long) snsc->tcp_tw,
2704 out + 2, outsize + 2, svg_p->restart);
2706 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2707 (unsigned long) snsc->udp_inuse,
2708 out + 3, outsize + 3, svg_p->restart);
2710 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2711 (unsigned long) snsc->raw_inuse,
2712 out + 4, outsize + 4, svg_p->restart);
2714 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2715 (unsigned long) snsc->frag_inuse,
2716 out + 5, outsize + 5, svg_p->restart);
2719 if (action & F_END) {
2720 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2721 spmin, spmax, out, outsize, svg_p, record_hdr);
2723 /* Free remaining structures */
2724 free_graphs(out, outsize, spmin, spmax);
2729 ***************************************************************************
2730 * Display IPv4 network statistics in SVG.
2733 * @a Activity structure with statistics.
2734 * @curr Index in array for current sample statistics.
2735 * @action Action expected from current function.
2736 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2737 * flag indicating that a restart record has been previously
2738 * found (.@restart) and time used for the X axis origin
2740 * @itv Interval of time in jiffies (only with F_MAIN action).
2741 * @record_hdr Pointer on record header of current stats sample.
2742 ***************************************************************************
2744 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2745 unsigned long long itv, struct record_header *record_hdr)
2748 *snic = (struct stats_net_ip *) a->buf[curr],
2749 *snip = (struct stats_net_ip *) a->buf[!curr];
2750 int group[] = {4, 2, 2};
2751 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2752 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2753 "asmrq/s", "asmok/s",
2754 "fragok/s", "fragcrt/s"};
2755 static double *spmin, *spmax;
2757 static int *outsize;
2759 if (action & F_BEGIN) {
2761 * Allocate arrays that will contain the graphs data
2762 * and the min/max values.
2764 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2767 if (action & F_MAIN) {
2768 /* Check for min/max values */
2769 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2773 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2774 S_VALUE(snip->InReceives, snic->InReceives, itv),
2775 out, outsize, svg_p->restart);
2777 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2778 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2779 out + 1, outsize + 1, svg_p->restart);
2781 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2782 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2783 out + 2, outsize + 2, svg_p->restart);
2785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2786 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2787 out + 3, outsize + 3, svg_p->restart);
2789 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2790 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2791 out + 4, outsize + 4, svg_p->restart);
2793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2794 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2795 out + 5, outsize + 5, svg_p->restart);
2797 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2798 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2799 out + 6, outsize + 6, svg_p->restart);
2801 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2802 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2803 out + 7, outsize + 7, svg_p->restart);
2806 if (action & F_END) {
2807 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2808 spmin, spmax, out, outsize, svg_p, record_hdr);
2810 /* Free remaining structures */
2811 free_graphs(out, outsize, spmin, spmax);
2816 ***************************************************************************
2817 * Display IPv4 network errors statistics in SVG.
2820 * @a Activity structure with statistics.
2821 * @curr Index in array for current sample statistics.
2822 * @action Action expected from current function.
2823 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2824 * flag indicating that a restart record has been previously
2825 * found (.@restart) and time used for the X axis origin
2827 * @itv Interval of time in jiffies (only with F_MAIN action).
2828 * @record_hdr Pointer on record header of current stats sample.
2829 ***************************************************************************
2831 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2832 unsigned long long itv, struct record_header *record_hdr)
2834 struct stats_net_eip
2835 *sneic = (struct stats_net_eip *) a->buf[curr],
2836 *sneip = (struct stats_net_eip *) a->buf[!curr];
2837 int group[] = {3, 2, 3};
2838 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
2839 "IPv4 network errors statistics (3)"};
2840 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
2841 "idisc/s", "odisc/s",
2842 "onort/s", "asmf/s", "fragf/s"};
2843 static double *spmin, *spmax;
2845 static int *outsize;
2847 if (action & F_BEGIN) {
2849 * Allocate arrays that will contain the graphs data
2850 * and the min/max values.
2852 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2855 if (action & F_MAIN) {
2856 /* Check for min/max values */
2857 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2861 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2862 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
2863 out, outsize, svg_p->restart);
2865 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2866 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
2867 out + 1, outsize + 1, svg_p->restart);
2869 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2870 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
2871 out + 2, outsize + 2, svg_p->restart);
2873 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2874 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
2875 out + 3, outsize + 3, svg_p->restart);
2877 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2878 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
2879 out + 4, outsize + 4, svg_p->restart);
2881 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2882 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
2883 out + 5, outsize + 5, svg_p->restart);
2885 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2886 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
2887 out + 6, outsize + 6, svg_p->restart);
2889 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2890 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
2891 out + 7, outsize + 7, svg_p->restart);
2894 if (action & F_END) {
2895 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2896 spmin, spmax, out, outsize, svg_p, record_hdr);
2898 /* Free remaining structures */
2899 free_graphs(out, outsize, spmin, spmax);
2904 ***************************************************************************
2905 * Display ICMPv4 network statistics in SVG.
2908 * @a Activity structure with statistics.
2909 * @curr Index in array for current sample statistics.
2910 * @action Action expected from current function.
2911 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2912 * flag indicating that a restart record has been previously
2913 * found (.@restart) and time used for the X axis origin
2915 * @itv Interval of time in jiffies (only with F_MAIN action).
2916 * @record_hdr Pointer on record header of current stats sample.
2917 ***************************************************************************
2919 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2920 unsigned long long itv, struct record_header *record_hdr)
2922 struct stats_net_icmp
2923 *snic = (struct stats_net_icmp *) a->buf[curr],
2924 *snip = (struct stats_net_icmp *) a->buf[!curr];
2925 int group[] = {2, 4, 4, 4};
2926 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
2927 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
2928 char *g_title[] = {"imsg/s", "omsg/s",
2929 "iech/s", "iechr/s", "oech/s", "oechr/s",
2930 "itm/s", "itmr/s", "otm/s", "otmr/s",
2931 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
2932 static double *spmin, *spmax;
2934 static int *outsize;
2936 if (action & F_BEGIN) {
2938 * Allocate arrays that will contain the graphs data
2939 * and the min/max values.
2941 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
2944 if (action & F_MAIN) {
2945 /* Check for min/max values */
2946 save_extrema(0, 14, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2950 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2951 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
2952 out, outsize, svg_p->restart);
2954 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2955 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
2956 out + 1, outsize + 1, svg_p->restart);
2958 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2959 S_VALUE(snip->InEchos, snic->InEchos, itv),
2960 out + 2, outsize + 2, svg_p->restart);
2962 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2963 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
2964 out + 3, outsize + 3, svg_p->restart);
2966 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2967 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
2968 out + 4, outsize + 4, svg_p->restart);
2970 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2971 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
2972 out + 5, outsize + 5, svg_p->restart);
2974 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2975 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
2976 out + 6, outsize + 6, svg_p->restart);
2978 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2979 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
2980 out + 7, outsize + 7, svg_p->restart);
2982 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2983 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
2984 out + 8, outsize + 8, svg_p->restart);
2986 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2987 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
2988 out + 9, outsize + 9, svg_p->restart);
2990 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2991 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
2992 out + 10, outsize + 10, svg_p->restart);
2994 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2995 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
2996 out + 11, outsize + 11, svg_p->restart);
2998 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2999 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3000 out + 12, outsize + 12, svg_p->restart);
3002 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3003 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3004 out + 13, outsize + 13, svg_p->restart);
3007 if (action & F_END) {
3008 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3009 spmin, spmax, out, outsize, svg_p, record_hdr);
3011 /* Free remaining structures */
3012 free_graphs(out, outsize, spmin, spmax);
3017 ***************************************************************************
3018 * Display ICMPv4 network errors statistics in SVG.
3021 * @a Activity structure with statistics.
3022 * @curr Index in array for current sample statistics.
3023 * @action Action expected from current function.
3024 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3025 * flag indicating that a restart record has been previously
3026 * found (.@restart) and time used for the X axis origin
3028 * @itv Interval of time in jiffies (only with F_MAIN action).
3029 * @record_hdr Pointer on record header of current stats sample.
3030 ***************************************************************************
3032 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3033 unsigned long long itv, struct record_header *record_hdr)
3035 struct stats_net_eicmp
3036 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3037 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3038 int group[] = {2, 2, 2, 2, 2, 2};
3039 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3040 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3041 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3042 char *g_title[] = {"ierr/s", "oerr/s",
3043 "idstunr/s", "odstunr/s",
3044 "itmex/s", "otmex/s",
3045 "iparmpb/s", "oparmpb/s",
3046 "isrcq/s", "osrcq/s",
3047 "iredir/s", "oredir/s"};
3048 static double *spmin, *spmax;
3050 static int *outsize;
3052 if (action & F_BEGIN) {
3054 * Allocate arrays that will contain the graphs data
3055 * and the min/max values.
3057 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3060 if (action & F_MAIN) {
3061 /* Check for min/max values */
3062 save_extrema(0, 12, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3066 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3067 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3068 out, outsize, svg_p->restart);
3070 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3071 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3072 out + 1, outsize + 1, svg_p->restart);
3074 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3075 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3076 out + 2, outsize + 2, svg_p->restart);
3078 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3079 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3080 out + 3, outsize + 3, svg_p->restart);
3082 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3083 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3084 out + 4, outsize + 4, svg_p->restart);
3086 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3087 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3088 out + 5, outsize + 5, svg_p->restart);
3090 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3091 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3092 out + 6, outsize + 6, svg_p->restart);
3094 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3095 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3096 out + 7, outsize + 7, svg_p->restart);
3098 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3099 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3100 out + 8, outsize + 8, svg_p->restart);
3102 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3103 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3104 out + 9, outsize + 9, svg_p->restart);
3106 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3107 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3108 out + 10, outsize + 10, svg_p->restart);
3110 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3111 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3112 out + 11, outsize + 11, svg_p->restart);
3115 if (action & F_END) {
3116 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3117 spmin, spmax, out, outsize, svg_p, record_hdr);
3119 /* Free remaining structures */
3120 free_graphs(out, outsize, spmin, spmax);
3125 ***************************************************************************
3126 * Display TCPv4 network statistics in SVG.
3129 * @a Activity structure with statistics.
3130 * @curr Index in array for current sample statistics.
3131 * @action Action expected from current function.
3132 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3133 * flag indicating that a restart record has been previously
3134 * found (.@restart) and time used for the X axis origin
3136 * @itv Interval of time in jiffies (only with F_MAIN action).
3137 * @record_hdr Pointer on record header of current stats sample.
3138 ***************************************************************************
3140 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3141 unsigned long long itv, struct record_header *record_hdr)
3143 struct stats_net_tcp
3144 *sntc = (struct stats_net_tcp *) a->buf[curr],
3145 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3146 int group[] = {2, 2};
3147 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3148 char *g_title[] = {"active/s", "passive/s",
3149 "iseg/s", "oseg/s"};
3150 static double *spmin, *spmax;
3152 static int *outsize;
3154 if (action & F_BEGIN) {
3156 * Allocate arrays that will contain the graphs data
3157 * and the min/max values.
3159 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3162 if (action & F_MAIN) {
3163 /* Check for min/max values */
3164 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3168 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3169 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3170 out, outsize, svg_p->restart);
3172 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3173 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3174 out + 1, outsize + 1, svg_p->restart);
3176 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3177 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3178 out + 2, outsize + 2, svg_p->restart);
3180 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3181 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3182 out + 3, outsize + 3, svg_p->restart);
3185 if (action & F_END) {
3186 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3187 spmin, spmax, out, outsize, svg_p, record_hdr);
3189 /* Free remaining structures */
3190 free_graphs(out, outsize, spmin, spmax);
3195 ***************************************************************************
3196 * Display TCPv4 network errors statistics in SVG.
3199 * @a Activity structure with statistics.
3200 * @curr Index in array for current sample statistics.
3201 * @action Action expected from current function.
3202 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3203 * flag indicating that a restart record has been previously
3204 * found (.@restart) and time used for the X axis origin
3206 * @itv Interval of time in jiffies (only with F_MAIN action).
3207 * @record_hdr Pointer on record header of current stats sample.
3208 ***************************************************************************
3210 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3211 unsigned long long itv, struct record_header *record_hdr)
3213 struct stats_net_etcp
3214 *snetc = (struct stats_net_etcp *) a->buf[curr],
3215 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3216 int group[] = {2, 3};
3217 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3218 char *g_title[] = {"atmptf/s", "estres/s",
3219 "retrans/s", "isegerr/s", "orsts/s"};
3220 static double *spmin, *spmax;
3222 static int *outsize;
3224 if (action & F_BEGIN) {
3226 * Allocate arrays that will contain the graphs data
3227 * and the min/max values.
3229 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3232 if (action & F_MAIN) {
3233 /* Check for min/max values */
3234 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3238 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3239 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3240 out, outsize, svg_p->restart);
3242 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3243 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3244 out + 1, outsize + 1, svg_p->restart);
3246 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3247 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3248 out + 2, outsize + 2, svg_p->restart);
3250 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3251 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3252 out + 3, outsize + 3, svg_p->restart);
3254 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3255 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3256 out + 4, outsize + 4, svg_p->restart);
3259 if (action & F_END) {
3260 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3261 spmin, spmax, out, outsize, svg_p, record_hdr);
3263 /* Free remaining structures */
3264 free_graphs(out, outsize, spmin, spmax);
3269 ***************************************************************************
3270 * Display UDPv4 network statistics in SVG.
3273 * @a Activity structure with statistics.
3274 * @curr Index in array for current sample statistics.
3275 * @action Action expected from current function.
3276 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3277 * flag indicating that a restart record has been previously
3278 * found (.@restart) and time used for the X axis origin
3280 * @itv Interval of time in jiffies (only with F_MAIN action).
3281 * @record_hdr Pointer on record header of current stats sample.
3282 ***************************************************************************
3284 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3285 unsigned long long itv, struct record_header *record_hdr)
3287 struct stats_net_udp
3288 *snuc = (struct stats_net_udp *) a->buf[curr],
3289 *snup = (struct stats_net_udp *) a->buf[!curr];
3290 int group[] = {2, 2};
3291 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3292 char *g_title[] = {"idgm/s", "odgm/s",
3293 "noport/s", "idgmerr/s"};
3294 static double *spmin, *spmax;
3296 static int *outsize;
3298 if (action & F_BEGIN) {
3300 * Allocate arrays that will contain the graphs data
3301 * and the min/max values.
3303 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3306 if (action & F_MAIN) {
3307 /* Check for min/max values */
3308 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3312 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3313 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3314 out, outsize, svg_p->restart);
3316 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3317 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3318 out + 1, outsize + 1, svg_p->restart);
3320 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3321 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3322 out + 2, outsize + 2, svg_p->restart);
3324 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3325 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3326 out + 3, outsize + 3, svg_p->restart);
3329 if (action & F_END) {
3330 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3331 spmin, spmax, out, outsize, svg_p, record_hdr);
3333 /* Free remaining structures */
3334 free_graphs(out, outsize, spmin, spmax);
3339 ***************************************************************************
3340 * Display IPV6 network socket statistics in SVG.
3343 * @a Activity structure with statistics.
3344 * @curr Index in array for current sample statistics.
3345 * @action Action expected from current function.
3346 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3347 * flag indicating that a restart record has been previously
3348 * found (.@restart) and time used for the X axis origin
3350 * @itv Interval of time in jiffies (only with F_MAIN action).
3351 * @record_hdr Pointer on record header of current stats sample.
3352 ***************************************************************************
3354 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3355 unsigned long long itv, struct record_header *record_hdr)
3357 struct stats_net_sock6
3358 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3360 char *title[] = {"IPv6 network sockets"};
3361 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3362 static double *spmin, *spmax;
3364 static int *outsize;
3366 if (action & F_BEGIN) {
3368 * Allocate arrays that will contain the graphs data
3369 * and the min/max values.
3371 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3374 if (action & F_MAIN) {
3375 /* Check for min/max values */
3376 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
3379 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3380 (unsigned long) snsc->tcp6_inuse,
3381 out, outsize, svg_p->restart);
3383 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3384 (unsigned long) snsc->udp6_inuse,
3385 out + 1, outsize + 1, svg_p->restart);
3387 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3388 (unsigned long) snsc->raw6_inuse,
3389 out + 2, outsize + 2, svg_p->restart);
3391 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3392 (unsigned long) snsc->frag6_inuse,
3393 out + 3, outsize + 3, svg_p->restart);
3396 if (action & F_END) {
3397 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3398 spmin, spmax, out, outsize, svg_p, record_hdr);
3400 /* Free remaining structures */
3401 free_graphs(out, outsize, spmin, spmax);
3406 ***************************************************************************
3407 * Display IPv6 network statistics in SVG.
3410 * @a Activity structure with statistics.
3411 * @curr Index in array for current sample statistics.
3412 * @action Action expected from current function.
3413 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3414 * flag indicating that a restart record has been previously
3415 * found (.@restart) and time used for the X axis origin
3417 * @itv Interval of time in jiffies (only with F_MAIN action).
3418 * @record_hdr Pointer on record header of current stats sample.
3419 ***************************************************************************
3421 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3422 unsigned long long itv, struct record_header *record_hdr)
3424 struct stats_net_ip6
3425 *snic = (struct stats_net_ip6 *) a->buf[curr],
3426 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3427 int group[] = {4, 2, 2, 2};
3428 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3429 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3430 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3431 "asmrq6/s", "asmok6/s",
3432 "imcpck6/s", "omcpck6/s",
3433 "fragok6/s", "fragcr6/s"};
3434 static double *spmin, *spmax;
3436 static int *outsize;
3438 if (action & F_BEGIN) {
3440 * Allocate arrays that will contain the graphs data
3441 * and the min/max values.
3443 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3446 if (action & F_MAIN) {
3447 /* Check for min/max values */
3448 save_extrema(10, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3453 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3454 out, outsize, svg_p->restart);
3456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3457 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3458 out + 1, outsize + 1, svg_p->restart);
3460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3461 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3462 out + 2, outsize + 2, svg_p->restart);
3464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3465 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3466 out + 3, outsize + 3, svg_p->restart);
3468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3469 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3470 out + 4, outsize + 4, svg_p->restart);
3472 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3473 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3474 out + 5, outsize + 5, svg_p->restart);
3476 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3477 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3478 out + 6, outsize + 6, svg_p->restart);
3480 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3481 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3482 out + 7, outsize + 7, svg_p->restart);
3484 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3485 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3486 out + 8, outsize + 8, svg_p->restart);
3488 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3489 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3490 out + 9, outsize + 9, svg_p->restart);
3493 if (action & F_END) {
3494 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3495 spmin, spmax, out, outsize, svg_p, record_hdr);
3497 /* Free remaining structures */
3498 free_graphs(out, outsize, spmin, spmax);
3503 ***************************************************************************
3504 * Display IPv6 network errors statistics in SVG.
3507 * @a Activity structure with statistics.
3508 * @curr Index in array for current sample statistics.
3509 * @action Action expected from current function.
3510 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3511 * flag indicating that a restart record has been previously
3512 * found (.@restart) and time used for the X axis origin
3514 * @itv Interval of time in jiffies (only with F_MAIN action).
3515 * @record_hdr Pointer on record header of current stats sample.
3516 ***************************************************************************
3518 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3519 unsigned long long itv, struct record_header *record_hdr)
3521 struct stats_net_eip6
3522 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3523 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3524 int group[] = {4, 2, 2, 3};
3525 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3526 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3527 "IPv6 network errors statistics (5)"};
3528 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3529 "idisc6/s", "odisc6/s",
3530 "inort6/s", "onort6/s",
3531 "asmf6/s", "fragf6/s", "itrpck6/s"};
3532 static double *spmin, *spmax;
3534 static int *outsize;
3536 if (action & F_BEGIN) {
3538 * Allocate arrays that will contain the graphs data
3539 * and the min/max values.
3541 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3544 if (action & F_MAIN) {
3545 /* Check for min/max values */
3546 save_extrema(11, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3550 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3551 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3552 out, outsize, svg_p->restart);
3554 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3555 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3556 out + 1, outsize + 1, svg_p->restart);
3558 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3559 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3560 out + 2, outsize + 2, svg_p->restart);
3562 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3563 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3564 out + 3, outsize + 3, svg_p->restart);
3566 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3567 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3568 out + 4, outsize + 4, svg_p->restart);
3570 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3571 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3572 out + 5, outsize + 5, svg_p->restart);
3574 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3575 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3576 out + 6, outsize + 6, svg_p->restart);
3578 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3579 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3580 out + 7, outsize + 7, svg_p->restart);
3582 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3583 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3584 out + 8, outsize + 8, svg_p->restart);
3586 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3587 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3588 out + 9, outsize + 9, svg_p->restart);
3590 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3591 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3592 out + 10, outsize + 10, svg_p->restart);
3595 if (action & F_END) {
3596 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3597 spmin, spmax, out, outsize, svg_p, record_hdr);
3599 /* Free remaining structures */
3600 free_graphs(out, outsize, spmin, spmax);
3605 ***************************************************************************
3606 * Display ICMPv6 network statistics in SVG.
3609 * @a Activity structure with statistics.
3610 * @curr Index in array for current sample statistics.
3611 * @action Action expected from current function.
3612 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3613 * flag indicating that a restart record has been previously
3614 * found (.@restart) and time used for the X axis origin
3616 * @itv Interval of time in jiffies (only with F_MAIN action).
3617 * @record_hdr Pointer on record header of current stats sample.
3618 ***************************************************************************
3620 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3621 unsigned long long itv, struct record_header *record_hdr)
3623 struct stats_net_icmp6
3624 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3625 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3626 int group[] = {2, 3, 5, 3, 4};
3627 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3628 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3629 "ICMPv6 network statistics (5)"};
3630 char *g_title[] = {"imsg6/s", "omsg6/s",
3631 "iech6/s", "iechr6/s", "oechr6/s",
3632 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3633 "irtsol6/s", "ortsol6/s", "irtad6/s",
3634 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3635 static double *spmin, *spmax;
3637 static int *outsize;
3639 if (action & F_BEGIN) {
3641 * Allocate arrays that will contain the graphs data
3642 * and the min/max values.
3644 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3647 if (action & F_MAIN) {
3648 /* Check for min/max values */
3649 save_extrema(0, 17, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3653 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3654 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3655 out, outsize, svg_p->restart);
3657 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3658 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3659 out + 1, outsize + 1, svg_p->restart);
3661 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3662 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3663 out + 2, outsize + 2, svg_p->restart);
3665 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3666 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3667 out + 3, outsize + 3, svg_p->restart);
3669 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3670 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3671 out + 4, outsize + 4, svg_p->restart);
3673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3674 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3675 out + 5, outsize + 5, svg_p->restart);
3677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3678 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3679 out + 6, outsize + 6, svg_p->restart);
3681 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3682 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3683 out + 7, outsize + 7, svg_p->restart);
3685 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3686 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3687 out + 8, outsize + 8, svg_p->restart);
3689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3690 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3691 out + 9, outsize + 9, svg_p->restart);
3693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3694 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3695 out + 10, outsize + 10, svg_p->restart);
3697 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3698 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3699 out + 11, outsize + 11, svg_p->restart);
3701 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3702 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3703 out + 12, outsize + 12, svg_p->restart);
3705 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3706 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3707 out + 13, outsize + 13, svg_p->restart);
3709 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3710 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3711 out + 14, outsize + 14, svg_p->restart);
3713 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3714 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3715 out + 15, outsize + 15, svg_p->restart);
3717 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3718 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3719 out + 16, outsize + 16, svg_p->restart);
3722 if (action & F_END) {
3723 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3724 spmin, spmax, out, outsize, svg_p, record_hdr);
3726 /* Free remaining structures */
3727 free_graphs(out, outsize, spmin, spmax);
3732 ***************************************************************************
3733 * Display ICMPv6 network errors statistics in SVG.
3736 * @a Activity structure with statistics.
3737 * @curr Index in array for current sample statistics.
3738 * @action Action expected from current function.
3739 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3740 * flag indicating that a restart record has been previously
3741 * found (.@restart) and time used for the X axis origin
3743 * @itv Interval of time in jiffies (only with F_MAIN action).
3744 * @record_hdr Pointer on record header of current stats sample.
3745 ***************************************************************************
3747 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3748 unsigned long long itv, struct record_header *record_hdr)
3750 struct stats_net_eicmp6
3751 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3752 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3753 int group[] = {1, 2, 2, 2, 2, 2};
3754 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3755 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3756 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3757 char *g_title[] = {"ierr6/s",
3758 "idtunr6/s", "odtunr6/s",
3759 "itmex6/s", "otmex6/s",
3760 "iprmpb6/s", "oprmpb6/s",
3761 "iredir6/s", "oredir6/s",
3762 "ipck2b6/s", "opck2b6/s"};
3763 static double *spmin, *spmax;
3765 static int *outsize;
3767 if (action & F_BEGIN) {
3769 * Allocate arrays that will contain the graphs data
3770 * and the min/max values.
3772 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3775 if (action & F_MAIN) {
3776 /* Check for min/max values */
3777 save_extrema(0, 11, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3781 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3782 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
3783 out, outsize, svg_p->restart);
3785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3786 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
3787 out + 1, outsize + 1, svg_p->restart);
3789 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3790 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
3791 out + 2, outsize + 2, svg_p->restart);
3793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3794 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
3795 out + 3, outsize + 3, svg_p->restart);
3797 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3798 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
3799 out + 4, outsize + 4, svg_p->restart);
3801 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3802 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
3803 out + 5, outsize + 5, svg_p->restart);
3805 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3806 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
3807 out + 6, outsize + 6, svg_p->restart);
3809 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3810 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
3811 out + 7, outsize + 7, svg_p->restart);
3813 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3814 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
3815 out + 8, outsize + 8, svg_p->restart);
3817 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3818 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
3819 out + 9, outsize + 9, svg_p->restart);
3821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3822 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
3823 out + 10, outsize + 10, svg_p->restart);
3826 if (action & F_END) {
3827 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3828 spmin, spmax, out, outsize, svg_p, record_hdr);
3830 /* Free remaining structures */
3831 free_graphs(out, outsize, spmin, spmax);
3836 ***************************************************************************
3837 * Display UDPv6 network statistics in SVG.
3840 * @a Activity structure with statistics.
3841 * @curr Index in array for current sample statistics.
3842 * @action Action expected from current function.
3843 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3844 * flag indicating that a restart record has been previously
3845 * found (.@restart) and time used for the X axis origin
3847 * @itv Interval of time in jiffies (only with F_MAIN action).
3848 * @record_hdr Pointer on record header of current stats sample.
3849 ***************************************************************************
3851 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3852 unsigned long long itv, struct record_header *record_hdr)
3854 struct stats_net_udp6
3855 *snuc = (struct stats_net_udp6 *) a->buf[curr],
3856 *snup = (struct stats_net_udp6 *) a->buf[!curr];
3857 int group[] = {2, 2};
3858 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
3859 char *g_title[] = {"idgm6/s", "odgm6/s",
3860 "noport6/s", "idgmer6/s"};
3861 static double *spmin, *spmax;
3863 static int *outsize;
3865 if (action & F_BEGIN) {
3867 * Allocate arrays that will contain the graphs data
3868 * and the min/max values.
3870 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3873 if (action & F_MAIN) {
3874 /* Check for min/max values */
3875 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3880 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
3881 out, outsize, svg_p->restart);
3883 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3884 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
3885 out + 1, outsize + 1, svg_p->restart);
3887 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3888 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
3889 out + 2, outsize + 2, svg_p->restart);
3891 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3892 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
3893 out + 3, outsize + 3, svg_p->restart);
3896 if (action & F_END) {
3897 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3898 spmin, spmax, out, outsize, svg_p, record_hdr);
3900 /* Free remaining structures */
3901 free_graphs(out, outsize, spmin, spmax);
3906 ***************************************************************************
3907 * Display CPU frequency statistics in SVG.
3910 * @a Activity structure with statistics.
3911 * @curr Index in array for current sample statistics.
3912 * @action Action expected from current function.
3913 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3914 * flag indicating that a restart record has been previously
3915 * found (.@restart) and time used for the X axis origin
3917 * @itv Interval of time in jiffies (only with F_MAIN action).
3918 * @record_hdr Pointer on record header of current stats sample.
3919 ***************************************************************************
3921 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3922 unsigned long long g_itv, struct record_header *record_hdr)
3924 struct stats_pwr_cpufreq *spc, *spp;
3926 char *title[] = {"CPU frequency"};
3927 char *g_title[] = {"MHz"};
3928 static double *spmin, *spmax;
3930 static int *outsize;
3934 if (action & F_BEGIN) {
3936 * Allocate arrays that will contain the graphs data
3937 * and the min/max values.
3939 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
3942 if (action & F_MAIN) {
3944 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
3946 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
3947 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
3949 /* Should current CPU (including CPU "all") be displayed? */
3950 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
3955 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
3956 ((double) spp->cpufreq) / 100,
3957 ((double) spc->cpufreq) / 100,
3958 out + i, outsize + i, svg_p->restart, svg_p->dt,
3959 spmin + i, spmax + i);
3963 if (action & F_END) {
3964 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
3966 /* Should current CPU (including CPU "all") be displayed? */
3967 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
3972 /* This is CPU "all" */
3973 strcpy(item_name, "all");
3976 sprintf(item_name, "%d", i - 1);
3979 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH,
3980 title, g_title, item_name, group,
3981 spmin + i, spmax + i, out + i, outsize + i,
3985 /* Free remaining structures */
3986 free_graphs(out, outsize, spmin, spmax);
3991 ***************************************************************************
3992 * Display fan statistics in SVG.
3995 * @a Activity structure with statistics.
3996 * @curr Index in array for current sample statistics.
3997 * @action Action expected from current function.
3998 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3999 * flag indicating that a restart record has been previously
4000 * found (.@restart) and time used for the X axis origin
4002 * @itv Interval of time in jiffies (only with F_MAIN action).
4003 * @record_hdr Pointer on record header of current stats sample.
4004 ***************************************************************************
4006 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4007 unsigned long long g_itv, struct record_header *record_hdr)
4009 struct stats_pwr_fan *spc, *spp;
4011 char *title[] = {"Fan speed"};
4012 char *g_title[] = {"~rpm"};
4013 static double *spmin, *spmax;
4015 static int *outsize;
4016 char item_name[MAX_SENSORS_DEV_LEN + 8];
4019 if (action & F_BEGIN) {
4021 * Allocate arrays that will contain the graphs data
4022 * and the min/max values.
4024 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4027 if (action & F_MAIN) {
4029 for (i = 0; i < a->nr; i++) {
4031 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4032 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4035 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4038 out + i, outsize + i, svg_p->restart, svg_p->dt,
4039 spmin + i, spmax + i);
4043 if (action & F_END) {
4044 for (i = 0; i < a->nr; i++) {
4046 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4048 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4049 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4051 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH,
4052 title, g_title, item_name, group,
4053 spmin + i, spmax + i, out + i, outsize + i,
4057 /* Free remaining structures */
4058 free_graphs(out, outsize, spmin, spmax);
4063 ***************************************************************************
4064 * Display temperature statistics in SVG.
4067 * @a Activity structure with statistics.
4068 * @curr Index in array for current sample statistics.
4069 * @action Action expected from current function.
4070 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4071 * flag indicating that a restart record has been previously
4072 * found (.@restart) and time used for the X axis origin
4074 * @itv Interval of time in jiffies (only with F_MAIN action).
4075 * @record_hdr Pointer on record header of current stats sample.
4076 ***************************************************************************
4078 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4079 unsigned long long g_itv, struct record_header *record_hdr)
4081 struct stats_pwr_temp *spc;
4083 char *title1[] = {"Device temperature (1)"};
4084 char *title2[] = {"Device temperature (2)"};
4085 char *g1_title[] = {"~degC"};
4086 char *g2_title[] = {"%temp"};
4087 static double *spmin, *spmax;
4089 static int *outsize;
4090 char item_name[MAX_SENSORS_DEV_LEN + 8];
4094 if (action & F_BEGIN) {
4096 * Allocate arrays that will contain the graphs data
4097 * and the min/max values.
4099 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4102 if (action & F_MAIN) {
4103 /* For each temperature sensor */
4104 for (i = 0; i < a->nr; i++) {
4106 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4108 /* Look for min/max values */
4109 if (spc->temp < *(spmin + 2 * i)) {
4110 *(spmin + 2 * i) = spc->temp;
4112 if (spc->temp > *(spmax + 2 * i)) {
4113 *(spmax + 2 * i) = spc->temp;
4115 tval = (spc->temp_max - spc->temp_min) ?
4116 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4118 if (tval < *(spmin + 2 * i + 1)) {
4119 *(spmin + 2 * i + 1) = tval;
4121 if (tval > *(spmax + 2 * i + 1)) {
4122 *(spmax + 2 * i + 1) = tval;
4126 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4128 out + 2 * i, outsize + 2 * i, svg_p->restart);
4130 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4132 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4136 if (action & F_END) {
4137 for (i = 0; i < a->nr; i++) {
4139 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4141 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4142 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4144 draw_activity_graphs(1, SVG_LINE_GRAPH,
4145 title1, g1_title, item_name, group,
4146 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4148 draw_activity_graphs(1, SVG_BAR_GRAPH,
4149 title2, g2_title, item_name, group,
4150 spmin + 2 * i + 1, spmax + 2 * i + 1,
4151 out + 2 * i + 1, outsize + 2 * i + 1,
4155 /* Free remaining structures */
4156 free_graphs(out, outsize, spmin, spmax);
4161 ***************************************************************************
4162 * Display voltage inputs statistics in SVG.
4165 * @a Activity structure with statistics.
4166 * @curr Index in array for current sample statistics.
4167 * @action Action expected from current function.
4168 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4169 * flag indicating that a restart record has been previously
4170 * found (.@restart) and time used for the X axis origin
4172 * @itv Interval of time in jiffies (only with F_MAIN action).
4173 * @record_hdr Pointer on record header of current stats sample.
4174 ***************************************************************************
4176 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4177 unsigned long long g_itv, struct record_header *record_hdr)
4179 struct stats_pwr_in *spc;
4181 char *title1[] = {"Voltage inputs (1)"};
4182 char *title2[] = {"Voltage inputs (2)"};
4183 char *g1_title[] = {"inV"};
4184 char *g2_title[] = {"%in"};
4185 static double *spmin, *spmax;
4187 static int *outsize;
4188 char item_name[MAX_SENSORS_DEV_LEN + 8];
4192 if (action & F_BEGIN) {
4194 * Allocate arrays that will contain the graphs data
4195 * and the min/max values.
4197 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4200 if (action & F_MAIN) {
4201 /* For each temperature sensor */
4202 for (i = 0; i < a->nr; i++) {
4204 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4206 /* Look for min/max values */
4207 if (spc->in < *(spmin + 2 * i)) {
4208 *(spmin + 2 * i) = spc->in;
4210 if (spc->in > *(spmax + 2 * i)) {
4211 *(spmax + 2 * i) = spc->in;
4213 tval = (spc->in_max - spc->in_min) ?
4214 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4216 if (tval < *(spmin + 2 * i + 1)) {
4217 *(spmin + 2 * i + 1) = tval;
4219 if (tval > *(spmax + 2 * i + 1)) {
4220 *(spmax + 2 * i + 1) = tval;
4224 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4226 out + 2 * i, outsize + 2 * i, svg_p->restart);
4228 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4230 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4234 if (action & F_END) {
4235 for (i = 0; i < a->nr; i++) {
4237 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4239 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4240 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4242 draw_activity_graphs(1, SVG_LINE_GRAPH,
4243 title1, g1_title, item_name, group,
4244 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4246 draw_activity_graphs(1, SVG_BAR_GRAPH,
4247 title2, g2_title, item_name, group,
4248 spmin + 2 * i + 1, spmax + 2 * i + 1,
4249 out + 2 * i + 1, outsize + 2 * i + 1,
4253 /* Free remaining structures */
4254 free_graphs(out, outsize, spmin, spmax);
4259 ***************************************************************************
4260 * Display huge pages statistics in SVG.
4263 * @a Activity structure with statistics.
4264 * @curr Index in array for current sample statistics.
4265 * @action Action expected from current function.
4266 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4267 * flag indicating that a restart record has been previously
4268 * found (.@restart) and time used for the X axis origin
4270 * @itv Interval of time in jiffies (only with F_MAIN action).
4271 * @record_hdr Pointer on record header of current stats sample.
4272 ***************************************************************************
4274 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4275 unsigned long long itv, struct record_header *record_hdr)
4278 *smc = (struct stats_huge *) a->buf[curr];
4281 char *title1[] = {"Huge pages utilization (1)"};
4282 char *title2[] = {"Huge pages utilization (2)"};
4283 char *g1_title[] = {"~kbhugfree", "~kbhugused"};
4284 char *g2_title[] = {"%hugused"};
4285 static double *spmin, *spmax;
4287 static int *outsize;
4290 if (action & F_BEGIN) {
4292 * Allocate arrays that will contain the graphs data
4293 * and the min/max values.
4295 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4298 if (action & F_MAIN) {
4299 /* Check for min/max values */
4300 save_extrema(0, 1, 0, (void *) a->buf[curr], NULL,
4303 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4304 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4306 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4307 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4309 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4310 if (tval < *(spmin + 2)) {
4311 *(spmin + 2) = tval;
4313 if (tval > *(spmax + 2)) {
4314 *(spmax + 2) = tval;
4318 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4319 (unsigned long) smc->frhkb,
4320 out, outsize, svg_p->restart);
4322 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4323 (unsigned long) smc->tlhkb - smc->frhkb,
4324 out + 1, outsize + 1, svg_p->restart);
4326 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4328 out + 2, outsize + 2, svg_p->dt);
4331 if (action & F_END) {
4332 draw_activity_graphs(1, SVG_LINE_GRAPH,
4333 title1, g1_title, NULL, group1,
4334 spmin, spmax, out, outsize, svg_p, record_hdr);
4335 draw_activity_graphs(1, SVG_BAR_GRAPH,
4336 title2, g2_title, NULL, group2,
4337 spmin + 2, spmax + 2, out + 2, outsize + 2,
4340 /* Free remaining structures */
4341 free_graphs(out, outsize, spmin, spmax);
4346 ***************************************************************************
4347 * Display filesystem statistics in SVG.
4350 * @a Activity structure with statistics.
4351 * @curr Index in array for current sample statistics.
4352 * @action Action expected from current function.
4353 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4354 * flag indicating that a restart record has been previously
4355 * found (.@restart) and time used for the X axis origin
4357 * @itv Interval of time in jiffies (only with F_MAIN action).
4358 * @record_hdr Pointer on record header of current stats sample.
4359 ***************************************************************************
4361 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4362 unsigned long long itv, struct record_header *record_hdr)
4364 struct stats_filesystem
4365 *sfc = (struct stats_filesystem *) a->buf[curr];
4366 int group1a[] = {2};
4367 int group1b[] = {2};
4368 int group2a[] = {2};
4369 int group2b[] = {1};
4370 char *title1a[] = {"Filesystem statistics (1)"};
4371 char *title1b[] = {"Filesystem statistics (2)"};
4372 char *title2a[] = {"Filesystem statistics (3)"};
4373 char *title2b[] = {"Filesystem statistics (4)"};
4374 char *g_title1a[] = {"~MBfsfree", "~MBfsused"};
4375 char *g_title1b[] = {"%ufsused", "%fsused"};
4376 char *g_title2a[] = {"Ifree/1000", "Iused/1000"};
4377 char *g_title2b[] = {"%Iused"};
4378 static double *spmin, *spmax;
4380 static int *outsize;
4385 if (action & F_BEGIN) {
4387 * Allocate arrays (#0..6) that will contain the graphs data
4388 * and the min/max values.
4389 * Also allocate two additional arrays (#7..8) for each filesystem:
4390 * out + 7 will contain the filesystem name,
4391 * out + 8 will contain the mount point.
4393 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
4396 if (action & F_MAIN) {
4397 /* For each filesystem structure */
4398 for (i = 0; i < a->nr; i++) {
4399 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4402 /* Size of filesystem is zero: We are at the end of the list */
4405 /* Look for corresponding graph */
4406 for (k = 0; k < a->nr; k++) {
4407 item_name = *(out + k * 9 + 7);
4408 if (!strcmp(sfc->fs_name, item_name))
4414 /* Graph not found: Look for first free entry */
4415 for (k = 0; k < a->nr; k++) {
4416 item_name = *(out + k * 9 + 7);
4417 if (!strcmp(item_name, ""))
4421 /* No free graph entry: Graph for this item won't be drawn */
4427 if (!item_name[0]) {
4428 /* Save filesystem name and mount point (if not already done) */
4429 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4430 item_name[CHUNKSIZE - 1] = '\0';
4431 item_name = *(out + pos + 8);
4432 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4433 item_name[CHUNKSIZE - 1] = '\0';
4436 /* Check for min/max values */
4438 /* Compute fsfree min/max values */
4439 tval = (double) sfc->f_bfree;
4440 if (tval > *(spmax + pos)) {
4441 *(spmax + pos) = tval;
4443 if (tval < *(spmin + pos)) {
4444 *(spmin + pos) = tval;
4446 /* Compute fsused min/max values */
4447 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4448 if (tval > *(spmax + pos + 1)) {
4449 *(spmax + pos + 1) = tval;
4451 if (tval < *(spmin + pos + 1)) {
4452 *(spmin + pos + 1) = tval;
4454 /* Compute %ufsused min/max values */
4455 tval = sfc->f_blocks ?
4456 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4457 if (tval > *(spmax + pos + 2)) {
4458 *(spmax + pos + 2) = tval;
4460 if (tval < *(spmin + pos + 2)) {
4461 *(spmin + pos + 2) = tval;
4463 /* Compute %fsused min/max values */
4464 tval = sfc->f_blocks ?
4465 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4466 if (tval > *(spmax + pos + 3)) {
4467 *(spmax + pos + 3) = tval;
4469 if (tval < *(spmin + pos + 3)) {
4470 *(spmin + pos + 3) = tval;
4472 /* Compute Ifree min/max values */
4473 tval = (double) sfc->f_ffree;
4474 if (tval > *(spmax + pos + 4)) {
4475 *(spmax + pos + 4) = tval;
4477 if (tval < *(spmin + pos + 4)) {
4478 *(spmin + pos + 4) = tval;
4480 /* Compute Iused min/max values */
4481 tval = (double) (sfc->f_files - sfc->f_ffree);
4482 if (tval > *(spmax + pos + 5)) {
4483 *(spmax + pos + 5) = tval;
4485 if (tval < *(spmin + pos + 5)) {
4486 *(spmin + pos + 5) = tval;
4488 /* Compute %Iused min/max values */
4489 tval = sfc->f_files ?
4490 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4491 if (tval > *(spmax + pos + 6)) {
4492 *(spmax + pos + 6) = tval;
4494 if (tval < *(spmin + pos + 6)) {
4495 *(spmin + pos + 6) = tval;
4499 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4500 (double) sfc->f_bfree / 1024 / 1024,
4501 out + pos, outsize + pos, svg_p->restart);
4503 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4504 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4505 out + pos + 1, outsize + pos + 1, svg_p->restart);
4507 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4510 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4511 out + pos + 2, outsize + pos + 2, svg_p->dt);
4513 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4516 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4517 out + pos + 3, outsize + pos + 3, svg_p->dt);
4519 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4520 ((double) sfc->f_ffree) / 1000,
4521 out + pos + 4, outsize + pos + 4, svg_p->restart);
4523 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4524 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4525 out + pos + 5, outsize + pos + 5, svg_p->restart);
4527 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4530 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4531 out + pos + 6, outsize + pos + 6, svg_p->dt);
4535 if (action & F_END) {
4537 for (i = 0; i < a->nr; i++) {
4539 /* Check if there is something to display */
4544 /* Conversion B -> MB */
4545 for (k = 0; k < 2; k++) {
4546 *(spmin + pos + k) /= (1024 * 1024);
4547 *(spmax + pos + k) /= (1024 * 1024);
4548 *(spmin + pos + 4 + k) /= 1000;
4549 *(spmax + pos + 4 + k) /= 1000;
4552 if (DISPLAY_MOUNT(a->opt_flags)) {
4553 item_name = *(out + pos + 8);
4556 item_name = *(out + pos + 7);
4559 draw_activity_graphs(1, SVG_LINE_GRAPH, title1a, g_title1a, item_name, group1a,
4560 spmin + pos, spmax + pos, out + pos, outsize + pos,
4562 draw_activity_graphs(1, SVG_BAR_GRAPH, title1b, g_title1b, item_name, group1b,
4563 spmin + pos + 2, spmax + pos + 2, out + pos + 2, outsize + pos + 2,
4565 draw_activity_graphs(1, SVG_LINE_GRAPH, title2a, g_title2a, item_name, group2a,
4566 spmin + pos + 4, spmax + pos + 4, out + pos + 4, outsize + pos + 4,
4568 draw_activity_graphs(1, SVG_BAR_GRAPH, title2b, g_title2b, item_name, group2b,
4569 spmin + pos + 6, spmax + pos + 6, out + pos + 6, outsize + pos + 6,
4573 /* Free remaining structures */
4574 free_graphs(out, outsize, spmin, spmax);
4579 ***************************************************************************
4580 * Display Fibre Channel HBA statistics in SVG.
4583 * @a Activity structure with statistics.
4584 * @curr Index in array for current sample statistics.
4585 * @action Action expected from current function.
4586 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4587 * flag indicating that a restart record has been previously
4588 * found (.@restart) and time used for the X axis origin
4590 * @itv Interval of time in jiffies (only with F_MAIN action).
4591 * @record_hdr Pointer on record header of current stats sample.
4592 ***************************************************************************
4594 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4595 unsigned long long itv, struct record_header *record_hdr)
4597 struct stats_fchost *sfcc, *sfcp;
4598 int group[] = {2, 2};
4599 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4600 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4601 "fch_rxw/s", "fch_txw/s"};
4602 static double *spmin, *spmax;
4604 static int *outsize;
4608 if (action & F_BEGIN) {
4610 * Allocate arrays (#0..3) that will contain the graphs data
4611 * and the min/max values.
4612 * Also allocate one additional array (#4) that will contain
4615 out = allocate_graph_lines(4 * a->nr, &outsize, &spmin, &spmax);
4618 if (action & F_MAIN) {
4619 /* For each FC HBA */
4620 for (i = 0; i < a->nr; i++) {
4622 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4623 if (!sfcc->fchost_name[0])
4624 /* We are at the end of the list */
4627 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
4630 item_name = *(out + pos + 4);
4631 if (!item_name[0]) {
4632 /* Save FC HBA name */
4633 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4634 item_name[CHUNKSIZE - 1] = '\0';
4637 /* Look for min/max values */
4638 save_extrema(0, 4, 0, (void *) sfcc, (void *) sfcp,
4639 itv, spmin + pos, spmax + pos);
4642 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4643 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4644 out + pos, outsize + pos, svg_p->restart);
4647 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4648 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4649 out + pos + 1, outsize + pos + 1, svg_p->restart);
4652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4653 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4654 out + pos + 2, outsize + pos + 2, svg_p->restart);
4657 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4658 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4659 out + pos + 3, outsize + pos + 3, svg_p->restart);
4663 if (action & F_END) {
4664 for (i = 0; i < a->nr; i++) {
4666 /* Check if there is something to display */
4671 item_name = *(out + pos + 4);
4672 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH,
4673 title, g_title, item_name, group,
4674 spmin + pos, spmax + pos, out + pos, outsize + pos,
4678 /* Free remaining structures */
4679 free_graphs(out, outsize, spmin, spmax);