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 * Display all graphs for current activity.
621 * @g_nr Number of sets of graphs (views) to display.
622 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
623 * @title Titles for each set of graphs.
624 * @g_title Titles for each graph.
625 * @item_name Item (network interface, etc.) name.
626 * @group Indicate how graphs are grouped together to make sets.
627 * @spmin Array containing min values for graphs.
628 * @spmax Array containing max values for graphs.
629 * @out Pointer on array of chars for each graph definition.
630 * @outsize Size of array of chars for each graph definition.
631 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
632 * time for the first sample of stats (.@ust_time_first), and
633 * times used as start and end values on the X axis
634 * (.@ust_time_ref and .@ust_time_end).
635 * @record_hdr Pointer on record header of current stats sample.
636 ***************************************************************************
638 void draw_activity_graphs(int g_nr, int g_type, char *title[], char *g_title[], char *item_name,
639 int group[], double *spmin, double *spmax, char **out, int *outsize,
640 struct svg_parm *svg_p, struct record_header *record_hdr)
642 struct record_header stamp;
645 int i, j, dp, pos = 0, views_nr = 0;
647 unsigned int asfactor[16];
649 double lmax, xfactor, yfactor, ypos, gmin, gmax;
650 char cur_time[32], val[32], stmp[32];
652 /* Translate to proper position for current activity */
653 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
655 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
657 /* For each set of graphs which are part of current activity */
658 for (i = 0; i < g_nr; i++) {
660 /* Get global min and max value for current set of graphs */
661 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
663 /* Don't display empty views if requested */
664 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005))
666 /* Increment number of views actually displayed */
669 /* Graph background */
670 printf("<rect x=\"0\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
672 SVG_V_YSIZE, SVG_V_XSIZE);
675 printf("<text x=\"0\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
676 20 + i * SVG_T_YSIZE, title[i]);
678 printf(" [%s]", item_name);
681 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
682 "(Min, Max values)</tspan>\n</text>\n",
683 5 + SVG_M_XSIZE + SVG_G_XSIZE,
684 25 + i * SVG_T_YSIZE);
687 * At least two samples are needed.
688 * And a min and max value should have been found.
690 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
691 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
693 printf("<text x=\"0\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
694 SVG_M_YSIZE + i * SVG_T_YSIZE);
699 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
700 SVG_M_XSIZE, SVG_M_YSIZE + i * SVG_T_YSIZE,
701 SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + i * SVG_T_YSIZE,
702 SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + i * SVG_T_YSIZE);
704 for (j = 0; j < 16; j++) {
705 /* Init autoscale factors */
709 if (AUTOSCALE_ON(flags) && (group[i] > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
711 for (j = 0; (j < group[i]) && (j < 16); j++) {
712 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
715 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
716 if (strlen(val) > 0) {
717 asfactor[j] = pwr10(strlen(val) - 1);
723 for (j = 0; j < group[i]; j++) {
724 /* Set dp to TRUE (1) if current metric is based on integer values */
725 dp = (g_title[pos + j][0] == '~');
726 snprintf(val, 32, "x%u ", asfactor[j]);
727 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
728 "%s %s(%.*f, %.*f)</text>\n",
729 5 + SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + i * SVG_T_YSIZE + j * 15,
730 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
731 asfactor[j] == 1 ? "" : val,
732 !dp * 2, *(spmin + pos + j) * asfactor[j],
733 !dp * 2, *(spmax + pos + j) * asfactor[j]);
736 /* Translate to proper position for current graph within current activity */
737 printf("<g transform=\"translate(%d,%d)\">\n",
738 SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + i * SVG_T_YSIZE);
741 if (g_type == SVG_LINE_GRAPH) {
742 /* For line graphs */
744 /* If all values are zero then set current max value to 1 */
750 /* Max value cannot be too small, else Y graduations will be meaningless */
751 if (lmax < SVG_H_GRIDNR * 0.01) {
752 lmax = SVG_H_GRIDNR * 0.01;
754 ypos = ygrid(lmax, &dp);
757 /* For bar graphs (used for %values) */
758 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
759 dp = 0; /* No decimals */
761 /* Max should be always 100% except for percentage values greater than 100% */
769 yfactor = (double) -SVG_G_YSIZE / lmax;
772 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
773 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
774 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
777 while (ypos * j <= lmax);
781 * Use same rounded value for graduation numbers as for grid lines
782 * to make sure they are properly aligned.
784 sprintf(stmp, "%.2f", ypos * j);
786 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
787 "text-anchor: end\">%.*f.</text>\n",
788 (long) (atof(stmp) * yfactor), dp, ypos * j);
791 while (ypos * j <= lmax);
793 /* Set number of vertical lines to 12 when option "oneday" is used */
794 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
796 k = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
797 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
798 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
800 for (j = 0; (j <= v_gridnr) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
801 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
802 set_record_timestamp_string(flags, &stamp, NULL, cur_time, 32, &rectime);
803 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
804 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
805 k * j, k * j, -SVG_G_YSIZE, xfactor);
807 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
808 * In this case, we should rather display the exact time instead of only the hour.
810 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
811 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
812 "text-anchor: start\">%2dH</text>\n",
813 (long) (k * j * xfactor) - 8, rectime.tm_hour);
816 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
817 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
818 (long) (k * j * xfactor), (long) (k * j * xfactor), cur_time);
822 if (!PRINT_LOCAL_TIME(flags)) {
823 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
824 "text-anchor: end\">UTC</text>\n");
827 /* Draw current graphs set */
828 for (j = 0; j < group[i]; j++) {
829 out_p = *(out + pos + j);
830 if (g_type == SVG_LINE_GRAPH) {
832 printf("<path id=\"g%dp%d\" d=\"%s\" "
833 "style=\"vector-effect: non-scaling-stroke; "
834 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
835 "transform=\"scale(%f,%f)\"/>\n",
836 svg_p->graph_no, pos + j, out_p,
837 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
839 yfactor * asfactor[j]);
841 else if (*out_p) { /* Ignore flat bars */
843 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
844 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
845 printf("%s\n", out_p);
856 (svg_p->graph_no) += views_nr;
860 ***************************************************************************
861 * Display CPU statistics in SVG.
864 * @a Activity structure with statistics.
865 * @curr Index in array for current sample statistics.
866 * @action Action expected from current function.
867 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
868 * flag indicating that a restart record has been previously
869 * found (.@restart), and time used for the X axis origin
871 * @itv Interval of time in jiffies (only with F_MAIN action).
872 * @record_hdr Pointer on record header of current stats sample.
873 ***************************************************************************
875 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
876 unsigned long long g_itv, struct record_header *record_hdr)
878 struct stats_cpu *scc, *scp;
881 char *title[] = {"CPU load"};
882 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
883 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
884 static double *spmin, *spmax;
889 int i, j, k, pos, cpu_offline;
891 if (action & F_BEGIN) {
893 * Allocate arrays that will contain the graphs data
894 * and the min/max values.
896 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
899 if (action & F_MAIN) {
901 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
903 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
904 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
906 /* Should current CPU (including CPU "all") be displayed? */
907 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
914 if (i) { /* Don't test CPU "all" here */
916 * If the CPU is offline then it is omited from /proc/stat:
917 * All the fields couldn't have been read and the sum of them is zero.
918 * (Remember that guest/guest_nice times are already included in
921 if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys +
922 scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal +
923 scc->cpu_hardirq + scc->cpu_softirq) == 0) {
925 * Set current struct fields (which have been set to zero)
926 * to values from previous iteration. Hence their values won't
927 * jump from zero when the CPU comes back online.
936 * Recalculate interval for current proc.
937 * If result is 0 then current CPU is a tickless one.
939 g_itv = get_per_cpu_interval(scc, scp);
943 if (!g_itv) { /* Current CPU is offline or tickless */
945 val = (cpu_offline ? 0.0 /* Offline CPU: %idle = 0% */
946 : 100.0); /* Tickless CPU: %idle = 100% */
948 if (DISPLAY_CPU_DEF(a->opt_flags)) {
951 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
955 /* Check min/max values for %user, etc. */
956 for (k = 0; k < j; k++) {
957 if (0.0 < *(spmin + pos + k)) {
958 *(spmin + pos + k) = 0.0;
960 if (0.0 > *(spmax + pos + k)) {
961 *(spmax + pos + k) = 0.0;
966 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
968 out + pos + j, outsize + pos + j, svg_p->dt,
969 spmin + pos + j, spmax + pos + j);
974 if (DISPLAY_CPU_DEF(a->opt_flags)) {
976 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
977 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv),
978 out + pos, outsize + pos, svg_p->dt,
979 spmin + pos, spmax + pos);
983 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
985 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
987 ll_sp_value(scp->cpu_user - scp->cpu_guest,
988 scc->cpu_user - scc->cpu_guest, g_itv),
989 out + pos, outsize + pos, svg_p->dt,
990 spmin + pos, spmax + pos);
993 if (DISPLAY_CPU_DEF(a->opt_flags)) {
995 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
996 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv),
997 out + pos + 1, outsize + pos + 1, svg_p->dt,
998 spmin + pos + 1, spmax + pos + 1);
1002 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1004 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1006 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1007 scc->cpu_nice - scc->cpu_guest_nice, g_itv),
1008 out + pos + 1, outsize + pos + 1, svg_p->dt,
1009 spmin + pos + 1, spmax + pos + 1);
1012 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1014 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1016 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1017 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1019 out + pos + 2, outsize + pos + 2, svg_p->dt,
1020 spmin + pos + 2, spmax + pos + 2);
1024 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1025 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv),
1026 out + pos + 2, outsize + pos + 2, svg_p->dt,
1027 spmin + pos + 2, spmax + pos + 2);
1031 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1032 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
1033 out + pos + 3, outsize + pos + 3, svg_p->dt,
1034 spmin + pos + 3, spmax + pos + 3);
1037 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1038 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
1039 out + pos + 4, outsize + pos + 4, svg_p->dt,
1040 spmin + pos + 4, spmax + pos + 4);
1042 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1044 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1045 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv),
1046 out + pos + 5, outsize + pos + 5, svg_p->dt,
1047 spmin + pos + 5, spmax + pos + 5);
1050 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1051 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv),
1052 out + pos + 6, outsize + pos + 6, svg_p->dt,
1053 spmin + pos + 6, spmax + pos + 6);
1056 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1057 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv),
1058 out + pos + 7, outsize + pos + 7, svg_p->dt,
1059 spmin + pos + 7, spmax + pos + 7);
1062 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1063 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, g_itv),
1064 out + pos + 8, outsize + pos + 8, svg_p->dt,
1065 spmin + pos + 8, spmax + pos + 8);
1074 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1076 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1077 ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv)),
1078 out + pos + j, outsize + pos + j, svg_p->dt,
1079 spmin + pos + j, spmax + pos + j);
1083 if (action & F_END) {
1084 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1086 /* Should current CPU (including CPU "all") be displayed? */
1087 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1093 /* This is CPU "all" */
1094 strcpy(item_name, "all");
1097 sprintf(item_name, "%d", i - 1);
1100 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1101 draw_activity_graphs(a->g_nr, SVG_BAR_GRAPH,
1102 title, g_title1, item_name, group1,
1103 spmin + pos, spmax + pos, out + pos, outsize + pos,
1107 draw_activity_graphs(a->g_nr, SVG_BAR_GRAPH,
1108 title, g_title2, item_name, group2,
1109 spmin + pos, spmax + pos, out + pos, outsize + pos,
1114 /* Free remaining structures */
1115 free_graphs(out, outsize, spmin, spmax);
1120 ***************************************************************************
1121 * Display task creation and context switch statistics in SVG.
1124 * @a Activity structure with statistics.
1125 * @curr Index in array for current sample statistics.
1126 * @action Action expected from current function.
1127 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1128 * flag indicating that a restart record has been previously
1129 * found (.@restart) and time used for the X axis origin
1131 * @itv Interval of time in jiffies (only with F_MAIN action).
1132 * @record_hdr Pointer on record header of current stats sample.
1133 ***************************************************************************
1135 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1136 unsigned long long itv, struct record_header *record_hdr)
1139 *spc = (struct stats_pcsw *) a->buf[curr],
1140 *spp = (struct stats_pcsw *) a->buf[!curr];
1141 int group[] = {1, 1};
1142 char *title[] = {"Switching activity", "Task creation"};
1143 char *g_title[] = {"cswch/s",
1145 static double *spmin, *spmax;
1147 static int *outsize;
1149 if (action & F_BEGIN) {
1151 * Allocate arrays that will contain the graphs data
1152 * and the min/max values.
1154 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1157 if (action & F_MAIN) {
1158 /* Check for min/max values */
1159 save_extrema(1, 1, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1162 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1163 S_VALUE(spp->context_switch, spc->context_switch, itv),
1164 out, outsize, svg_p->restart);
1166 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1167 S_VALUE(spp->processes, spc->processes, itv),
1168 out + 1, outsize + 1, svg_p->restart);
1171 if (action & F_END) {
1172 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1173 spmin, spmax, out, outsize, svg_p, record_hdr);
1175 /* Free remaining structures */
1176 free_graphs(out, outsize, spmin, spmax);
1181 ***************************************************************************
1182 * Display swap statistics in SVG.
1185 * @a Activity structure with statistics.
1186 * @curr Index in array for current sample statistics.
1187 * @action Action expected from current function.
1188 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1189 * flag indicating that a restart record has been previously
1190 * found (.@restart) and time used for the X axis origin
1192 * @itv Interval of time in jiffies (only with F_MAIN action).
1193 * @record_hdr Pointer on record header of current stats sample.
1194 ***************************************************************************
1196 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1197 unsigned long long itv, struct record_header *record_hdr)
1200 *ssc = (struct stats_swap *) a->buf[curr],
1201 *ssp = (struct stats_swap *) a->buf[!curr];
1203 char *title[] = {"Swap activity"};
1204 char *g_title[] = {"pswpin/s", "pswpout/s" };
1205 static double *spmin, *spmax;
1207 static int *outsize;
1209 if (action & F_BEGIN) {
1211 * Allocate arrays that will contain the graphs data
1212 * and the min/max values.
1214 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1217 if (action & F_MAIN) {
1218 /* Check for min/max values */
1219 save_extrema(0, 2, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1222 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1223 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1224 out, outsize, svg_p->restart);
1226 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1227 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1228 out + 1, outsize + 1, svg_p->restart);
1231 if (action & F_END) {
1232 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1233 spmin, spmax, out, outsize, svg_p, record_hdr);
1235 /* Free remaining structures */
1236 free_graphs(out, outsize, spmin, spmax);
1241 ***************************************************************************
1242 * Display paging statistics in SVG.
1245 * @a Activity structure with statistics.
1246 * @curr Index in array for current sample statistics.
1247 * @action Action expected from current function.
1248 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1249 * flag indicating that a restart record has been previously
1250 * found (.@restart) and time used for the X axis origin
1252 * @itv Interval of time in jiffies (only with F_MAIN action).
1253 * @record_hdr Pointer on record header of current stats sample.
1254 ***************************************************************************
1256 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1257 unsigned long long itv, struct record_header *record_hdr)
1260 *spc = (struct stats_paging *) a->buf[curr],
1261 *spp = (struct stats_paging *) a->buf[!curr];
1262 int group[] = {2, 2, 4};
1263 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1264 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1265 "fault/s", "majflt/s",
1266 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1267 static double *spmin, *spmax;
1269 static int *outsize;
1271 if (action & F_BEGIN) {
1273 * Allocate arrays that will contain the graphs data
1274 * and the min/max values.
1276 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1279 if (action & F_MAIN) {
1280 /* Check for min/max values */
1281 save_extrema(0, 8, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1284 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1285 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1286 out, outsize, svg_p->restart);
1288 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1289 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1290 out + 1, outsize + 1, svg_p->restart);
1292 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1293 S_VALUE(spp->pgfault, spc->pgfault, itv),
1294 out + 2, outsize + 2, svg_p->restart);
1296 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1297 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1298 out + 3, outsize + 3, svg_p->restart);
1300 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1301 S_VALUE(spp->pgfree, spc->pgfree, itv),
1302 out + 4, outsize + 4, svg_p->restart);
1304 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1305 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1306 out + 5, outsize + 5, svg_p->restart);
1308 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1309 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1310 out + 6, outsize + 6, svg_p->restart);
1312 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1313 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1314 out + 7, outsize + 7, svg_p->restart);
1317 if (action & F_END) {
1318 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1319 spmin, spmax, out, outsize, svg_p, record_hdr);
1321 /* Free remaining structures */
1322 free_graphs(out, outsize, spmin, spmax);
1327 ***************************************************************************
1328 * Display I/O and transfer rate statistics in SVG.
1331 * @a Activity structure with statistics.
1332 * @curr Index in array for current sample statistics.
1333 * @action Action expected from current function.
1334 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1335 * flag indicating that a restart record has been previously
1336 * found (.@restart) and time used for the X axis origin
1338 * @itv Interval of time in jiffies (only with F_MAIN action).
1339 * @record_hdr Pointer on record header of current stats sample.
1340 ***************************************************************************
1342 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1343 unsigned long long itv, struct record_header *record_hdr)
1346 *sic = (struct stats_io *) a->buf[curr],
1347 *sip = (struct stats_io *) a->buf[!curr];
1348 int group[] = {3, 2};
1349 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1350 char *g_title[] = {"tps", "rtps", "wtps",
1351 "bread/s", "bwrtn/s"};
1352 static double *spmin, *spmax;
1354 static int *outsize;
1356 if (action & F_BEGIN) {
1358 * Allocate arrays that will contain the graphs data
1359 * and the min/max values.
1361 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1364 if (action & F_MAIN) {
1365 /* Check for min/max values */
1366 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1370 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1371 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1372 out, outsize, svg_p->restart);
1374 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1375 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1376 out + 1, outsize + 1, svg_p->restart);
1378 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1379 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1380 out + 2, outsize + 2, svg_p->restart);
1382 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1383 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1384 out + 3, outsize + 3, svg_p->restart);
1386 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1387 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1388 out + 4, outsize + 4, svg_p->restart);
1391 if (action & F_END) {
1392 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1393 spmin, spmax, out, outsize, svg_p, record_hdr);
1395 /* Free remaining structures */
1396 free_graphs(out, outsize, spmin, spmax);
1401 ***************************************************************************
1402 * Display memory statistics in SVG.
1405 * @a Activity structure with statistics.
1406 * @curr Index in array for current sample statistics.
1407 * @action Action expected from current function.
1408 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1409 * flag indicating that a restart record has been previously
1410 * found (.@restart) and time used for the X axis origin
1412 * @itv Interval of time in jiffies (only with F_MAIN action).
1413 * @record_hdr Pointer on record header of current stats sample.
1414 ***************************************************************************
1416 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1417 unsigned long long itv, struct record_header *record_hdr)
1420 *smc = (struct stats_memory *) a->buf[curr];
1421 int group1a[] = {2, 2};
1422 int group1b[] = {1, 1};
1423 int group1c[] = {4, 5};
1424 int group2a[] = {3};
1425 int group2b[] = {1, 1};
1426 char *title1a[] = {"Memory utilization (1)", "Memory utilization (2)"};
1427 char *title1b[] = {"Memory utilization (3)", "Memory utilization (4)"};
1428 char *title1c[] = {"Memory utilization (5)", "Memory utilization (6)"};
1429 char *title2a[] = {"Swap utilization (1)"};
1430 char *title2b[] = {"Swap utilization (2)", "Swap utilization (3)"};
1431 char *g_title1a[] = {"MBmemfree", "MBmemused",
1432 "MBcached", "MBbuffers"};
1433 char *g_title1b[] = {"%memused", "%commit"};
1434 char *g_title1c[] = {"MBcommit", "MBactive", "MBinact", "MBdirty",
1435 "MBanonpg", "MBslab", "MBkstack", "MBpgtbl", "MBvmused"};
1436 char *g_title2a[] = {"MBswpfree", "MBswpused", "MBswpcad"};
1437 char *g_title2b[] = {"%swpused", "%swpcad"};
1438 static double *spmin, *spmax;
1440 static int *outsize;
1444 if (action & F_BEGIN) {
1446 * Allocate arrays that will contain the graphs data
1447 * and the min/max values.
1449 out = allocate_graph_lines(22, &outsize, &spmin, &spmax);
1452 if (action & F_MAIN) {
1453 /* Check for min/max values */
1454 save_extrema(0, 16, 0, (void *) a->buf[curr], NULL,
1456 /* Compute %memused min/max values */
1457 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1458 if (tval > *(spmax + 16)) {
1459 *(spmax + 16) = tval;
1461 if (tval < *(spmin + 16)) {
1462 *(spmin + 16) = tval;
1464 /* Compute %commit min/max values */
1465 tval = (smc->tlmkb + smc->tlskb) ?
1466 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1467 if (tval > *(spmax + 17)) {
1468 *(spmax + 17) = tval;
1470 if (tval < *(spmin + 17)) {
1471 *(spmin + 17) = tval;
1473 /* Compute %swpused min/max values */
1475 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1476 if (tval > *(spmax + 18)) {
1477 *(spmax + 18) = tval;
1479 if (tval < *(spmin + 18)) {
1480 *(spmin + 18) = tval;
1482 /* Compute %swpcad min/max values */
1483 tval = (smc->tlskb - smc->frskb) ?
1484 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1485 if (tval > *(spmax + 19)) {
1486 *(spmax + 19) = tval;
1488 if (tval < *(spmin + 19)) {
1489 *(spmin + 19) = tval;
1491 /* Compute memused min/max values in MB */
1492 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1493 if (tval > *(spmax + 20)) {
1494 *(spmax + 20) = tval;
1496 if (tval < *(spmin + 20)) {
1497 *(spmin + 20) = tval;
1499 /* Compute swpused min/max values in MB */
1500 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1501 if (tval > *(spmax + 21)) {
1502 *(spmax + 21) = tval;
1504 if (tval < *(spmin + 21)) {
1505 *(spmin + 21) = tval;
1509 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1510 ((double) smc->frmkb) / 1024,
1511 out, outsize, svg_p->restart);
1513 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1514 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1515 out + 1, outsize + 1, svg_p->restart);
1517 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1518 ((double) smc->camkb) / 1024,
1519 out + 2, outsize + 2, svg_p->restart);
1521 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1522 ((double) smc->bufkb) / 1024,
1523 out + 3, outsize + 3, svg_p->restart);
1525 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1526 ((double) smc->frskb) / 1024,
1527 out + 4, outsize + 4, svg_p->restart);
1529 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1530 ((double) (smc->tlskb - smc->frskb)) / 1024,
1531 out + 5, outsize + 5, svg_p->restart);
1533 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1534 ((double) smc->caskb) / 1024,
1535 out + 6, outsize + 6, svg_p->restart);
1537 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1538 ((double) smc->comkb) / 1024,
1539 out + 7, outsize + 7, svg_p->restart);
1541 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1542 ((double) smc->activekb) / 1024,
1543 out + 8, outsize + 8, svg_p->restart);
1545 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1546 ((double) smc->inactkb) / 1024,
1547 out + 9, outsize + 9, svg_p->restart);
1549 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1550 ((double) smc->dirtykb) / 1024,
1551 out + 10, outsize + 10, svg_p->restart);
1553 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1554 ((double) smc->anonpgkb) / 1024,
1555 out + 11, outsize + 11, svg_p->restart);
1557 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1558 ((double) smc->slabkb) / 1024,
1559 out + 12, outsize + 12, svg_p->restart);
1561 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1562 ((double) smc->kstackkb) / 1024,
1563 out + 13, outsize + 13, svg_p->restart);
1565 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1566 ((double) smc->pgtblkb) / 1024,
1567 out + 14, outsize + 14, svg_p->restart);
1569 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1570 ((double) smc->vmusedkb) / 1024,
1571 out + 15, outsize + 15, svg_p->restart);
1573 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1576 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1577 out + 16, outsize + 16, svg_p->dt);
1579 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1581 (smc->tlmkb + smc->tlskb) ?
1582 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1583 out + 17, outsize + 17, svg_p->dt);
1585 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1588 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1589 out + 18, outsize + 18, svg_p->dt);
1591 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1593 (smc->tlskb - smc->frskb) ?
1594 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1595 out + 19, outsize + 19, svg_p->dt);
1598 if (action & F_END) {
1600 /* Conversion kB -> MB */
1601 for (i = 0; i < 16; i++) {
1602 *(spmin + i) /= 1024;
1603 *(spmax + i) /= 1024;
1606 if (DISPLAY_MEM_AMT(a->opt_flags)) {
1607 /* frmkb and tlmkb should be together because they will be drawn on the same view */
1608 *(spmax + 3) = *(spmax + 1);
1609 *(spmin + 3) = *(spmin + 1);
1610 /* Move memused min/max values */
1611 *(spmax + 1) = *(spmax + 20);
1612 *(spmin + 1) = *(spmin + 20);
1614 draw_activity_graphs(2, SVG_LINE_GRAPH, title1a, g_title1a, NULL, group1a,
1615 spmin, spmax, out, outsize, svg_p, record_hdr);
1616 draw_activity_graphs(2, SVG_BAR_GRAPH, title1b, g_title1b, NULL, group1b,
1617 spmin + 16, spmax + 16, out + 16, outsize + 16, svg_p, record_hdr);
1618 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 2 : 1,
1619 SVG_LINE_GRAPH, title1c, g_title1c, NULL, group1c,
1620 spmin + 7, spmax + 7, out + 7, outsize + 7, svg_p, record_hdr);
1623 if (DISPLAY_SWAP(a->opt_flags)) {
1624 /* Move swpused min/max values */
1625 *(spmax + 5) = *(spmax + 21);
1626 *(spmin + 5) = *(spmin + 21);
1628 draw_activity_graphs(1, SVG_LINE_GRAPH, title2a, g_title2a, NULL, group2a,
1629 spmin + 4, spmax + 4, out + 4, outsize + 4, svg_p, record_hdr);
1630 draw_activity_graphs(2, SVG_BAR_GRAPH, title2b, g_title2b, NULL, group2b,
1631 spmin + 18, spmax + 18, out + 18, outsize + 18, svg_p, record_hdr);
1634 /* Free remaining structures */
1635 free_graphs(out, outsize, spmin, spmax);
1640 ***************************************************************************
1641 * Display kernel tables statistics in SVG.
1644 * @a Activity structure with statistics.
1645 * @curr Index in array for current sample statistics.
1646 * @action Action expected from current function.
1647 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1648 * flag indicating that a restart record has been previously
1649 * found (.@restart) and time used for the X axis origin
1651 * @itv Interval of time in jiffies (only with F_MAIN action).
1652 * @record_hdr Pointer on record header of current stats sample.
1653 ***************************************************************************
1655 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1656 unsigned long long itv, struct record_header *record_hdr)
1658 struct stats_ktables
1659 *skc = (struct stats_ktables *) a->buf[curr];
1660 int group[] = {3, 1};
1661 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1662 char *g_title[] = {"~file-nr", "~inode-nr", "~dentunusd",
1664 static double *spmin, *spmax;
1666 static int *outsize;
1668 if (action & F_BEGIN) {
1670 * Allocate arrays that will contain the graphs data
1671 * and the min/max values.
1673 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1676 if (action & F_MAIN) {
1677 /* Check for min/max values */
1678 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
1681 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1682 (unsigned long) skc->file_used,
1683 out, outsize, svg_p->restart);
1685 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1686 (unsigned long) skc->inode_used,
1687 out + 1, outsize + 1, svg_p->restart);
1689 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1690 (unsigned long) skc->dentry_stat,
1691 out + 2, outsize + 2, svg_p->restart);
1693 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1694 (unsigned long) skc->pty_nr,
1695 out + 3, outsize + 3, svg_p->restart);
1698 if (action & F_END) {
1699 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1700 spmin, spmax, out, outsize, svg_p, record_hdr);
1702 /* Free remaining structures */
1703 free_graphs(out, outsize, spmin, spmax);
1708 ***************************************************************************
1709 * Display queue and load statistics in SVG.
1712 * @a Activity structure with statistics.
1713 * @curr Index in array for current sample statistics.
1714 * @action Action expected from current function.
1715 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1716 * flag indicating that a restart record has been previously
1717 * found (.@restart) and time used for the X axis origin
1719 * @itv Interval of time in jiffies (only with F_MAIN action).
1720 * @record_hdr Pointer on record header of current stats sample.
1721 ***************************************************************************
1723 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1724 unsigned long long itv, struct record_header *record_hdr)
1727 *sqc = (struct stats_queue *) a->buf[curr];
1728 int group[] = {2, 3, 1};
1729 char *title[] = {"Queue length", "Load average", "Task list"};
1730 char *g_title[] = {"~runq-sz", "~blocked",
1731 "ldavg-1", "ldavg-5", "ldavg-15",
1733 static double *spmin, *spmax;
1735 static int *outsize;
1737 if (action & F_BEGIN) {
1739 * Allocate arrays that will contain the graphs data
1740 * and the min/max values.
1742 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1745 if (action & F_MAIN) {
1746 /* Check for min/max values */
1747 save_extrema(0, 2, 4, (void *) a->buf[curr], NULL,
1750 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1751 (unsigned long) sqc->nr_running,
1752 out, outsize, svg_p->restart);
1754 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1755 (unsigned long) sqc->procs_blocked,
1756 out + 1, outsize + 1, svg_p->restart);
1758 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1759 (double) sqc->load_avg_1 / 100,
1760 out + 2, outsize + 2, svg_p->restart);
1762 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1763 (double) sqc->load_avg_5 / 100,
1764 out + 3, outsize + 3, svg_p->restart);
1766 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1767 (double) sqc->load_avg_15 / 100,
1768 out + 4, outsize + 4, svg_p->restart);
1770 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1771 (unsigned long) sqc->nr_threads,
1772 out + 5, outsize + 5, svg_p->restart);
1775 if (action & F_END) {
1776 /* Fix min/max values for load average */
1777 *(spmin + 2) /= 100; *(spmax + 2) /= 100;
1778 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1779 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1781 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
1782 spmin, spmax, out, outsize, svg_p, record_hdr);
1784 /* Free remaining structures */
1785 free_graphs(out, outsize, spmin, spmax);
1790 ***************************************************************************
1791 * Display disk statistics in SVG.
1794 * @a Activity structure with statistics.
1795 * @curr Index in array for current sample statistics.
1796 * @action Action expected from current function.
1797 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1798 * flag indicating that a restart record has been previously
1799 * found (.@restart) and time used for the X axis origin
1801 * @itv Interval of time in jiffies (only with F_MAIN action).
1802 * @record_hdr Pointer on record header of current stats sample.
1803 ***************************************************************************
1805 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1806 unsigned long long itv, struct record_header *record_hdr)
1808 struct stats_disk *sdc, *sdp;
1809 struct ext_disk_stats xds;
1810 int group1[] = {1, 2, 2, 2};
1812 char *title1[] = {"Disk statistics (1)", "Disk statistics (2)",
1813 "Disk statistics (3)", "Disk statistics (4)"};
1814 char *title2[] = {"Disk statistics (5)"};
1815 char *g_title1[] = {"tps",
1816 "rd_sec/s", "wr_sec/s",
1817 "avgrq-sz", "avgqu-sz",
1819 char *g_title2[] = {"%util"};
1820 static double *spmin, *spmax;
1822 static int *outsize;
1823 char *item_name, *persist_dev_name;
1825 int i, j, k, pos, restart, *unregistered;
1827 if (action & F_BEGIN) {
1829 * Allocate arrays (#0..7) that will contain the graphs data
1830 * and the min/max values.
1831 * Also allocate one additional array (#8) for each disk device:
1832 * spmax + 8 will contain the device major number,
1833 * spmin + 8 will contain the device minor number,
1834 * outsize + 8 will contain a positive value (TRUE) if the device
1835 * has either still not been registered, or has been unregistered.
1837 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
1840 if (action & F_MAIN) {
1841 restart = svg_p->restart;
1843 * Mark previously registered devices as now
1844 * possibly unregistered for all graphs.
1846 for (k = 0; k < a->nr; k++) {
1847 unregistered = outsize + k * 9 + 8;
1848 if (*unregistered == FALSE) {
1849 *unregistered = MAYBE;
1853 /* For each device structure */
1854 for (i = 0; i < a->nr; i++) {
1855 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
1856 if (!(sdc->major + sdc->minor))
1857 /* Empty structure: Ignore it */
1860 /* Look for corresponding graph */
1861 for (k = 0; k < a->nr; k++) {
1862 if ((sdc->major == *(spmax + k * 9 + 8)) &&
1863 (sdc->minor == *(spmin + k * 9 + 8)))
1868 /* Graph not found: Look for first free entry */
1869 for (k = 0; k < a->nr; k++) {
1870 if (*(spmax + k * 9 + 8) == -DBL_MAX)
1874 /* No free graph entry: Graph for this item won't be drawn */
1878 unregistered = outsize + pos + 8;
1880 j = check_disk_reg(a, curr, !curr, i);
1881 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
1884 * If current device was marked as previously unregistered,
1885 * then set restart variable to TRUE so that the graph will be
1886 * discontinuous, and mark it as now registered.
1888 if (*unregistered == TRUE) {
1891 *unregistered = FALSE;
1893 if (*(spmax + pos + 8) == -DBL_MAX) {
1894 /* Save device major and minor numbers (if not already done) */
1895 *(spmax + pos + 8) = sdc->major;
1896 *(spmin + pos + 8) = sdc->minor;
1899 /* Check for min/max values */
1900 save_extrema(1, 2, 0, (void *) sdc, (void *) sdp,
1901 itv, spmin + pos, spmax + pos);
1903 compute_ext_disk_stats(sdc, sdp, itv, &xds);
1904 if (xds.arqsz < *(spmin + pos + 3)) {
1905 *(spmin + pos + 3) = xds.arqsz;
1907 if (xds.arqsz > *(spmax + pos + 3)) {
1908 *(spmax + pos + 3) = xds.arqsz;
1910 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
1911 if (aqusz < *(spmin + pos + 4)) {
1912 *(spmin + pos + 4) = aqusz;
1914 if (aqusz > *(spmax + pos + 4)) {
1915 *(spmax + pos + 4) = aqusz;
1917 if (xds.await < *(spmin + pos + 5)) {
1918 *(spmin + pos + 5) = xds.await;
1920 if (xds.await > *(spmax + pos + 5)) {
1921 *(spmax + pos + 5) = xds.await;
1923 if (xds.svctm < *(spmin + pos + 6)) {
1924 *(spmin + pos + 6) = xds.svctm;
1926 if (xds.svctm > *(spmax + pos + 6)) {
1927 *(spmax + pos + 6) = xds.svctm;
1929 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
1930 *(spmin + pos + 7) = xds.util / 10.0;
1932 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
1933 *(spmax + pos + 7) = xds.util / 10.0;
1937 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1938 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
1939 out + pos, outsize + pos, restart);
1942 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1943 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv),
1944 out + pos + 1, outsize + pos + 1, restart);
1947 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1948 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv),
1949 out + pos + 2, outsize + pos + 2, restart);
1952 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1954 out + pos + 3, outsize + pos + 3, restart);
1957 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1959 out + pos + 4, outsize + pos + 4, restart);
1962 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1964 out + pos + 5, outsize + pos + 5, restart);
1967 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1969 out + pos + 6, outsize + pos + 6, restart);
1972 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1973 0.0, xds.util / 10.0,
1974 out + pos + 7, outsize + pos + 7, svg_p->dt);
1977 /* Mark devices not seen here as now unregistered */
1978 for (k = 0; k < a->nr; k++) {
1979 unregistered = outsize + k * 9 + 8;
1980 if (*unregistered != FALSE) {
1981 *unregistered = TRUE;
1986 if (action & F_END) {
1987 for (i = 0; i < a->nr; i++) {
1988 /* Check if there is something to display */
1994 persist_dev_name = NULL;
1996 if (DISPLAY_PERSIST_NAME_S(flags)) {
1997 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2001 if (persist_dev_name) {
2002 item_name = persist_dev_name;
2005 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2006 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2010 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2011 USE_PRETTY_OPTION(flags));
2015 draw_activity_graphs(a->g_nr - 1, SVG_LINE_GRAPH,
2016 title1, g_title1, item_name, group1,
2017 spmin + pos, spmax + pos, out + pos, outsize + pos,
2019 draw_activity_graphs(1, SVG_BAR_GRAPH,
2020 title2, g_title2, item_name, group2,
2021 spmin + pos + 7, spmax + pos + 7, out + pos + 7, outsize + pos + 7,
2025 /* Free remaining structures */
2026 free_graphs(out, outsize, spmin, spmax);
2031 ***************************************************************************
2032 * Display network interfaces statistics in SVG.
2035 * @a Activity structure with statistics.
2036 * @curr Index in array for current sample statistics.
2037 * @action Action expected from current function.
2038 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2039 * flag indicating that a restart record has been previously
2040 * found (.@restart) and time used for the X axis origin
2042 * @itv Interval of time in jiffies (only with F_MAIN action).
2043 * @record_hdr Pointer on record header of current stats sample.
2044 ***************************************************************************
2046 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2047 unsigned long long itv, struct record_header *record_hdr)
2049 struct stats_net_dev *sndc, *sndp;
2050 int group1[] = {2, 2, 3};
2052 char *title1[] = {"Network statistics (1)", "Network statistics (2)",
2053 "Network statistics (3)"};
2054 char *title2[] = {"Network statistics (4)"};
2055 char *g_title1[] = {"rxpck/s", "txpck/s",
2057 "rxcmp/s", "txcmp/s", "rxmcst/s"};
2058 char *g_title2[] = {"%ifutil"};
2059 static double *spmin, *spmax;
2061 static int *outsize;
2063 double rxkb, txkb, ifutil;
2064 int i, j, k, pos, restart, *unregistered;
2066 if (action & F_BEGIN) {
2068 * Allocate arrays (#0..7) that will contain the graphs data
2069 * and the min/max values.
2070 * Also allocate one additional array (#8) for each interface:
2071 * out + 8 will contain the interface name,
2072 * outsize + 8 will contain a positive value (TRUE) if the interface
2073 * has either still not been registered, or has been unregistered.
2075 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2078 if (action & F_MAIN) {
2079 restart = svg_p->restart;
2081 * Mark previously registered interfaces as now
2082 * possibly unregistered for all graphs.
2084 for (k = 0; k < a->nr; k++) {
2085 unregistered = outsize + k * 9 + 8;
2086 if (*unregistered == FALSE) {
2087 *unregistered = MAYBE;
2091 /* For each network interfaces structure */
2092 for (i = 0; i < a->nr; i++) {
2093 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2094 if (!strcmp(sndc->interface, ""))
2095 /* Empty structure: Ignore it */
2098 /* Look for corresponding graph */
2099 for (k = 0; k < a->nr; k++) {
2100 item_name = *(out + k * 9 + 8);
2101 if (!strcmp(sndc->interface, item_name))
2106 /* Graph not found: Look for first free entry */
2107 for (k = 0; k < a->nr; k++) {
2108 item_name = *(out + k * 9 + 8);
2109 if (!strcmp(item_name, ""))
2113 /* No free graph entry: Graph for this item won't be drawn */
2118 unregistered = outsize + pos + 8;
2120 j = check_net_dev_reg(a, curr, !curr, i);
2121 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2124 * If current interface was marked as previously unregistered,
2125 * then set restart variable to TRUE so that the graph will be
2126 * discontinuous, and mark it as now registered.
2128 if (*unregistered == TRUE) {
2131 *unregistered = FALSE;
2133 if (!item_name[0]) {
2134 /* Save network interface name (if not already done) */
2135 strncpy(item_name, sndc->interface, CHUNKSIZE);
2136 item_name[CHUNKSIZE - 1] = '\0';
2139 /* Check for min/max values */
2140 save_extrema(7, 0, 0, (void *) sndc, (void *) sndp,
2141 itv, spmin + pos, spmax + pos);
2143 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2144 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2145 ifutil = compute_ifutil(sndc, rxkb, txkb);
2146 if (ifutil < *(spmin + pos + 7)) {
2147 *(spmin + pos + 7) = ifutil;
2149 if (ifutil > *(spmax + pos + 7)) {
2150 *(spmax + pos + 7) = ifutil;
2154 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2155 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2156 out + pos, outsize + pos, restart);
2159 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2160 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2161 out + pos + 1, outsize + pos + 1, restart);
2164 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2166 out + pos + 2, outsize + pos + 2, restart);
2169 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2171 out + pos + 3, outsize + pos + 3, restart);
2174 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2175 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2176 out + pos + 4, outsize + pos + 4, restart);
2179 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2180 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2181 out + pos + 5, outsize + pos + 5, restart);
2184 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2185 S_VALUE(sndp->multicast, sndc->multicast, itv),
2186 out + pos + 6, outsize + pos + 6, restart);
2189 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2191 out + pos + 7, outsize + pos + 7, svg_p->dt);
2194 /* Mark interfaces not seen here as now unregistered */
2195 for (k = 0; k < a->nr; k++) {
2196 unregistered = outsize + k * 9 + 8;
2197 if (*unregistered != FALSE) {
2198 *unregistered = TRUE;
2203 if (action & F_END) {
2204 for (i = 0; i < a->nr; i++) {
2206 * Check if there is something to display.
2207 * Don't test sndc->interface because maybe the network
2208 * interface has been registered later.
2214 /* Recalculate min and max values in kB, not in B */
2215 *(spmin + pos + 2) /= 1024;
2216 *(spmax + pos + 2) /= 1024;
2217 *(spmin + pos + 3) /= 1024;
2218 *(spmax + pos + 3) /= 1024;
2220 item_name = *(out + pos + 8);
2221 draw_activity_graphs(a->g_nr - 1, SVG_LINE_GRAPH,
2222 title1, g_title1, item_name, group1,
2223 spmin + pos, spmax + pos, out + pos, outsize + pos,
2225 draw_activity_graphs(1, SVG_BAR_GRAPH,
2226 title2, g_title2, item_name, group2,
2227 spmin + pos + 7, spmax + pos + 7, out + pos + 7, outsize + pos + 7,
2231 /* Free remaining structures */
2232 free_graphs(out, outsize, spmin, spmax);
2237 ***************************************************************************
2238 * Display network interface errors statistics in SVG.
2241 * @a Activity structure with statistics.
2242 * @curr Index in array for current sample statistics.
2243 * @action Action expected from current function.
2244 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2245 * flag indicating that a restart record has been previously
2246 * found (.@restart) and time used for the X axis origin
2248 * @itv Interval of time in jiffies (only with F_MAIN action).
2249 * @record_hdr Pointer on record header of current stats sample.
2250 ***************************************************************************
2252 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2253 unsigned long long itv, struct record_header *record_hdr)
2255 struct stats_net_edev *snedc, *snedp;
2256 int group[] = {2, 2, 2, 3};
2257 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2258 "Network statistics (3)", "Network statistics (4)"};
2259 char *g_title[] = {"rxerr/s", "txerr/s",
2260 "rxdrop/s", "txdrop/s",
2261 "rxfifo/s", "txfifo/s",
2262 "rxfram/s", "txcarr/s", "coll/s"};
2263 static double *spmin, *spmax;
2265 static int *outsize;
2267 double tmpmin, tmpmax;
2268 int i, j, k, pos, restart, *unregistered;
2270 if (action & F_BEGIN) {
2272 * Allocate arrays (#0..8) that will contain the graphs data
2273 * and the min/max values.
2274 * Also allocate one additional array (#9) for each interface:
2275 * out + 9 will contain the interface name,
2276 * outsize + 9 will contain a positive value (TRUE) if the interface
2277 * has either still not been registered, or has been unregistered.
2279 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
2282 if (action & F_MAIN) {
2283 restart = svg_p->restart;
2285 * Mark previously registered interfaces as now
2286 * possibly unregistered for all graphs.
2288 for (k = 0; k < a->nr; k++) {
2289 unregistered = outsize + k * 10 + 9;
2290 if (*unregistered == FALSE) {
2291 *unregistered = MAYBE;
2295 /* For each network interfaces structure */
2296 for (i = 0; i < a->nr; i++) {
2297 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2298 if (!strcmp(snedc->interface, ""))
2299 /* Empty structure: Ignore it */
2302 /* Look for corresponding graph */
2303 for (k = 0; k < a->nr; k++) {
2304 item_name = *(out + k * 10 + 9);
2305 if (!strcmp(snedc->interface, item_name))
2310 /* Graph not found: Look for first free entry */
2311 for (k = 0; k < a->nr; k++) {
2312 item_name = *(out + k * 10 + 9);
2313 if (!strcmp(item_name, ""))
2317 /* No free graph entry: Graph for this item won't be drawn */
2322 unregistered = outsize + pos + 9;
2324 j = check_net_edev_reg(a, curr, !curr, i);
2325 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2328 * If current interface was marked as previously unregistered,
2329 * then set restart variable to TRUE so that the graph will be
2330 * discontinuous, and mark it as now registered.
2332 if (*unregistered == TRUE) {
2335 *unregistered = FALSE;
2337 if (!item_name[0]) {
2338 /* Save network interface name (if not already done) */
2339 strncpy(item_name, snedc->interface, CHUNKSIZE);
2340 item_name[CHUNKSIZE - 1] = '\0';
2343 /* Check for min/max values */
2344 save_extrema(9, 0, 0, (void *) snedc, (void *) snedp,
2345 itv, spmin + pos, spmax + pos);
2348 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2349 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2350 out + pos, outsize + pos, restart);
2353 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2354 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2355 out + pos + 1, outsize + pos + 1, restart);
2358 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2359 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2360 out + pos + 2, outsize + pos + 2, restart);
2363 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2364 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2365 out + pos + 3, outsize + pos + 3, restart);
2368 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2369 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2370 out + pos + 4, outsize + pos + 4, restart);
2373 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2374 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2375 out + pos + 5, outsize + pos + 5, restart);
2378 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2379 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2380 out + pos + 6, outsize + pos + 6, restart);
2383 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2384 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2385 out + pos + 7, outsize + pos + 7, restart);
2388 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2389 S_VALUE(snedp->collisions, snedc->collisions, itv),
2390 out + pos + 8, outsize + pos + 8, restart);
2393 /* Mark interfaces not seen here as now unregistered */
2394 for (k = 0; k < a->nr; k++) {
2395 unregistered = outsize + k * 10 + 9;
2396 if (*unregistered != FALSE) {
2397 *unregistered = TRUE;
2402 if (action & F_END) {
2403 for (i = 0; i < a->nr; i++) {
2405 * Check if there is something to display.
2406 * Don't test snedc->interface because maybe the network
2407 * interface has been registered later.
2414 * Move coll/s min and max values at the end of the list,
2415 * because coll/s graph will be drawn on the last view.
2417 tmpmin = *(spmin + pos);
2418 tmpmax = *(spmax + pos);
2419 for (k = 1; k < 9; k++) {
2420 *(spmin + pos + k - 1) = *(spmin + pos + k);
2421 *(spmax + pos + k - 1) = *(spmax + pos + k);
2423 *(spmin + pos + 8) = tmpmin;
2424 *(spmax + pos + 8) = tmpmax;
2426 item_name = *(out + pos + 9);
2427 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH,
2428 title, g_title, item_name, group,
2429 spmin + pos, spmax + pos, out + pos, outsize + pos,
2433 /* Free remaining structures */
2434 free_graphs(out, outsize, spmin, spmax);
2439 ***************************************************************************
2440 * Display NFS client statistics in SVG.
2443 * @a Activity structure with statistics.
2444 * @curr Index in array for current sample statistics.
2445 * @action Action expected from current function.
2446 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2447 * flag indicating that a restart record has been previously
2448 * found (.@restart) and time used for the X axis origin
2450 * @itv Interval of time in jiffies (only with F_MAIN action).
2451 * @record_hdr Pointer on record header of current stats sample.
2452 ***************************************************************************
2454 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2455 unsigned long long itv, struct record_header *record_hdr)
2457 struct stats_net_nfs
2458 *snnc = (struct stats_net_nfs *) a->buf[curr],
2459 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2460 int group[] = {2, 2, 2};
2461 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)", "NFS client statistics (3)"};
2462 char *g_title[] = {"call/s", "retrans/s",
2463 "read/s", "write/s",
2464 "access/s", "getatt/s"};
2465 static double *spmin, *spmax;
2467 static int *outsize;
2469 if (action & F_BEGIN) {
2471 * Allocate arrays that will contain the graphs data
2472 * and the min/max values.
2474 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2477 if (action & F_MAIN) {
2478 /* Check for min/max values */
2479 save_extrema(0, 0, 6, (void *) a->buf[curr], (void *) a->buf[!curr],
2483 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2484 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2485 out, outsize, svg_p->restart);
2487 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2488 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2489 out + 1, outsize + 1, svg_p->restart);
2491 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2492 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2493 out + 2, outsize + 2, svg_p->restart);
2495 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2496 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2497 out + 3, outsize + 3, svg_p->restart);
2499 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2500 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2501 out + 4, outsize + 4, svg_p->restart);
2503 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2504 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2505 out + 5, outsize + 5, svg_p->restart);
2508 if (action & F_END) {
2509 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2510 spmin, spmax, out, outsize, svg_p, record_hdr);
2512 /* Free remaining structures */
2513 free_graphs(out, outsize, spmin, spmax);
2518 ***************************************************************************
2519 * Display NFS server statistics in SVG.
2522 * @a Activity structure with statistics.
2523 * @curr Index in array for current sample statistics.
2524 * @action Action expected from current function.
2525 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2526 * flag indicating that a restart record has been previously
2527 * found (.@restart) and time used for the X axis origin
2529 * @itv Interval of time in jiffies (only with F_MAIN action).
2530 * @record_hdr Pointer on record header of current stats sample.
2531 ***************************************************************************
2533 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2534 unsigned long long itv, struct record_header *record_hdr)
2536 struct stats_net_nfsd
2537 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2538 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2539 int group[] = {2, 3, 2, 2, 2};
2540 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)", "NFS server statistics (3)",
2541 "NFS server statistics (4)", "NFS server statistics (5)"};
2542 char *g_title[] = {"scall/s", "badcall/s",
2543 "packet/s", "udp/s", "tcp/s",
2545 "sread/s", "swrite/s",
2546 "saccess/s", "sgetatt/s"};
2547 static double *spmin, *spmax;
2549 static int *outsize;
2551 if (action & F_BEGIN) {
2553 * Allocate arrays that will contain the graphs data
2554 * and the min/max values.
2556 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2559 if (action & F_MAIN) {
2560 /* Check for min/max values */
2561 save_extrema(0, 0, 11, (void *) a->buf[curr], (void *) a->buf[!curr],
2565 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2566 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2567 out, outsize, svg_p->restart);
2569 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2570 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2571 out + 1, outsize + 1, svg_p->restart);
2573 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2574 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2575 out + 2, outsize + 2, svg_p->restart);
2577 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2578 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2579 out + 3, outsize + 3, svg_p->restart);
2581 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2582 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2583 out + 4, outsize + 4, svg_p->restart);
2585 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2586 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2587 out + 5, outsize + 5, svg_p->restart);
2589 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2590 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2591 out + 6, outsize + 6, svg_p->restart);
2593 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2594 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2595 out + 7, outsize + 7, svg_p->restart);
2597 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2598 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2599 out + 8, outsize + 8, svg_p->restart);
2601 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2602 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2603 out + 9, outsize + 9, svg_p->restart);
2605 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2606 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2607 out + 10, outsize + 10, svg_p->restart);
2610 if (action & F_END) {
2611 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2612 spmin, spmax, out, outsize, svg_p, record_hdr);
2614 /* Free remaining structures */
2615 free_graphs(out, outsize, spmin, spmax);
2620 ***************************************************************************
2621 * Display network socket statistics in SVG.
2624 * @a Activity structure with statistics.
2625 * @curr Index in array for current sample statistics.
2626 * @action Action expected from current function.
2627 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2628 * flag indicating that a restart record has been previously
2629 * found (.@restart) and time used for the X axis origin
2631 * @itv Interval of time in jiffies (only with F_MAIN action).
2632 * @record_hdr Pointer on record header of current stats sample.
2633 ***************************************************************************
2635 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2636 unsigned long long itv, struct record_header *record_hdr)
2638 struct stats_net_sock
2639 *snsc = (struct stats_net_sock *) a->buf[curr];
2640 int group[] = {1, 5};
2641 char *title[] = {"Network sockets (1)", "Network sockets (2)"};
2642 char *g_title[] = {"~totsck",
2643 "~tcpsck", "~tcp-tw", "~udpsck", "~rawsck", "~ip-frag"};
2644 static double *spmin, *spmax;
2646 static int *outsize;
2648 if (action & F_BEGIN) {
2650 * Allocate arrays that will contain the graphs data
2651 * and the min/max values.
2653 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2656 if (action & F_MAIN) {
2657 /* Check for min/max values */
2658 save_extrema(0, 0, 6, (void *) a->buf[curr], NULL,
2661 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2662 (unsigned long) snsc->sock_inuse,
2663 out, outsize, svg_p->restart);
2665 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2666 (unsigned long) snsc->tcp_inuse,
2667 out + 1, outsize + 1, svg_p->restart);
2669 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2670 (unsigned long) snsc->tcp_tw,
2671 out + 2, outsize + 2, svg_p->restart);
2673 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2674 (unsigned long) snsc->udp_inuse,
2675 out + 3, outsize + 3, svg_p->restart);
2677 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2678 (unsigned long) snsc->raw_inuse,
2679 out + 4, outsize + 4, svg_p->restart);
2681 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2682 (unsigned long) snsc->frag_inuse,
2683 out + 5, outsize + 5, svg_p->restart);
2686 if (action & F_END) {
2687 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2688 spmin, spmax, out, outsize, svg_p, record_hdr);
2690 /* Free remaining structures */
2691 free_graphs(out, outsize, spmin, spmax);
2696 ***************************************************************************
2697 * Display IPv4 network statistics in SVG.
2700 * @a Activity structure with statistics.
2701 * @curr Index in array for current sample statistics.
2702 * @action Action expected from current function.
2703 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2704 * flag indicating that a restart record has been previously
2705 * found (.@restart) and time used for the X axis origin
2707 * @itv Interval of time in jiffies (only with F_MAIN action).
2708 * @record_hdr Pointer on record header of current stats sample.
2709 ***************************************************************************
2711 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2712 unsigned long long itv, struct record_header *record_hdr)
2715 *snic = (struct stats_net_ip *) a->buf[curr],
2716 *snip = (struct stats_net_ip *) a->buf[!curr];
2717 int group[] = {4, 2, 2};
2718 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2719 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2720 "asmrq/s", "asmok/s",
2721 "fragok/s", "fragcrt/s"};
2722 static double *spmin, *spmax;
2724 static int *outsize;
2726 if (action & F_BEGIN) {
2728 * Allocate arrays that will contain the graphs data
2729 * and the min/max values.
2731 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2734 if (action & F_MAIN) {
2735 /* Check for min/max values */
2736 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2740 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2741 S_VALUE(snip->InReceives, snic->InReceives, itv),
2742 out, outsize, svg_p->restart);
2744 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2745 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2746 out + 1, outsize + 1, svg_p->restart);
2748 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2749 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2750 out + 2, outsize + 2, svg_p->restart);
2752 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2753 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2754 out + 3, outsize + 3, svg_p->restart);
2756 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2757 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2758 out + 4, outsize + 4, svg_p->restart);
2760 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2761 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2762 out + 5, outsize + 5, svg_p->restart);
2764 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2765 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2766 out + 6, outsize + 6, svg_p->restart);
2768 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2769 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2770 out + 7, outsize + 7, svg_p->restart);
2773 if (action & F_END) {
2774 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2775 spmin, spmax, out, outsize, svg_p, record_hdr);
2777 /* Free remaining structures */
2778 free_graphs(out, outsize, spmin, spmax);
2783 ***************************************************************************
2784 * Display IPv4 network errors statistics in SVG.
2787 * @a Activity structure with statistics.
2788 * @curr Index in array for current sample statistics.
2789 * @action Action expected from current function.
2790 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2791 * flag indicating that a restart record has been previously
2792 * found (.@restart) and time used for the X axis origin
2794 * @itv Interval of time in jiffies (only with F_MAIN action).
2795 * @record_hdr Pointer on record header of current stats sample.
2796 ***************************************************************************
2798 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2799 unsigned long long itv, struct record_header *record_hdr)
2801 struct stats_net_eip
2802 *sneic = (struct stats_net_eip *) a->buf[curr],
2803 *sneip = (struct stats_net_eip *) a->buf[!curr];
2804 int group[] = {3, 2, 3};
2805 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
2806 "IPv4 network errors statistics (3)"};
2807 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
2808 "idisc/s", "odisc/s",
2809 "onort/s", "asmf/s", "fragf/s"};
2810 static double *spmin, *spmax;
2812 static int *outsize;
2814 if (action & F_BEGIN) {
2816 * Allocate arrays that will contain the graphs data
2817 * and the min/max values.
2819 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2822 if (action & F_MAIN) {
2823 /* Check for min/max values */
2824 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2828 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2829 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
2830 out, outsize, svg_p->restart);
2832 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2833 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
2834 out + 1, outsize + 1, svg_p->restart);
2836 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2837 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
2838 out + 2, outsize + 2, svg_p->restart);
2840 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2841 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
2842 out + 3, outsize + 3, svg_p->restart);
2844 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2845 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
2846 out + 4, outsize + 4, svg_p->restart);
2848 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2849 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
2850 out + 5, outsize + 5, svg_p->restart);
2852 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2853 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
2854 out + 6, outsize + 6, svg_p->restart);
2856 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2857 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
2858 out + 7, outsize + 7, svg_p->restart);
2861 if (action & F_END) {
2862 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2863 spmin, spmax, out, outsize, svg_p, record_hdr);
2865 /* Free remaining structures */
2866 free_graphs(out, outsize, spmin, spmax);
2871 ***************************************************************************
2872 * Display ICMPv4 network statistics in SVG.
2875 * @a Activity structure with statistics.
2876 * @curr Index in array for current sample statistics.
2877 * @action Action expected from current function.
2878 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2879 * flag indicating that a restart record has been previously
2880 * found (.@restart) and time used for the X axis origin
2882 * @itv Interval of time in jiffies (only with F_MAIN action).
2883 * @record_hdr Pointer on record header of current stats sample.
2884 ***************************************************************************
2886 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2887 unsigned long long itv, struct record_header *record_hdr)
2889 struct stats_net_icmp
2890 *snic = (struct stats_net_icmp *) a->buf[curr],
2891 *snip = (struct stats_net_icmp *) a->buf[!curr];
2892 int group[] = {2, 4, 4, 4};
2893 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
2894 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
2895 char *g_title[] = {"imsg/s", "omsg/s",
2896 "iech/s", "iechr/s", "oech/s", "oechr/s",
2897 "itm/s", "itmr/s", "otm/s", "otmr/s",
2898 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
2899 static double *spmin, *spmax;
2901 static int *outsize;
2903 if (action & F_BEGIN) {
2905 * Allocate arrays that will contain the graphs data
2906 * and the min/max values.
2908 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
2911 if (action & F_MAIN) {
2912 /* Check for min/max values */
2913 save_extrema(0, 14, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2917 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2918 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
2919 out, outsize, svg_p->restart);
2921 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2922 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
2923 out + 1, outsize + 1, svg_p->restart);
2925 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2926 S_VALUE(snip->InEchos, snic->InEchos, itv),
2927 out + 2, outsize + 2, svg_p->restart);
2929 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2930 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
2931 out + 3, outsize + 3, svg_p->restart);
2933 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2934 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
2935 out + 4, outsize + 4, svg_p->restart);
2937 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2938 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
2939 out + 5, outsize + 5, svg_p->restart);
2941 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2942 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
2943 out + 6, outsize + 6, svg_p->restart);
2945 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2946 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
2947 out + 7, outsize + 7, svg_p->restart);
2949 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2950 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
2951 out + 8, outsize + 8, svg_p->restart);
2953 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2954 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
2955 out + 9, outsize + 9, svg_p->restart);
2957 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2958 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
2959 out + 10, outsize + 10, svg_p->restart);
2961 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2962 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
2963 out + 11, outsize + 11, svg_p->restart);
2965 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2966 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
2967 out + 12, outsize + 12, svg_p->restart);
2969 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2970 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
2971 out + 13, outsize + 13, svg_p->restart);
2974 if (action & F_END) {
2975 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
2976 spmin, spmax, out, outsize, svg_p, record_hdr);
2978 /* Free remaining structures */
2979 free_graphs(out, outsize, spmin, spmax);
2984 ***************************************************************************
2985 * Display ICMPv4 network errors statistics in SVG.
2988 * @a Activity structure with statistics.
2989 * @curr Index in array for current sample statistics.
2990 * @action Action expected from current function.
2991 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2992 * flag indicating that a restart record has been previously
2993 * found (.@restart) and time used for the X axis origin
2995 * @itv Interval of time in jiffies (only with F_MAIN action).
2996 * @record_hdr Pointer on record header of current stats sample.
2997 ***************************************************************************
2999 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3000 unsigned long long itv, struct record_header *record_hdr)
3002 struct stats_net_eicmp
3003 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3004 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3005 int group[] = {2, 2, 2, 2, 2, 2};
3006 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3007 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3008 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3009 char *g_title[] = {"ierr/s", "oerr/s",
3010 "idstunr/s", "odstunr/s",
3011 "itmex/s", "otmex/s",
3012 "iparmpb/s", "oparmpb/s",
3013 "isrcq/s", "osrcq/s",
3014 "iredir/s", "oredir/s"};
3015 static double *spmin, *spmax;
3017 static int *outsize;
3019 if (action & F_BEGIN) {
3021 * Allocate arrays that will contain the graphs data
3022 * and the min/max values.
3024 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3027 if (action & F_MAIN) {
3028 /* Check for min/max values */
3029 save_extrema(0, 12, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3033 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3034 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3035 out, outsize, svg_p->restart);
3037 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3038 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3039 out + 1, outsize + 1, svg_p->restart);
3041 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3042 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3043 out + 2, outsize + 2, svg_p->restart);
3045 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3046 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3047 out + 3, outsize + 3, svg_p->restart);
3049 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3050 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3051 out + 4, outsize + 4, svg_p->restart);
3053 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3054 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3055 out + 5, outsize + 5, svg_p->restart);
3057 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3058 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3059 out + 6, outsize + 6, svg_p->restart);
3061 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3062 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3063 out + 7, outsize + 7, svg_p->restart);
3065 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3066 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3067 out + 8, outsize + 8, svg_p->restart);
3069 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3070 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3071 out + 9, outsize + 9, svg_p->restart);
3073 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3074 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3075 out + 10, outsize + 10, svg_p->restart);
3077 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3078 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3079 out + 11, outsize + 11, svg_p->restart);
3082 if (action & F_END) {
3083 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3084 spmin, spmax, out, outsize, svg_p, record_hdr);
3086 /* Free remaining structures */
3087 free_graphs(out, outsize, spmin, spmax);
3092 ***************************************************************************
3093 * Display TCPv4 network statistics in SVG.
3096 * @a Activity structure with statistics.
3097 * @curr Index in array for current sample statistics.
3098 * @action Action expected from current function.
3099 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3100 * flag indicating that a restart record has been previously
3101 * found (.@restart) and time used for the X axis origin
3103 * @itv Interval of time in jiffies (only with F_MAIN action).
3104 * @record_hdr Pointer on record header of current stats sample.
3105 ***************************************************************************
3107 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3108 unsigned long long itv, struct record_header *record_hdr)
3110 struct stats_net_tcp
3111 *sntc = (struct stats_net_tcp *) a->buf[curr],
3112 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3113 int group[] = {2, 2};
3114 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3115 char *g_title[] = {"active/s", "passive/s",
3116 "iseg/s", "oseg/s"};
3117 static double *spmin, *spmax;
3119 static int *outsize;
3121 if (action & F_BEGIN) {
3123 * Allocate arrays that will contain the graphs data
3124 * and the min/max values.
3126 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3129 if (action & F_MAIN) {
3130 /* Check for min/max values */
3131 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3135 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3136 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3137 out, outsize, svg_p->restart);
3139 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3140 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3141 out + 1, outsize + 1, svg_p->restart);
3143 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3144 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3145 out + 2, outsize + 2, svg_p->restart);
3147 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3148 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3149 out + 3, outsize + 3, svg_p->restart);
3152 if (action & F_END) {
3153 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3154 spmin, spmax, out, outsize, svg_p, record_hdr);
3156 /* Free remaining structures */
3157 free_graphs(out, outsize, spmin, spmax);
3162 ***************************************************************************
3163 * Display TCPv4 network errors statistics in SVG.
3166 * @a Activity structure with statistics.
3167 * @curr Index in array for current sample statistics.
3168 * @action Action expected from current function.
3169 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3170 * flag indicating that a restart record has been previously
3171 * found (.@restart) and time used for the X axis origin
3173 * @itv Interval of time in jiffies (only with F_MAIN action).
3174 * @record_hdr Pointer on record header of current stats sample.
3175 ***************************************************************************
3177 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3178 unsigned long long itv, struct record_header *record_hdr)
3180 struct stats_net_etcp
3181 *snetc = (struct stats_net_etcp *) a->buf[curr],
3182 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3183 int group[] = {2, 3};
3184 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3185 char *g_title[] = {"atmptf/s", "estres/s",
3186 "retrans/s", "isegerr/s", "orsts/s"};
3187 static double *spmin, *spmax;
3189 static int *outsize;
3191 if (action & F_BEGIN) {
3193 * Allocate arrays that will contain the graphs data
3194 * and the min/max values.
3196 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3199 if (action & F_MAIN) {
3200 /* Check for min/max values */
3201 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3205 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3206 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3207 out, outsize, svg_p->restart);
3209 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3210 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3211 out + 1, outsize + 1, svg_p->restart);
3213 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3214 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3215 out + 2, outsize + 2, svg_p->restart);
3217 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3218 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3219 out + 3, outsize + 3, svg_p->restart);
3221 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3222 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3223 out + 4, outsize + 4, svg_p->restart);
3226 if (action & F_END) {
3227 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3228 spmin, spmax, out, outsize, svg_p, record_hdr);
3230 /* Free remaining structures */
3231 free_graphs(out, outsize, spmin, spmax);
3236 ***************************************************************************
3237 * Display UDPv4 network statistics in SVG.
3240 * @a Activity structure with statistics.
3241 * @curr Index in array for current sample statistics.
3242 * @action Action expected from current function.
3243 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3244 * flag indicating that a restart record has been previously
3245 * found (.@restart) and time used for the X axis origin
3247 * @itv Interval of time in jiffies (only with F_MAIN action).
3248 * @record_hdr Pointer on record header of current stats sample.
3249 ***************************************************************************
3251 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3252 unsigned long long itv, struct record_header *record_hdr)
3254 struct stats_net_udp
3255 *snuc = (struct stats_net_udp *) a->buf[curr],
3256 *snup = (struct stats_net_udp *) a->buf[!curr];
3257 int group[] = {2, 2};
3258 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3259 char *g_title[] = {"idgm/s", "odgm/s",
3260 "noport/s", "idgmerr/s"};
3261 static double *spmin, *spmax;
3263 static int *outsize;
3265 if (action & F_BEGIN) {
3267 * Allocate arrays that will contain the graphs data
3268 * and the min/max values.
3270 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3273 if (action & F_MAIN) {
3274 /* Check for min/max values */
3275 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3279 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3280 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3281 out, outsize, svg_p->restart);
3283 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3284 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3285 out + 1, outsize + 1, svg_p->restart);
3287 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3288 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3289 out + 2, outsize + 2, svg_p->restart);
3291 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3292 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3293 out + 3, outsize + 3, svg_p->restart);
3296 if (action & F_END) {
3297 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3298 spmin, spmax, out, outsize, svg_p, record_hdr);
3300 /* Free remaining structures */
3301 free_graphs(out, outsize, spmin, spmax);
3306 ***************************************************************************
3307 * Display IPV6 network socket statistics in SVG.
3310 * @a Activity structure with statistics.
3311 * @curr Index in array for current sample statistics.
3312 * @action Action expected from current function.
3313 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3314 * flag indicating that a restart record has been previously
3315 * found (.@restart) and time used for the X axis origin
3317 * @itv Interval of time in jiffies (only with F_MAIN action).
3318 * @record_hdr Pointer on record header of current stats sample.
3319 ***************************************************************************
3321 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3322 unsigned long long itv, struct record_header *record_hdr)
3324 struct stats_net_sock6
3325 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3327 char *title[] = {"IPv6 network sockets"};
3328 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3329 static double *spmin, *spmax;
3331 static int *outsize;
3333 if (action & F_BEGIN) {
3335 * Allocate arrays that will contain the graphs data
3336 * and the min/max values.
3338 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3341 if (action & F_MAIN) {
3342 /* Check for min/max values */
3343 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
3346 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3347 (unsigned long) snsc->tcp6_inuse,
3348 out, outsize, svg_p->restart);
3350 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3351 (unsigned long) snsc->udp6_inuse,
3352 out + 1, outsize + 1, svg_p->restart);
3354 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3355 (unsigned long) snsc->raw6_inuse,
3356 out + 2, outsize + 2, svg_p->restart);
3358 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3359 (unsigned long) snsc->frag6_inuse,
3360 out + 3, outsize + 3, svg_p->restart);
3363 if (action & F_END) {
3364 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3365 spmin, spmax, out, outsize, svg_p, record_hdr);
3367 /* Free remaining structures */
3368 free_graphs(out, outsize, spmin, spmax);
3373 ***************************************************************************
3374 * Display IPv6 network statistics in SVG.
3377 * @a Activity structure with statistics.
3378 * @curr Index in array for current sample statistics.
3379 * @action Action expected from current function.
3380 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3381 * flag indicating that a restart record has been previously
3382 * found (.@restart) and time used for the X axis origin
3384 * @itv Interval of time in jiffies (only with F_MAIN action).
3385 * @record_hdr Pointer on record header of current stats sample.
3386 ***************************************************************************
3388 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3389 unsigned long long itv, struct record_header *record_hdr)
3391 struct stats_net_ip6
3392 *snic = (struct stats_net_ip6 *) a->buf[curr],
3393 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3394 int group[] = {4, 2, 2, 2};
3395 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3396 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3397 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3398 "asmrq6/s", "asmok6/s",
3399 "imcpck6/s", "omcpck6/s",
3400 "fragok6/s", "fragcr6/s"};
3401 static double *spmin, *spmax;
3403 static int *outsize;
3405 if (action & F_BEGIN) {
3407 * Allocate arrays that will contain the graphs data
3408 * and the min/max values.
3410 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3413 if (action & F_MAIN) {
3414 /* Check for min/max values */
3415 save_extrema(10, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3419 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3420 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3421 out, outsize, svg_p->restart);
3423 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3424 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3425 out + 1, outsize + 1, svg_p->restart);
3427 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3428 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3429 out + 2, outsize + 2, svg_p->restart);
3431 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3432 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3433 out + 3, outsize + 3, svg_p->restart);
3435 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3436 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3437 out + 4, outsize + 4, svg_p->restart);
3439 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3440 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3441 out + 5, outsize + 5, svg_p->restart);
3443 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3444 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3445 out + 6, outsize + 6, svg_p->restart);
3447 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3448 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3449 out + 7, outsize + 7, svg_p->restart);
3451 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3452 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3453 out + 8, outsize + 8, svg_p->restart);
3455 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3456 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3457 out + 9, outsize + 9, svg_p->restart);
3460 if (action & F_END) {
3461 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3462 spmin, spmax, out, outsize, svg_p, record_hdr);
3464 /* Free remaining structures */
3465 free_graphs(out, outsize, spmin, spmax);
3470 ***************************************************************************
3471 * Display IPv6 network errors statistics in SVG.
3474 * @a Activity structure with statistics.
3475 * @curr Index in array for current sample statistics.
3476 * @action Action expected from current function.
3477 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3478 * flag indicating that a restart record has been previously
3479 * found (.@restart) and time used for the X axis origin
3481 * @itv Interval of time in jiffies (only with F_MAIN action).
3482 * @record_hdr Pointer on record header of current stats sample.
3483 ***************************************************************************
3485 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3486 unsigned long long itv, struct record_header *record_hdr)
3488 struct stats_net_eip6
3489 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3490 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3491 int group[] = {4, 2, 2, 3};
3492 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3493 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3494 "IPv6 network errors statistics (5)"};
3495 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3496 "idisc6/s", "odisc6/s",
3497 "inort6/s", "onort6/s",
3498 "asmf6/s", "fragf6/s", "itrpck6/s"};
3499 static double *spmin, *spmax;
3501 static int *outsize;
3503 if (action & F_BEGIN) {
3505 * Allocate arrays that will contain the graphs data
3506 * and the min/max values.
3508 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3511 if (action & F_MAIN) {
3512 /* Check for min/max values */
3513 save_extrema(11, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3517 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3518 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3519 out, outsize, svg_p->restart);
3521 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3522 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3523 out + 1, outsize + 1, svg_p->restart);
3525 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3526 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3527 out + 2, outsize + 2, svg_p->restart);
3529 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3530 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3531 out + 3, outsize + 3, svg_p->restart);
3533 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3534 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3535 out + 4, outsize + 4, svg_p->restart);
3537 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3538 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3539 out + 5, outsize + 5, svg_p->restart);
3541 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3542 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3543 out + 6, outsize + 6, svg_p->restart);
3545 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3546 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3547 out + 7, outsize + 7, svg_p->restart);
3549 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3550 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3551 out + 8, outsize + 8, svg_p->restart);
3553 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3554 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3555 out + 9, outsize + 9, svg_p->restart);
3557 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3558 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3559 out + 10, outsize + 10, svg_p->restart);
3562 if (action & F_END) {
3563 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3564 spmin, spmax, out, outsize, svg_p, record_hdr);
3566 /* Free remaining structures */
3567 free_graphs(out, outsize, spmin, spmax);
3572 ***************************************************************************
3573 * Display ICMPv6 network statistics in SVG.
3576 * @a Activity structure with statistics.
3577 * @curr Index in array for current sample statistics.
3578 * @action Action expected from current function.
3579 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3580 * flag indicating that a restart record has been previously
3581 * found (.@restart) and time used for the X axis origin
3583 * @itv Interval of time in jiffies (only with F_MAIN action).
3584 * @record_hdr Pointer on record header of current stats sample.
3585 ***************************************************************************
3587 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3588 unsigned long long itv, struct record_header *record_hdr)
3590 struct stats_net_icmp6
3591 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3592 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3593 int group[] = {2, 3, 5, 3, 4};
3594 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3595 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3596 "ICMPv6 network statistics (5)"};
3597 char *g_title[] = {"imsg6/s", "omsg6/s",
3598 "iech6/s", "iechr6/s", "oechr6/s",
3599 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3600 "irtsol6/s", "ortsol6/s", "irtad6/s",
3601 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3602 static double *spmin, *spmax;
3604 static int *outsize;
3606 if (action & F_BEGIN) {
3608 * Allocate arrays that will contain the graphs data
3609 * and the min/max values.
3611 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3614 if (action & F_MAIN) {
3615 /* Check for min/max values */
3616 save_extrema(0, 17, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3620 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3621 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3622 out, outsize, svg_p->restart);
3624 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3625 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3626 out + 1, outsize + 1, svg_p->restart);
3628 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3629 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3630 out + 2, outsize + 2, svg_p->restart);
3632 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3633 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3634 out + 3, outsize + 3, svg_p->restart);
3636 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3637 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3638 out + 4, outsize + 4, svg_p->restart);
3640 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3641 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3642 out + 5, outsize + 5, svg_p->restart);
3644 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3645 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3646 out + 6, outsize + 6, svg_p->restart);
3648 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3649 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3650 out + 7, outsize + 7, svg_p->restart);
3652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3653 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3654 out + 8, outsize + 8, svg_p->restart);
3656 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3657 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3658 out + 9, outsize + 9, svg_p->restart);
3660 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3661 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3662 out + 10, outsize + 10, svg_p->restart);
3664 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3665 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3666 out + 11, outsize + 11, svg_p->restart);
3668 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3669 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3670 out + 12, outsize + 12, svg_p->restart);
3672 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3673 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3674 out + 13, outsize + 13, svg_p->restart);
3676 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3677 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3678 out + 14, outsize + 14, svg_p->restart);
3680 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3681 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3682 out + 15, outsize + 15, svg_p->restart);
3684 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3685 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3686 out + 16, outsize + 16, svg_p->restart);
3689 if (action & F_END) {
3690 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3691 spmin, spmax, out, outsize, svg_p, record_hdr);
3693 /* Free remaining structures */
3694 free_graphs(out, outsize, spmin, spmax);
3699 ***************************************************************************
3700 * Display ICMPv6 network errors statistics in SVG.
3703 * @a Activity structure with statistics.
3704 * @curr Index in array for current sample statistics.
3705 * @action Action expected from current function.
3706 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3707 * flag indicating that a restart record has been previously
3708 * found (.@restart) and time used for the X axis origin
3710 * @itv Interval of time in jiffies (only with F_MAIN action).
3711 * @record_hdr Pointer on record header of current stats sample.
3712 ***************************************************************************
3714 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3715 unsigned long long itv, struct record_header *record_hdr)
3717 struct stats_net_eicmp6
3718 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3719 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3720 int group[] = {1, 2, 2, 2, 2, 2};
3721 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3722 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3723 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3724 char *g_title[] = {"ierr6/s",
3725 "idtunr6/s", "odtunr6/s",
3726 "itmex6/s", "otmex6/s",
3727 "iprmpb6/s", "oprmpb6/s",
3728 "iredir6/s", "oredir6/s",
3729 "ipck2b6/s", "opck2b6/s"};
3730 static double *spmin, *spmax;
3732 static int *outsize;
3734 if (action & F_BEGIN) {
3736 * Allocate arrays that will contain the graphs data
3737 * and the min/max values.
3739 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3742 if (action & F_MAIN) {
3743 /* Check for min/max values */
3744 save_extrema(0, 11, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3748 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3749 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
3750 out, outsize, svg_p->restart);
3752 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3753 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
3754 out + 1, outsize + 1, svg_p->restart);
3756 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3757 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
3758 out + 2, outsize + 2, svg_p->restart);
3760 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3761 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
3762 out + 3, outsize + 3, svg_p->restart);
3764 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3765 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
3766 out + 4, outsize + 4, svg_p->restart);
3768 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3769 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
3770 out + 5, outsize + 5, svg_p->restart);
3772 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3773 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
3774 out + 6, outsize + 6, svg_p->restart);
3776 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3777 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
3778 out + 7, outsize + 7, svg_p->restart);
3780 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3781 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
3782 out + 8, outsize + 8, svg_p->restart);
3784 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3785 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
3786 out + 9, outsize + 9, svg_p->restart);
3788 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3789 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
3790 out + 10, outsize + 10, svg_p->restart);
3793 if (action & F_END) {
3794 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3795 spmin, spmax, out, outsize, svg_p, record_hdr);
3797 /* Free remaining structures */
3798 free_graphs(out, outsize, spmin, spmax);
3803 ***************************************************************************
3804 * Display UDPv6 network statistics in SVG.
3807 * @a Activity structure with statistics.
3808 * @curr Index in array for current sample statistics.
3809 * @action Action expected from current function.
3810 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3811 * flag indicating that a restart record has been previously
3812 * found (.@restart) and time used for the X axis origin
3814 * @itv Interval of time in jiffies (only with F_MAIN action).
3815 * @record_hdr Pointer on record header of current stats sample.
3816 ***************************************************************************
3818 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3819 unsigned long long itv, struct record_header *record_hdr)
3821 struct stats_net_udp6
3822 *snuc = (struct stats_net_udp6 *) a->buf[curr],
3823 *snup = (struct stats_net_udp6 *) a->buf[!curr];
3824 int group[] = {2, 2};
3825 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
3826 char *g_title[] = {"idgm6/s", "odgm6/s",
3827 "noport6/s", "idgmer6/s"};
3828 static double *spmin, *spmax;
3830 static int *outsize;
3832 if (action & F_BEGIN) {
3834 * Allocate arrays that will contain the graphs data
3835 * and the min/max values.
3837 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3840 if (action & F_MAIN) {
3841 /* Check for min/max values */
3842 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3846 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3847 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
3848 out, outsize, svg_p->restart);
3850 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3851 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
3852 out + 1, outsize + 1, svg_p->restart);
3854 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3855 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
3856 out + 2, outsize + 2, svg_p->restart);
3858 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3859 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
3860 out + 3, outsize + 3, svg_p->restart);
3863 if (action & F_END) {
3864 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH, title, g_title, NULL, group,
3865 spmin, spmax, out, outsize, svg_p, record_hdr);
3867 /* Free remaining structures */
3868 free_graphs(out, outsize, spmin, spmax);
3873 ***************************************************************************
3874 * Display CPU frequency statistics in SVG.
3877 * @a Activity structure with statistics.
3878 * @curr Index in array for current sample statistics.
3879 * @action Action expected from current function.
3880 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3881 * flag indicating that a restart record has been previously
3882 * found (.@restart) and time used for the X axis origin
3884 * @itv Interval of time in jiffies (only with F_MAIN action).
3885 * @record_hdr Pointer on record header of current stats sample.
3886 ***************************************************************************
3888 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3889 unsigned long long g_itv, struct record_header *record_hdr)
3891 struct stats_pwr_cpufreq *spc, *spp;
3893 char *title[] = {"CPU frequency"};
3894 char *g_title[] = {"MHz"};
3895 static double *spmin, *spmax;
3897 static int *outsize;
3901 if (action & F_BEGIN) {
3903 * Allocate arrays that will contain the graphs data
3904 * and the min/max values.
3906 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
3909 if (action & F_MAIN) {
3911 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
3913 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
3914 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
3916 /* Should current CPU (including CPU "all") be displayed? */
3917 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
3922 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
3923 ((double) spp->cpufreq) / 100,
3924 ((double) spc->cpufreq) / 100,
3925 out + i, outsize + i, svg_p->restart, svg_p->dt,
3926 spmin + i, spmax + i);
3930 if (action & F_END) {
3931 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
3933 /* Should current CPU (including CPU "all") be displayed? */
3934 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
3939 /* This is CPU "all" */
3940 strcpy(item_name, "all");
3943 sprintf(item_name, "%d", i - 1);
3946 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH,
3947 title, g_title, item_name, group,
3948 spmin + i, spmax + i, out + i, outsize + i,
3952 /* Free remaining structures */
3953 free_graphs(out, outsize, spmin, spmax);
3958 ***************************************************************************
3959 * Display fan statistics in SVG.
3962 * @a Activity structure with statistics.
3963 * @curr Index in array for current sample statistics.
3964 * @action Action expected from current function.
3965 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3966 * flag indicating that a restart record has been previously
3967 * found (.@restart) and time used for the X axis origin
3969 * @itv Interval of time in jiffies (only with F_MAIN action).
3970 * @record_hdr Pointer on record header of current stats sample.
3971 ***************************************************************************
3973 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3974 unsigned long long g_itv, struct record_header *record_hdr)
3976 struct stats_pwr_fan *spc, *spp;
3978 char *title[] = {"Fan speed"};
3979 char *g_title[] = {"~rpm"};
3980 static double *spmin, *spmax;
3982 static int *outsize;
3983 char item_name[MAX_SENSORS_DEV_LEN + 8];
3986 if (action & F_BEGIN) {
3988 * Allocate arrays that will contain the graphs data
3989 * and the min/max values.
3991 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
3994 if (action & F_MAIN) {
3996 for (i = 0; i < a->nr; i++) {
3998 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
3999 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4002 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4005 out + i, outsize + i, svg_p->restart, svg_p->dt,
4006 spmin + i, spmax + i);
4010 if (action & F_END) {
4011 for (i = 0; i < a->nr; i++) {
4013 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4015 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4016 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4018 draw_activity_graphs(a->g_nr, SVG_LINE_GRAPH,
4019 title, g_title, item_name, group,
4020 spmin + i, spmax + i, out + i, outsize + i,
4024 /* Free remaining structures */
4025 free_graphs(out, outsize, spmin, spmax);
4030 ***************************************************************************
4031 * Display temperature statistics in SVG.
4034 * @a Activity structure with statistics.
4035 * @curr Index in array for current sample statistics.
4036 * @action Action expected from current function.
4037 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4038 * flag indicating that a restart record has been previously
4039 * found (.@restart) and time used for the X axis origin
4041 * @itv Interval of time in jiffies (only with F_MAIN action).
4042 * @record_hdr Pointer on record header of current stats sample.
4043 ***************************************************************************
4045 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4046 unsigned long long g_itv, struct record_header *record_hdr)
4048 struct stats_pwr_temp *spc;
4050 char *title1[] = {"Device temperature (1)"};
4051 char *title2[] = {"Device temperature (2)"};
4052 char *g1_title[] = {"~degC"};
4053 char *g2_title[] = {"%temp"};
4054 static double *spmin, *spmax;
4056 static int *outsize;
4057 char item_name[MAX_SENSORS_DEV_LEN + 8];
4061 if (action & F_BEGIN) {
4063 * Allocate arrays that will contain the graphs data
4064 * and the min/max values.
4066 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4069 if (action & F_MAIN) {
4070 /* For each temperature sensor */
4071 for (i = 0; i < a->nr; i++) {
4073 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4075 /* Look for min/max values */
4076 if (spc->temp < *(spmin + 2 * i)) {
4077 *(spmin + 2 * i) = spc->temp;
4079 if (spc->temp > *(spmax + 2 * i)) {
4080 *(spmax + 2 * i) = spc->temp;
4082 tval = (spc->temp_max - spc->temp_min) ?
4083 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4085 if (tval < *(spmin + 2 * i + 1)) {
4086 *(spmin + 2 * i + 1) = tval;
4088 if (tval > *(spmax + 2 * i + 1)) {
4089 *(spmax + 2 * i + 1) = tval;
4093 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4095 out + 2 * i, outsize + 2 * i, svg_p->restart);
4097 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4099 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4103 if (action & F_END) {
4104 for (i = 0; i < a->nr; i++) {
4106 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4108 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4109 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4111 draw_activity_graphs(1, SVG_LINE_GRAPH,
4112 title1, g1_title, item_name, group,
4113 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4115 draw_activity_graphs(1, SVG_BAR_GRAPH,
4116 title2, g2_title, item_name, group,
4117 spmin + 2 * i + 1, spmax + 2 * i + 1,
4118 out + 2 * i + 1, outsize + 2 * i + 1,
4122 /* Free remaining structures */
4123 free_graphs(out, outsize, spmin, spmax);
4128 ***************************************************************************
4129 * Display voltage inputs statistics in SVG.
4132 * @a Activity structure with statistics.
4133 * @curr Index in array for current sample statistics.
4134 * @action Action expected from current function.
4135 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4136 * flag indicating that a restart record has been previously
4137 * found (.@restart) and time used for the X axis origin
4139 * @itv Interval of time in jiffies (only with F_MAIN action).
4140 * @record_hdr Pointer on record header of current stats sample.
4141 ***************************************************************************
4143 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4144 unsigned long long g_itv, struct record_header *record_hdr)
4146 struct stats_pwr_in *spc;
4148 char *title1[] = {"Voltage inputs (1)"};
4149 char *title2[] = {"Voltage inputs (2)"};
4150 char *g1_title[] = {"inV"};
4151 char *g2_title[] = {"%in"};
4152 static double *spmin, *spmax;
4154 static int *outsize;
4155 char item_name[MAX_SENSORS_DEV_LEN + 8];
4159 if (action & F_BEGIN) {
4161 * Allocate arrays that will contain the graphs data
4162 * and the min/max values.
4164 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4167 if (action & F_MAIN) {
4168 /* For each temperature sensor */
4169 for (i = 0; i < a->nr; i++) {
4171 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4173 /* Look for min/max values */
4174 if (spc->in < *(spmin + 2 * i)) {
4175 *(spmin + 2 * i) = spc->in;
4177 if (spc->in > *(spmax + 2 * i)) {
4178 *(spmax + 2 * i) = spc->in;
4180 tval = (spc->in_max - spc->in_min) ?
4181 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4183 if (tval < *(spmin + 2 * i + 1)) {
4184 *(spmin + 2 * i + 1) = tval;
4186 if (tval > *(spmax + 2 * i + 1)) {
4187 *(spmax + 2 * i + 1) = tval;
4191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4193 out + 2 * i, outsize + 2 * i, svg_p->restart);
4195 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4197 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4201 if (action & F_END) {
4202 for (i = 0; i < a->nr; i++) {
4204 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4206 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4207 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4209 draw_activity_graphs(1, SVG_LINE_GRAPH,
4210 title1, g1_title, item_name, group,
4211 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4213 draw_activity_graphs(1, SVG_BAR_GRAPH,
4214 title2, g2_title, item_name, group,
4215 spmin + 2 * i + 1, spmax + 2 * i + 1,
4216 out + 2 * i + 1, outsize + 2 * i + 1,
4220 /* Free remaining structures */
4221 free_graphs(out, outsize, spmin, spmax);
4226 ***************************************************************************
4227 * Display huge pages statistics in SVG.
4230 * @a Activity structure with statistics.
4231 * @curr Index in array for current sample statistics.
4232 * @action Action expected from current function.
4233 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4234 * flag indicating that a restart record has been previously
4235 * found (.@restart) and time used for the X axis origin
4237 * @itv Interval of time in jiffies (only with F_MAIN action).
4238 * @record_hdr Pointer on record header of current stats sample.
4239 ***************************************************************************
4241 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4242 unsigned long long itv, struct record_header *record_hdr)
4245 *smc = (struct stats_huge *) a->buf[curr];
4248 char *title1[] = {"Huge pages utilization (1)"};
4249 char *title2[] = {"Huge pages utilization (2)"};
4250 char *g1_title[] = {"~kbhugfree", "~kbhugused"};
4251 char *g2_title[] = {"%hugused"};
4252 static double *spmin, *spmax;
4254 static int *outsize;
4257 if (action & F_BEGIN) {
4259 * Allocate arrays that will contain the graphs data
4260 * and the min/max values.
4262 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4265 if (action & F_MAIN) {
4266 /* Check for min/max values */
4267 save_extrema(0, 1, 0, (void *) a->buf[curr], NULL,
4270 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4271 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4273 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4274 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4276 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4277 if (tval < *(spmin + 2)) {
4278 *(spmin + 2) = tval;
4280 if (tval > *(spmax + 2)) {
4281 *(spmax + 2) = tval;
4285 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4286 (unsigned long) smc->frhkb,
4287 out, outsize, svg_p->restart);
4289 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4290 (unsigned long) smc->tlhkb - smc->frhkb,
4291 out + 1, outsize + 1, svg_p->restart);
4293 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4295 out + 2, outsize + 2, svg_p->dt);
4298 if (action & F_END) {
4299 draw_activity_graphs(1, SVG_LINE_GRAPH,
4300 title1, g1_title, NULL, group1,
4301 spmin, spmax, out, outsize, svg_p, record_hdr);
4302 draw_activity_graphs(1, SVG_BAR_GRAPH,
4303 title2, g2_title, NULL, group2,
4304 spmin + 2, spmax + 2, out + 2, outsize + 2,
4307 /* Free remaining structures */
4308 free_graphs(out, outsize, spmin, spmax);
4313 ***************************************************************************
4314 * Display filesystem statistics in SVG.
4317 * @a Activity structure with statistics.
4318 * @curr Index in array for current sample statistics.
4319 * @action Action expected from current function.
4320 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4321 * flag indicating that a restart record has been previously
4322 * found (.@restart) and time used for the X axis origin
4324 * @itv Interval of time in jiffies (only with F_MAIN action).
4325 * @record_hdr Pointer on record header of current stats sample.
4326 ***************************************************************************
4328 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4329 unsigned long long itv, struct record_header *record_hdr)
4331 struct stats_filesystem
4332 *sfc = (struct stats_filesystem *) a->buf[curr];
4333 int group1a[] = {2};
4334 int group1b[] = {2};
4335 int group2a[] = {2};
4336 int group2b[] = {1};
4337 char *title1a[] = {"Filesystem statistics (1)"};
4338 char *title1b[] = {"Filesystem statistics (2)"};
4339 char *title2a[] = {"Filesystem statistics (3)"};
4340 char *title2b[] = {"Filesystem statistics (4)"};
4341 char *g_title1a[] = {"~MBfsfree", "~MBfsused"};
4342 char *g_title1b[] = {"%ufsused", "%fsused"};
4343 char *g_title2a[] = {"Ifree/1000", "Iused/1000"};
4344 char *g_title2b[] = {"%Iused"};
4345 static double *spmin, *spmax;
4347 static int *outsize;
4352 if (action & F_BEGIN) {
4354 * Allocate arrays (#0..6) that will contain the graphs data
4355 * and the min/max values.
4356 * Also allocate two additional arrays (#7..8) for each filesystem:
4357 * out + 7 will contain the filesystem name,
4358 * out + 8 will contain the mount point.
4360 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
4363 if (action & F_MAIN) {
4364 /* For each filesystem structure */
4365 for (i = 0; i < a->nr; i++) {
4366 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4369 /* Size of filesystem is zero: We are at the end of the list */
4372 /* Look for corresponding graph */
4373 for (k = 0; k < a->nr; k++) {
4374 item_name = *(out + k * 9 + 7);
4375 if (!strcmp(sfc->fs_name, item_name))
4381 /* Graph not found: Look for first free entry */
4382 for (k = 0; k < a->nr; k++) {
4383 item_name = *(out + k * 9 + 7);
4384 if (!strcmp(item_name, ""))
4388 /* No free graph entry: Graph for this item won't be drawn */
4394 if (!item_name[0]) {
4395 /* Save filesystem name and mount point (if not already done) */
4396 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4397 item_name[CHUNKSIZE - 1] = '\0';
4398 item_name = *(out + pos + 8);
4399 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4400 item_name[CHUNKSIZE - 1] = '\0';
4403 /* Check for min/max values */
4405 /* Compute fsfree min/max values */
4406 tval = (double) sfc->f_bfree;
4407 if (tval > *(spmax + pos)) {
4408 *(spmax + pos) = tval;
4410 if (tval < *(spmin + pos)) {
4411 *(spmin + pos) = tval;
4413 /* Compute fsused min/max values */
4414 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4415 if (tval > *(spmax + pos + 1)) {
4416 *(spmax + pos + 1) = tval;
4418 if (tval < *(spmin + pos + 1)) {
4419 *(spmin + pos + 1) = tval;
4421 /* Compute %ufsused min/max values */
4422 tval = sfc->f_blocks ?
4423 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4424 if (tval > *(spmax + pos + 2)) {
4425 *(spmax + pos + 2) = tval;
4427 if (tval < *(spmin + pos + 2)) {
4428 *(spmin + pos + 2) = tval;
4430 /* Compute %fsused min/max values */
4431 tval = sfc->f_blocks ?
4432 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4433 if (tval > *(spmax + pos + 3)) {
4434 *(spmax + pos + 3) = tval;
4436 if (tval < *(spmin + pos + 3)) {
4437 *(spmin + pos + 3) = tval;
4439 /* Compute Ifree min/max values */
4440 tval = (double) sfc->f_ffree;
4441 if (tval > *(spmax + pos + 4)) {
4442 *(spmax + pos + 4) = tval;
4444 if (tval < *(spmin + pos + 4)) {
4445 *(spmin + pos + 4) = tval;
4447 /* Compute Iused min/max values */
4448 tval = (double) (sfc->f_files - sfc->f_ffree);
4449 if (tval > *(spmax + pos + 5)) {
4450 *(spmax + pos + 5) = tval;
4452 if (tval < *(spmin + pos + 5)) {
4453 *(spmin + pos + 5) = tval;
4455 /* Compute %Iused min/max values */
4456 tval = sfc->f_files ?
4457 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4458 if (tval > *(spmax + pos + 6)) {
4459 *(spmax + pos + 6) = tval;
4461 if (tval < *(spmin + pos + 6)) {
4462 *(spmin + pos + 6) = tval;
4466 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4467 (double) sfc->f_bfree / 1024 / 1024,
4468 out + pos, outsize + pos, svg_p->restart);
4470 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4471 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4472 out + pos + 1, outsize + pos + 1, svg_p->restart);
4474 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4477 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4478 out + pos + 2, outsize + pos + 2, svg_p->dt);
4480 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4483 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4484 out + pos + 3, outsize + pos + 3, svg_p->dt);
4486 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4487 ((double) sfc->f_ffree) / 1000,
4488 out + pos + 4, outsize + pos + 4, svg_p->restart);
4490 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4491 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4492 out + pos + 5, outsize + pos + 5, svg_p->restart);
4494 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4497 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4498 out + pos + 6, outsize + pos + 6, svg_p->dt);
4502 if (action & F_END) {
4504 for (i = 0; i < a->nr; i++) {
4506 /* Check if there is something to display */
4511 /* Conversion B -> MB */
4512 for (k = 0; k < 2; k++) {
4513 *(spmin + pos + k) /= (1024 * 1024);
4514 *(spmax + pos + k) /= (1024 * 1024);
4515 *(spmin + pos + 4 + k) /= 1000;
4516 *(spmax + pos + 4 + k) /= 1000;
4519 if (DISPLAY_MOUNT(a->opt_flags)) {
4520 item_name = *(out + pos + 8);
4523 item_name = *(out + pos + 7);
4526 draw_activity_graphs(1, SVG_LINE_GRAPH, title1a, g_title1a, item_name, group1a,
4527 spmin + pos, spmax + pos, out + pos, outsize + pos,
4529 draw_activity_graphs(1, SVG_BAR_GRAPH, title1b, g_title1b, item_name, group1b,
4530 spmin + pos + 2, spmax + pos + 2, out + pos + 2, outsize + pos + 2,
4532 draw_activity_graphs(1, SVG_LINE_GRAPH, title2a, g_title2a, item_name, group2a,
4533 spmin + pos + 4, spmax + pos + 4, out + pos + 4, outsize + pos + 4,
4535 draw_activity_graphs(1, SVG_BAR_GRAPH, title2b, g_title2b, item_name, group2b,
4536 spmin + pos + 6, spmax + pos + 6, out + pos + 6, outsize + pos + 6,
4540 /* Free remaining structures */
4541 free_graphs(out, outsize, spmin, spmax);