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, 0x50040f, 0xffffbf, 0x193d55};
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 * Assume values cannot be negative.
56 * The structure containing the statistics sample is composed of @llu_nr
57 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
58 * followed by @u_nr unsigned int fields.
61 * @llu_nr Number of unsigned long long fields composing the structure.
62 * @lu_nr Number of unsigned long fields composing the structure.
63 * @u_nr Number of unsigned int fields composing the structure.
64 * @cs Pointer on current sample statistics structure.
65 * @ps Pointer on previous sample statistics structure (may be NULL).
66 * @itv Interval of time in jiffies.
67 * @spmin Array containing min values already found for this activity.
68 * @spmax Array containing max values already found for this activity.
69 * @g_fields Index in spmin/spmax arrays where extrema values for each
70 * activity metric will be saved. As a consequence spmin/spmax
71 * arrays mau contain values in a different order than that of
72 * the fields in the statistics structure.
75 * @spmin Array containg the possible new min values for current activity.
76 * @spmax Array containg the possible new max values for current activity.
77 ***************************************************************************
79 void save_extrema(int llu_nr, int lu_nr, int u_nr, void *cs, void *ps,
80 unsigned long long itv, double *spmin, double *spmax, int g_fields[])
82 unsigned long long *lluc, *llup;
83 unsigned long *luc, *lup;
84 unsigned int *uc, *up;
88 /* Compare unsigned long long fields */
89 lluc = (unsigned long long *) cs;
90 llup = (unsigned long long *) ps;
91 for (i = 0; i < llu_nr; i++, m++) {
93 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
97 * If no pointer on previous sample has been given
98 * then the value is not a per-second one.
100 val = (double) *lluc;
102 if (val < *(spmin + g_fields[m])) {
103 *(spmin + g_fields[m]) = val;
105 if (val > *(spmax + g_fields[m])) {
106 *(spmax + g_fields[m]) = val;
108 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
110 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
114 /* Compare unsigned long fields */
115 luc = (unsigned long *) lluc;
116 lup = (unsigned long *) llup;
117 for (i = 0; i < lu_nr; i++, m++) {
119 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
124 if (val < *(spmin + g_fields[m])) {
125 *(spmin + g_fields[m]) = val;
127 if (val > *(spmax + g_fields[m])) {
128 *(spmax + g_fields[m]) = val;
130 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
132 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
136 /* Compare unsigned int fields */
137 uc = (unsigned int *) luc;
138 up = (unsigned int *) lup;
139 for (i = 0; i < u_nr; i++, m++) {
141 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
146 if (val < *(spmin + g_fields[m])) {
147 *(spmin + g_fields[m]) = val;
149 if (val > *(spmax + g_fields[m])) {
150 *(spmax + g_fields[m]) = val;
152 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
154 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
160 ***************************************************************************
161 * Find the min and max values of all the graphs that will be drawn in the
162 * same view. The graphs have their own min and max values in
163 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
166 * @pos Position in array for the first graph extrema value.
167 * @n Number of graphs to scan.
168 * @spmin Array containing min values for graphs.
169 * @spmax Array containing max values for graphs.
172 * @gmin Global min value found.
173 * @gmax Global max value found.
174 ***************************************************************************
176 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
177 double *gmin, double *gmax)
181 *gmin = *(spmin + pos);
182 *gmax = *(spmax + pos);
184 for (i = 1; i < n; i++) {
185 if (*(spmin + pos + i) < *gmin) {
186 *gmin = *(spmin + pos + i);
188 if (*(spmax + pos + i) > *gmax) {
189 *gmax = *(spmax + pos + i);
195 ***************************************************************************
196 * Allocate arrays used to save graphs data, min and max values.
197 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
198 * array is returned. This is equivalent to "char data[][n]" where each
199 * element is of indeterminate size and will contain the graph data (eg.
200 * << path d="M12,14 L13,16..." ... >>.
201 * The size of element data[i] is given by outsize[i].
202 * Also allocate an array to save min values (equivalent to "double spmin[n]")
203 * and an array for max values (equivalent to "double spmax[n]").
206 * @n Number of graphs to draw for current activity.
209 * @outsize Array that will contain the sizes of each element in array
210 * of chars. Equivalent to "int outsize[n]" with
211 * outsize[n] = sizeof(data[][n]).
212 * @spmin Array that will contain min values for current activity.
213 * @spmax Array that will contain max values for current activity.
216 * Pointer on array of arrays of chars that will contain the graphs data.
218 * NB: @min and @max arrays contain values in the same order as the fields
219 * in the statistics structure.
220 ***************************************************************************
222 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
229 * Allocate an array of pointers. Each of these pointers will
230 * be an array of chars.
232 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
236 /* Allocate array that will contain the size of each array of chars */
237 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
241 /* Allocate array that will contain the min value of each graph */
242 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
246 /* Allocate array that will contain the max value of each graph */
247 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
251 /* Allocate arrays of chars that will contain graphs data */
252 for (i = 0; i < n; i++) {
253 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
258 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
259 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
260 *(*spmin + i) = DBL_MAX; /* Init min and max values */
261 *(*spmax + i) = -DBL_MAX;
268 ***************************************************************************
269 * Save SVG code for current graph.
272 * @data SVG code to append to current graph definition.
273 * @out Pointer on array of chars for current graph definition.
274 * @outsize Size of array of chars for current graph definition.
277 * @out Pointer on array of chars for current graph definition that
278 * has been updated with the addition of current sample data.
279 * @outsize Array that containing the (possibly new) sizes of each
280 * element in array of chars.
281 ***************************************************************************
283 void save_svg_data(char *data, char **out, int *outsize)
289 /* Determine space left in array */
290 len = *outsize - strlen(out_p) - 1;
291 if (strlen(data) >= len) {
293 * If current array of chars doesn't have enough space left
294 * then reallocate it with CHUNKSIZE more bytes.
296 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
298 *outsize += CHUNKSIZE;
301 strncat(out_p, data, len);
305 ***************************************************************************
306 * Update line graph definition by appending current X,Y coordinates.
309 * @timetag Timestamp in seconds since the epoch for current sample
310 * stats. Will be used as X coordinate.
311 * @value Value of current sample metric. Will be used as Y coordinate.
312 * @out Pointer on array of chars for current graph definition.
313 * @outsize Size of array of chars for current graph definition.
314 * @restart Set to TRUE if a RESTART record has been read since the last
318 * @out Pointer on array of chars for current graph definition that
319 * has been updated with the addition of current sample data.
320 * @outsize Array that containing the (possibly new) sizes of each
321 * element in array of chars.
322 ***************************************************************************
324 void lnappend(unsigned long timetag, double value, char **out, int *outsize, int restart)
328 /* Prepare additional graph definition data */
329 snprintf(data, 128, " %c%lu,%.2f", restart ? 'M' : 'L', timetag, value);
332 save_svg_data(data, out, outsize);
336 ***************************************************************************
337 * Update line graph definition by appending current X,Y coordinates. Use
338 * (unsigned long) integer values here.
341 * @timetag Timestamp in seconds since the epoch for current sample
342 * stats. Will be used as X coordinate.
343 * @value Value of current sample metric. Will be used as Y coordinate.
344 * @out Pointer on array of chars for current graph definition.
345 * @outsize Size of array of chars for current graph definition.
346 * @restart Set to TRUE if a RESTART record has been read since the last
350 * @out Pointer on array of chars for current graph definition that
351 * has been updated with the addition of current sample data.
352 * @outsize Array that containing the (possibly new) sizes of each
353 * element in array of chars.
354 ***************************************************************************
356 void lniappend(unsigned long timetag, unsigned long value, char **out, int *outsize,
361 /* Prepare additional graph definition data */
362 snprintf(data, 128, " %c%lu,%lu", restart ? 'M' : 'L', timetag, value);
365 save_svg_data(data, out, outsize);
369 ***************************************************************************
370 * Update bar graph definition by adding a new rectangle.
373 * @timetag Timestamp in seconds since the epoch for current sample
374 * stats. Will be used as X coordinate.
375 * @value Value of current sample metric. Will be used as rectangle
377 * @offset Offset for Y coordinate.
378 * @out Pointer on array of chars for current graph definition.
379 * @outsize Size of array of chars for current graph definition.
380 * @dt Interval of time in seconds between current and previous
384 * @out Pointer on array of chars for current graph definition that
385 * has been updated with the addition of current sample data.
386 * @outsize Array that containing the (possibly new) sizes of each
387 * element in array of chars.
388 ***************************************************************************
390 void brappend(unsigned long timetag, double offset, double value, char **out, int *outsize,
395 /* Prepare additional graph definition data */
396 if ((value == 0.0) || (dt == 0))
397 /* Dont draw a flat rectangle! */
400 snprintf(data, 128, "<rect x=\"%lu\" y=\"%.2f\" height=\"%.2f\" width=\"%lu\"/>",
401 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
404 save_svg_data(data, out, outsize);
409 ***************************************************************************
410 * Update CPU graph and min/max values for each metric.
413 * @timetag Timestamp in seconds since the epoch for current sample
414 * stats. Will be used as X coordinate.
415 * @offset Offset for Y coordinate.
416 * @value Value of current CPU metric. Will be used as rectangle
418 * @out Pointer on array of chars for current graph definition.
419 * @outsize Size of array of chars for current graph definition.
420 * @dt Interval of time in seconds between current and previous
422 * @spmin Min value already found for this CPU metric.
423 * @spmax Max value already found for this CPU metric.
426 * @offset New offset value, to use to draw next rectangle
427 * @out Pointer on array of chars for current graph definition that
428 * has been updated with the addition of current sample data.
429 * @outsize Array that containing the (possibly new) sizes of each
430 * element in array of chars.
431 ***************************************************************************
433 void cpuappend(unsigned long timetag, double *offset, double value, char **out, int *outsize,
434 unsigned long dt, double *spmin, double *spmax)
436 /* Save min and max values */
437 if (value < *spmin) {
440 if (value > *spmax) {
443 /* Prepare additional graph definition data */
444 brappend(timetag, *offset, value, out, outsize, dt);
450 ***************************************************************************
451 * Update rectangular graph and min/max values.
454 * @timetag Timestamp in seconds since the epoch for current sample
455 * stats. Will be used as X coordinate.
456 * @p_value Metric value for previous sample
457 * @value Metric value for current sample.
458 * @out Pointer on array of chars for current graph definition.
459 * @outsize Size of array of chars for current graph definition.
460 * @restart Set to TRUE if a RESTART record has been read since the last
462 * @dt Interval of time in seconds between current and previous
464 * @spmin Min value already found for this metric.
465 * @spmax Max value already found for this metric.
468 * @out Pointer on array of chars for current graph definition that
469 * has been updated with the addition of current sample data.
470 * @outsize Array that containing the (possibly new) sizes of each
471 * element in array of chars.
472 * @spmin Min value for this metric.
473 * @spmax Max value for this metric.
474 ***************************************************************************
476 void recappend(unsigned long timetag, double p_value, double value, char **out, int *outsize,
477 int restart, unsigned long dt, double *spmin, double *spmax)
479 char data[128], data1[128], data2[128];
481 /* Save min and max values */
482 if (value < *spmin) {
485 if (value > *spmax) {
488 /* Prepare additional graph definition data */
490 snprintf(data1, 128, " M%lu,%.2f", timetag - dt, p_value);
493 if (p_value != value) {
494 snprintf(data2, 128, " L%lu,%.2f", timetag, value);
497 snprintf(data, 128, "%s L%lu,%.2f%s", restart ? data1 : "", timetag, p_value,
498 p_value != value ? data2 : "");
501 save_svg_data(data, out, outsize);
505 ***************************************************************************
506 * Calculate 10 raised to the power of n.
509 * @n Power number to use.
512 * 10 raised to the power of n.
513 ***************************************************************************
515 unsigned int pwr10(int n)
520 for (i = 0; i < n; i++) {
528 ***************************************************************************
529 * Autoscale graphs of a given view.
532 * @asf_nr (Maximum) number of autoscale factors.
533 * @group Number of graphs in current view.
534 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
535 * @pos Position in array for the first graph in view.
536 * @gmax Global max value for all graphs in view.
537 * @spmax Array containing max values for graphs.
540 * @asfactor Autoscale factors (one for each graph).
541 ***************************************************************************
543 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
544 double gmax, double *spmax)
549 for (j = 0; j < asf_nr; j++) {
550 /* Init autoscale factors */
554 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
556 for (j = 0; (j < group) && (j < asf_nr); j++) {
557 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
560 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
561 if (strlen(val) > 0) {
562 asfactor[j] = pwr10(strlen(val) - 1);
569 ***************************************************************************
570 * Display background grid (horizontal lines) and corresponding graduations.
573 * @ypos Gap between two horizontal lines.
574 * @yfactor Scaling factor on Y axis.
575 * @lmax Max value for current view.
576 * @dp Number of decimal places for graduations.
577 ***************************************************************************
579 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
585 /* Display horizontal lines (except on X axis) */
587 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
588 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
589 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
593 * Display graduations.
594 * Use same rounded value for graduation numbers as for grid lines
595 * to make sure they are properly aligned.
597 sprintf(stmp, "%.2f", ypos * j);
598 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
599 "text-anchor: end\">%.*f.</text>\n",
600 (long) (atof(stmp) * yfactor), dp, ypos * j);
603 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
607 ***************************************************************************
608 * Display background grid (vertical lines) and corresponding graduations.
611 * @xpos Gap between two vertical lines.
612 * @xfactor Scaling factor on X axis.
613 * @v_gridnr Number of vertical lines to display.
614 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
615 ***************************************************************************
617 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
619 struct record_header stamp;
621 char cur_time[TIMESTAMP_LEN];
624 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
626 for (j = 0; (j <= v_gridnr) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
628 /* Display vertical lines */
629 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
630 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
631 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
632 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
633 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
635 * Display graduations.
636 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
637 * In this case, we should rather display the exact time instead of only the hour.
639 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
640 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
641 "text-anchor: start\">%2dH</text>\n",
642 (long) (xpos * j * xfactor) - 8, rectime.tm_hour);
645 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
646 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
647 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
649 stamp.ust_time += xpos;
652 if (!PRINT_LOCAL_TIME(flags)) {
653 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
654 "text-anchor: end\">UTC</text>\n");
659 ***************************************************************************
660 * Calculate the value on the Y axis between two horizontal lines that will
661 * make the graph background grid.
664 * @lmax Max value reached for this graph.
667 * @dp Number of decimal places for Y graduations.
670 * Value between two horizontal lines.
671 ***************************************************************************
673 double ygrid(double lmax, int *dp)
684 n = (long) (lmax / SVG_H_GRIDNR);
687 return (lmax / SVG_H_GRIDNR);
689 snprintf(val, 32, "%ld", n);
696 return ((double) (((long) (n / e)) * e));
700 ***************************************************************************
701 * Calculate the value on the X axis between two vertical lines that will
702 * make the graph background grid.
705 * @timestart First data timestamp (X coordinate of the first data point).
706 * @timeend Last data timestamp (X coordinate of the last data point).
707 * @v_gridnr Number of vertical lines to display. Its value is normally
708 * SVG_V_GRIDNR, except when option "oneday" is used, in which
709 * case it is set to 12.
712 * Value between two vertical lines.
713 ***************************************************************************
715 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
717 if ((timeend - timestart) <= v_gridnr)
720 return ((timeend - timestart) / v_gridnr);
724 ***************************************************************************
725 * Free global graphs structures.
728 * @out Pointer on array of chars for each graph definition.
729 * @outsize Size of array of chars for each graph definition.
730 * @spmin Array containing min values for graphs.
731 * @spmax Array containing max values for graphs.
732 ***************************************************************************
734 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
751 ***************************************************************************
752 * Skip current view where all graphs have only zero values. This function
753 * is called when option "skipempty" has been used, or when "No data" have
754 * been found for current view.
757 * @out Pointer on array of chars for each graph definition.
758 * @pos Position of current view in the array of graphs definitions.
759 * @group Number of graphs in current view.
762 * @pos Position of next view in the array of graphs definitions.
763 ***************************************************************************
765 void skip_current_view(char **out, int *pos, int group)
770 for (j = 0; j < group; j++) {
771 out_p = *(out + *pos + j);
773 /* Even if not displayed, current graph data have to be freed */
781 ***************************************************************************
782 * Display all graphs for current activity.
785 * @g_nr Number of views to display.
786 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
787 * @title Titles for each set of graphs.
788 * @g_title Titles for each graph.
789 * @item_name Item (network interface, etc.) name.
790 * @group Indicate how graphs are grouped together to make sets.
791 * @spmin Array containing min values for graphs.
792 * @spmax Array containing max values for graphs.
793 * @out Pointer on array of chars for each graph definition.
794 * @outsize Size of array of chars for each graph definition.
795 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
796 * time for the first sample of stats (.@ust_time_first), and
797 * times used as start and end values on the X axis
798 * (.@ust_time_ref and .@ust_time_end).
799 * @record_hdr Pointer on record header of current stats sample.
800 ***************************************************************************
802 void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
803 int group[], double *spmin, double *spmax, char **out, int *outsize,
804 struct svg_parm *svg_p, struct record_header *record_hdr)
807 int i, j, dp, pos = 0, views_nr = 0;
808 int v_gridnr, xv, yv;
809 unsigned int asfactor[16];
811 double lmax, xfactor, yfactor, ypos, gmin, gmax;
812 char val[32], cur_date[TIMESTAMP_LEN];
814 /* Translate to proper position for current activity */
815 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
817 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
819 /* For each view which is part of current activity */
820 for (i = 0; i < g_nr; i++) {
822 /* Get global min and max value for current view */
823 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
825 /* Don't display empty views if requested */
826 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
827 skip_current_view(out, &pos, group[i]);
830 /* Increment number of views actually displayed */
833 /* Compute top left position of view */
834 if (PACK_VIEWS(flags)) {
835 xv = (views_nr - 1) * SVG_T_XSIZE;
840 yv = (views_nr - 1) * SVG_T_YSIZE;
843 /* Graph background */
844 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
845 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
848 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
849 xv, 20 + yv, title[i]);
851 printf(" [%s]", item_name);
854 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
855 "(Min, Max values)</tspan>\n</text>\n",
856 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
859 * At least two samples are needed.
860 * And a min and max value should have been found.
862 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
863 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
865 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
866 xv, yv + SVG_M_YSIZE);
867 skip_current_view(out, &pos, group[i]);
872 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
873 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
874 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
875 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
877 /* Autoscaling graphs if needed */
878 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
881 for (j = 0; j < group[i]; j++) {
882 /* Set dp to TRUE (1) if current metric is based on integer values */
883 dp = (g_title[pos + j][0] == '~');
884 snprintf(val, 32, "x%u ", asfactor[j]);
885 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
886 "%s %s(%.*f, %.*f)</text>\n",
887 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
888 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
889 asfactor[j] == 1 ? "" : val,
890 !dp * 2, *(spmin + pos + j) * asfactor[j],
891 !dp * 2, *(spmax + pos + j) * asfactor[j]);
894 if (DISPLAY_INFO(flags)) {
895 /* Display additional info (hostname, date) */
896 printf("<text x=\"%d\" y=\"%d\" "
897 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
899 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
900 svg_p->file_hdr->sa_nodename);
902 /* Get report date */
903 set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
904 cur_date, sizeof(cur_date));
905 printf("<tspan x=\"%d\" y=\"%d\" "
906 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
907 "%s</tspan>\n</text>\n",
908 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
912 /* Translate to proper position for current graph within current activity */
913 printf("<g transform=\"translate(%d,%d)\">\n",
914 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
917 if (g_type[i] == SVG_LINE_GRAPH) {
918 /* For line graphs */
920 /* If all values are zero then set current max value to 1 */
926 /* Max value cannot be too small, else Y graduations will be meaningless */
927 if (lmax < SVG_H_GRIDNR * 0.01) {
928 lmax = SVG_H_GRIDNR * 0.01;
930 ypos = ygrid(lmax, &dp);
933 /* For bar graphs (used for %values) */
934 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
935 dp = 0; /* No decimals */
937 /* Max should be always 100% except for percentage values greater than 100% */
945 yfactor = (double) -SVG_G_YSIZE / lmax;
947 /* Display horizontal lines and graduations */
948 display_hgrid(ypos, yfactor, lmax, dp);
950 /* Set number of vertical lines to 12 when option "oneday" is used */
951 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
953 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
954 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
956 /* Display vertical lines and graduations */
957 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
959 /* Draw current graphs set */
960 for (j = 0; j < group[i]; j++) {
961 out_p = *(out + pos + j);
962 if (g_type[i] == SVG_LINE_GRAPH) {
964 printf("<path id=\"g%dp%d\" d=\"%s\" "
965 "style=\"vector-effect: non-scaling-stroke; "
966 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
967 "transform=\"scale(%f,%f)\"/>\n",
968 svg_p->graph_no, pos + j, out_p,
969 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
971 yfactor * asfactor[j]);
973 else if (*out_p) { /* Ignore flat bars */
975 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
976 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
977 printf("%s\n", out_p);
987 /* For next row of views */
988 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
992 ***************************************************************************
993 * Display CPU statistics in SVG.
996 * @a Activity structure with statistics.
997 * @curr Index in array for current sample statistics.
998 * @action Action expected from current function.
999 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1000 * flag indicating that a restart record has been previously
1001 * found (.@restart), and time used for the X axis origin
1003 * @itv Interval of time in jiffies (only with F_MAIN action).
1004 * @record_hdr Pointer on record header of current stats sample.
1005 ***************************************************************************
1007 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1008 unsigned long long g_itv, struct record_header *record_hdr)
1010 struct stats_cpu *scc, *scp;
1013 int g_type[] = {SVG_BAR_GRAPH};
1014 char *title[] = {"CPU load"};
1015 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1016 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1017 static double *spmin, *spmax;
1019 static int *outsize;
1022 int i, j, k, pos, cpu_offline;
1024 if (action & F_BEGIN) {
1026 * Allocate arrays that will contain the graphs data
1027 * and the min/max values.
1029 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
1032 if (action & F_MAIN) {
1034 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1036 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1037 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1039 /* Should current CPU (including CPU "all") be displayed? */
1040 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1047 if (i) { /* Don't test CPU "all" here */
1049 * If the CPU is offline then it is omited from /proc/stat:
1050 * All the fields couldn't have been read and the sum of them is zero.
1051 * (Remember that guest/guest_nice times are already included in
1054 if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys +
1055 scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal +
1056 scc->cpu_hardirq + scc->cpu_softirq) == 0) {
1058 * Set current struct fields (which have been set to zero)
1059 * to values from previous iteration. Hence their values won't
1060 * jump from zero when the CPU comes back online.
1069 * Recalculate interval for current proc.
1070 * If result is 0 then current CPU is a tickless one.
1072 g_itv = get_per_cpu_interval(scc, scp);
1073 cpu_offline = FALSE;
1076 if (!g_itv) { /* Current CPU is offline or tickless */
1078 val = (cpu_offline ? 0.0 /* Offline CPU: %idle = 0% */
1079 : 100.0); /* Tickless CPU: %idle = 100% */
1081 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1084 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1088 /* Check min/max values for %user, etc. */
1089 for (k = 0; k < j; k++) {
1090 if (0.0 < *(spmin + pos + k)) {
1091 *(spmin + pos + k) = 0.0;
1093 if (0.0 > *(spmax + pos + k)) {
1094 *(spmax + pos + k) = 0.0;
1099 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1101 out + pos + j, outsize + pos + j, svg_p->dt,
1102 spmin + pos + j, spmax + pos + j);
1107 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1109 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1110 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv),
1111 out + pos, outsize + pos, svg_p->dt,
1112 spmin + pos, spmax + pos);
1116 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1118 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1120 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1121 scc->cpu_user - scc->cpu_guest, g_itv),
1122 out + pos, outsize + pos, svg_p->dt,
1123 spmin + pos, spmax + pos);
1126 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1128 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1129 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv),
1130 out + pos + 1, outsize + pos + 1, svg_p->dt,
1131 spmin + pos + 1, spmax + pos + 1);
1135 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1137 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1139 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1140 scc->cpu_nice - scc->cpu_guest_nice, g_itv),
1141 out + pos + 1, outsize + pos + 1, svg_p->dt,
1142 spmin + pos + 1, spmax + pos + 1);
1145 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1147 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1149 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1150 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1152 out + pos + 2, outsize + pos + 2, svg_p->dt,
1153 spmin + pos + 2, spmax + pos + 2);
1157 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1158 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv),
1159 out + pos + 2, outsize + pos + 2, svg_p->dt,
1160 spmin + pos + 2, spmax + pos + 2);
1164 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1165 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
1166 out + pos + 3, outsize + pos + 3, svg_p->dt,
1167 spmin + pos + 3, spmax + pos + 3);
1169 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1170 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
1171 out + pos + 4, outsize + pos + 4, svg_p->dt,
1172 spmin + pos + 4, spmax + pos + 4);
1174 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1176 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1177 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv),
1178 out + pos + 5, outsize + pos + 5, svg_p->dt,
1179 spmin + pos + 5, spmax + pos + 5);
1181 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1182 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv),
1183 out + pos + 6, outsize + pos + 6, svg_p->dt,
1184 spmin + pos + 6, spmax + pos + 6);
1186 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1187 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv),
1188 out + pos + 7, outsize + pos + 7, svg_p->dt,
1189 spmin + pos + 7, spmax + pos + 7);
1191 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1192 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, g_itv),
1193 out + pos + 8, outsize + pos + 8, svg_p->dt,
1194 spmin + pos + 8, spmax + pos + 8);
1203 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1205 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1206 ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv)),
1207 out + pos + j, outsize + pos + j, svg_p->dt,
1208 spmin + pos + j, spmax + pos + j);
1212 if (action & F_END) {
1213 if (DISPLAY_IDLE(flags)) {
1214 /* Include additional %idle field */
1219 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1221 /* Should current CPU (including CPU "all") be displayed? */
1222 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1228 /* This is CPU "all" */
1229 strcpy(item_name, "all");
1232 sprintf(item_name, "%d", i - 1);
1235 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1236 draw_activity_graphs(a->g_nr, g_type,
1237 title, g_title1, item_name, group1,
1238 spmin + pos, spmax + pos, out + pos, outsize + pos,
1242 draw_activity_graphs(a->g_nr, g_type,
1243 title, g_title2, item_name, group2,
1244 spmin + pos, spmax + pos, out + pos, outsize + pos,
1249 /* Free remaining structures */
1250 free_graphs(out, outsize, spmin, spmax);
1255 ***************************************************************************
1256 * Display task creation and context switch statistics in SVG.
1259 * @a Activity structure with statistics.
1260 * @curr Index in array for current sample statistics.
1261 * @action Action expected from current function.
1262 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1263 * flag indicating that a restart record has been previously
1264 * found (.@restart) and time used for the X axis origin
1266 * @itv Interval of time in jiffies (only with F_MAIN action).
1267 * @record_hdr Pointer on record header of current stats sample.
1268 ***************************************************************************
1270 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1271 unsigned long long itv, struct record_header *record_hdr)
1274 *spc = (struct stats_pcsw *) a->buf[curr],
1275 *spp = (struct stats_pcsw *) a->buf[!curr];
1276 int group[] = {1, 1};
1277 int g_fields[] = {1, 0};
1278 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1279 char *title[] = {"Task creation", "Switching activity"};
1280 char *g_title[] = {"proc/s",
1282 static double *spmin, *spmax;
1284 static int *outsize;
1286 if (action & F_BEGIN) {
1288 * Allocate arrays that will contain the graphs data
1289 * and the min/max values.
1291 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1294 if (action & F_MAIN) {
1295 /* Check for min/max values */
1296 save_extrema(1, 1, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1297 itv, spmin, spmax, g_fields);
1299 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1300 S_VALUE(spp->processes, spc->processes, itv),
1301 out, outsize, svg_p->restart);
1303 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1304 S_VALUE(spp->context_switch, spc->context_switch, itv),
1305 out + 1, outsize + 1, svg_p->restart);
1308 if (action & F_END) {
1309 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1310 spmin, spmax, out, outsize, svg_p, record_hdr);
1312 /* Free remaining structures */
1313 free_graphs(out, outsize, spmin, spmax);
1318 ***************************************************************************
1319 * Display swap statistics in SVG.
1322 * @a Activity structure with statistics.
1323 * @curr Index in array for current sample statistics.
1324 * @action Action expected from current function.
1325 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1326 * flag indicating that a restart record has been previously
1327 * found (.@restart) and time used for the X axis origin
1329 * @itv Interval of time in jiffies (only with F_MAIN action).
1330 * @record_hdr Pointer on record header of current stats sample.
1331 ***************************************************************************
1333 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1334 unsigned long long itv, struct record_header *record_hdr)
1337 *ssc = (struct stats_swap *) a->buf[curr],
1338 *ssp = (struct stats_swap *) a->buf[!curr];
1340 int g_type[] = {SVG_LINE_GRAPH};
1341 char *title[] = {"Swap activity"};
1342 char *g_title[] = {"pswpin/s", "pswpout/s" };
1343 int g_fields[] = {0, 1};
1344 static double *spmin, *spmax;
1346 static int *outsize;
1348 if (action & F_BEGIN) {
1350 * Allocate arrays that will contain the graphs data
1351 * and the min/max values.
1353 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1356 if (action & F_MAIN) {
1357 /* Check for min/max values */
1358 save_extrema(0, 2, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1359 itv, spmin, spmax, g_fields);
1361 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1362 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1363 out, outsize, svg_p->restart);
1365 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1366 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1367 out + 1, outsize + 1, svg_p->restart);
1370 if (action & F_END) {
1371 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1372 spmin, spmax, out, outsize, svg_p, record_hdr);
1374 /* Free remaining structures */
1375 free_graphs(out, outsize, spmin, spmax);
1380 ***************************************************************************
1381 * Display paging statistics in SVG.
1384 * @a Activity structure with statistics.
1385 * @curr Index in array for current sample statistics.
1386 * @action Action expected from current function.
1387 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1388 * flag indicating that a restart record has been previously
1389 * found (.@restart) and time used for the X axis origin
1391 * @itv Interval of time in jiffies (only with F_MAIN action).
1392 * @record_hdr Pointer on record header of current stats sample.
1393 ***************************************************************************
1395 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1396 unsigned long long itv, struct record_header *record_hdr)
1399 *spc = (struct stats_paging *) a->buf[curr],
1400 *spp = (struct stats_paging *) a->buf[!curr];
1401 int group[] = {2, 2, 4};
1402 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1403 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1404 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1405 "fault/s", "majflt/s",
1406 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1407 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1408 static double *spmin, *spmax;
1410 static int *outsize;
1412 if (action & F_BEGIN) {
1414 * Allocate arrays that will contain the graphs data
1415 * and the min/max values.
1417 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1420 if (action & F_MAIN) {
1421 /* Check for min/max values */
1422 save_extrema(0, 8, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1423 itv, spmin, spmax, g_fields);
1425 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1426 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1427 out, outsize, svg_p->restart);
1429 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1430 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1431 out + 1, outsize + 1, svg_p->restart);
1433 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1434 S_VALUE(spp->pgfault, spc->pgfault, itv),
1435 out + 2, outsize + 2, svg_p->restart);
1437 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1438 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1439 out + 3, outsize + 3, svg_p->restart);
1441 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1442 S_VALUE(spp->pgfree, spc->pgfree, itv),
1443 out + 4, outsize + 4, svg_p->restart);
1445 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1446 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1447 out + 5, outsize + 5, svg_p->restart);
1449 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1450 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1451 out + 6, outsize + 6, svg_p->restart);
1453 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1454 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1455 out + 7, outsize + 7, svg_p->restart);
1458 if (action & F_END) {
1459 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1460 spmin, spmax, out, outsize, svg_p, record_hdr);
1462 /* Free remaining structures */
1463 free_graphs(out, outsize, spmin, spmax);
1468 ***************************************************************************
1469 * Display I/O and transfer rate statistics in SVG.
1472 * @a Activity structure with statistics.
1473 * @curr Index in array for current sample statistics.
1474 * @action Action expected from current function.
1475 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1476 * flag indicating that a restart record has been previously
1477 * found (.@restart) and time used for the X axis origin
1479 * @itv Interval of time in jiffies (only with F_MAIN action).
1480 * @record_hdr Pointer on record header of current stats sample.
1481 ***************************************************************************
1483 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1484 unsigned long long itv, struct record_header *record_hdr)
1487 *sic = (struct stats_io *) a->buf[curr],
1488 *sip = (struct stats_io *) a->buf[!curr];
1489 int group[] = {3, 2};
1490 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1491 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1492 char *g_title[] = {"tps", "rtps", "wtps",
1493 "bread/s", "bwrtn/s"};
1494 int g_fields[] = {0, 1, 2, 3, 4};
1495 static double *spmin, *spmax;
1497 static int *outsize;
1499 if (action & F_BEGIN) {
1501 * Allocate arrays that will contain the graphs data
1502 * and the min/max values.
1504 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1507 if (action & F_MAIN) {
1508 /* Check for min/max values */
1509 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1510 itv, spmin, spmax, g_fields);
1513 * If we get negative values, this is probably because
1514 * one or more devices/filesystems have been unmounted.
1515 * We display 0.0 in this case though we should rather tell
1516 * the user that the value cannot be calculated here.
1519 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1520 sic->dk_drive < sip->dk_drive ? 0.0 :
1521 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1522 out, outsize, svg_p->restart);
1524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1525 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1526 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1527 out + 1, outsize + 1, svg_p->restart);
1529 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1530 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1531 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1532 out + 2, outsize + 2, svg_p->restart);
1534 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1535 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1536 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1537 out + 3, outsize + 3, svg_p->restart);
1539 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1540 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1541 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1542 out + 4, outsize + 4, svg_p->restart);
1545 if (action & F_END) {
1546 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1547 spmin, spmax, out, outsize, svg_p, record_hdr);
1549 /* Free remaining structures */
1550 free_graphs(out, outsize, spmin, spmax);
1555 ***************************************************************************
1556 * Display memory statistics in SVG.
1559 * @a Activity structure with statistics.
1560 * @curr Index in array for current sample statistics.
1561 * @action Action expected from current function.
1562 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1563 * flag indicating that a restart record has been previously
1564 * found (.@restart) and time used for the X axis origin
1566 * @itv Interval of time in jiffies (only with F_MAIN action).
1567 * @record_hdr Pointer on record header of current stats sample.
1568 ***************************************************************************
1570 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1571 unsigned long long itv, struct record_header *record_hdr)
1574 *smc = (struct stats_memory *) a->buf[curr];
1575 int group1[] = {3, 1, 3, 1, 3, 5};
1576 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1577 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1578 int group2[] = {3, 1, 1};
1579 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1580 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1581 "Memory utilization (3)", "Memory utilization (4)",
1582 "Memory utilization (5)", "Memory utilization (6)"};
1583 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1584 "Swap utilization (3)"};
1585 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1586 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1587 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1589 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1591 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1592 static double *spmin, *spmax;
1594 static int *outsize;
1598 if (action & F_BEGIN) {
1600 * Allocate arrays that will contain the graphs data
1601 * and the min/max values.
1603 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1606 if (action & F_MAIN) {
1607 /* Check for min/max values */
1608 save_extrema(0, 17, 0, (void *) a->buf[curr], NULL,
1609 itv, spmin, spmax, g_fields);
1610 /* Compute %memused min/max values */
1611 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1612 if (tval > *(spmax + 3)) {
1613 *(spmax + 3) = tval;
1615 if (tval < *(spmin + 3)) {
1616 *(spmin + 3) = tval;
1618 /* Compute %commit min/max values */
1619 tval = (smc->tlmkb + smc->tlskb) ?
1620 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1621 if (tval > *(spmax + 7)) {
1622 *(spmax + 7) = tval;
1624 if (tval < *(spmin + 7)) {
1625 *(spmin + 7) = tval;
1627 /* Compute %swpused min/max values */
1629 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1630 if (tval > *(spmax + 19)) {
1631 *(spmax + 19) = tval;
1633 if (tval < *(spmin + 19)) {
1634 *(spmin + 19) = tval;
1636 /* Compute %swpcad min/max values */
1637 tval = (smc->tlskb - smc->frskb) ?
1638 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1639 if (tval > *(spmax + 20)) {
1640 *(spmax + 20) = tval;
1642 if (tval < *(spmin + 20)) {
1643 *(spmin + 20) = tval;
1645 /* Compute memused min/max values in MB */
1646 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1647 if (tval > *(spmax + 2)) {
1648 *(spmax + 2) = tval;
1650 if (tval < *(spmin + 2)) {
1651 *(spmin + 2) = tval;
1653 /* Compute swpused min/max values in MB */
1654 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1655 if (tval > *(spmax + 17)) {
1656 *(spmax + 17) = tval;
1658 if (tval < *(spmin + 17)) {
1659 *(spmin + 17) = tval;
1663 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1664 ((double) smc->frmkb) / 1024,
1665 out, outsize, svg_p->restart);
1667 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1668 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1669 out + 2, outsize + 2, svg_p->restart);
1671 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1672 ((double) smc->availablekb) / 1024,
1673 out + 1, outsize + 1, svg_p->restart);
1675 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1676 ((double) smc->bufkb) / 1024,
1677 out + 4, outsize + 4, svg_p->restart);
1679 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1680 ((double) smc->camkb) / 1024,
1681 out + 5, outsize + 5, svg_p->restart);
1683 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1684 ((double) smc->frskb) / 1024,
1685 out + 16, outsize + 16, svg_p->restart);
1687 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1688 ((double) (smc->tlskb - smc->frskb)) / 1024,
1689 out + 17, outsize + 17, svg_p->restart);
1691 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1692 ((double) smc->caskb) / 1024,
1693 out + 18, outsize + 18, svg_p->restart);
1695 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1696 ((double) smc->comkb) / 1024,
1697 out + 6, outsize + 6, svg_p->restart);
1699 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1700 ((double) smc->activekb) / 1024,
1701 out + 8, outsize + 8, svg_p->restart);
1703 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1704 ((double) smc->inactkb) / 1024,
1705 out + 9, outsize + 9, svg_p->restart);
1707 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1708 ((double) smc->dirtykb) / 1024,
1709 out + 10, outsize + 10, svg_p->restart);
1711 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1712 ((double) smc->anonpgkb) / 1024,
1713 out + 11, outsize + 11, svg_p->restart);
1715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1716 ((double) smc->slabkb) / 1024,
1717 out + 12, outsize + 12, svg_p->restart);
1719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1720 ((double) smc->kstackkb) / 1024,
1721 out + 13, outsize + 13, svg_p->restart);
1723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1724 ((double) smc->pgtblkb) / 1024,
1725 out + 14, outsize + 14, svg_p->restart);
1727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1728 ((double) smc->vmusedkb) / 1024,
1729 out + 15, outsize + 15, svg_p->restart);
1731 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1734 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1735 out + 3, outsize + 3, svg_p->dt);
1737 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1739 (smc->tlmkb + smc->tlskb) ?
1740 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1741 out + 7, outsize + 7, svg_p->dt);
1743 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1746 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1747 out + 19, outsize + 19, svg_p->dt);
1749 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1751 (smc->tlskb - smc->frskb) ?
1752 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1753 out + 20, outsize + 20, svg_p->dt);
1756 if (action & F_END) {
1758 /* Conversion kB -> MB */
1759 for (i = 0; i < 17; i++) {
1760 *(spmin + g_fields[i]) /= 1024;
1761 *(spmax + g_fields[i]) /= 1024;
1764 if (DISPLAY_MEMORY(a->opt_flags)) {
1765 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1766 g_type1, title1, g_title1, NULL, group1,
1767 spmin, spmax, out, outsize, svg_p, record_hdr);
1770 if (DISPLAY_SWAP(a->opt_flags)) {
1771 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1772 spmin + 15, spmax + 15, out + 15, outsize + 15,
1776 /* Free remaining structures */
1777 free_graphs(out, outsize, spmin, spmax);
1782 ***************************************************************************
1783 * Display kernel tables statistics in SVG.
1786 * @a Activity structure with statistics.
1787 * @curr Index in array for current sample statistics.
1788 * @action Action expected from current function.
1789 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1790 * flag indicating that a restart record has been previously
1791 * found (.@restart) and time used for the X axis origin
1793 * @itv Interval of time in jiffies (only with F_MAIN action).
1794 * @record_hdr Pointer on record header of current stats sample.
1795 ***************************************************************************
1797 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1798 unsigned long long itv, struct record_header *record_hdr)
1800 struct stats_ktables
1801 *skc = (struct stats_ktables *) a->buf[curr];
1802 int group[] = {3, 1};
1803 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1804 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1805 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1807 int g_fields[] = {1, 2, 0, 3};
1808 static double *spmin, *spmax;
1810 static int *outsize;
1812 if (action & F_BEGIN) {
1814 * Allocate arrays that will contain the graphs data
1815 * and the min/max values.
1817 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1820 if (action & F_MAIN) {
1821 /* Check for min/max values */
1822 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
1823 itv, spmin, spmax, g_fields);
1825 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1826 (unsigned long) skc->dentry_stat,
1827 out, outsize, svg_p->restart);
1829 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1830 (unsigned long) skc->file_used,
1831 out + 1, outsize + 1, svg_p->restart);
1833 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1834 (unsigned long) skc->inode_used,
1835 out + 2, outsize + 2, svg_p->restart);
1837 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1838 (unsigned long) skc->pty_nr,
1839 out + 3, outsize + 3, svg_p->restart);
1842 if (action & F_END) {
1843 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1844 spmin, spmax, out, outsize, svg_p, record_hdr);
1846 /* Free remaining structures */
1847 free_graphs(out, outsize, spmin, spmax);
1852 ***************************************************************************
1853 * Display queue and load statistics in SVG.
1856 * @a Activity structure with statistics.
1857 * @curr Index in array for current sample statistics.
1858 * @action Action expected from current function.
1859 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1860 * flag indicating that a restart record has been previously
1861 * found (.@restart) and time used for the X axis origin
1863 * @itv Interval of time in jiffies (only with F_MAIN action).
1864 * @record_hdr Pointer on record header of current stats sample.
1865 ***************************************************************************
1867 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1868 unsigned long long itv, struct record_header *record_hdr)
1871 *sqc = (struct stats_queue *) a->buf[curr];
1872 int group[] = {2, 1, 3};
1873 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1874 char *title[] = {"Queue length", "Task list", "Load average"};
1875 char *g_title[] = {"~runq-sz", "~blocked",
1877 "ldavg-1", "ldavg-5", "ldavg-15"};
1878 int g_fields[] = {0, 1, 3, 4, 5, 2};
1879 static double *spmin, *spmax;
1881 static int *outsize;
1883 if (action & F_BEGIN) {
1885 * Allocate arrays that will contain the graphs data
1886 * and the min/max values.
1888 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1891 if (action & F_MAIN) {
1892 /* Check for min/max values */
1893 save_extrema(0, 2, 4, (void *) a->buf[curr], NULL,
1894 itv, spmin, spmax, g_fields);
1896 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1897 (unsigned long) sqc->nr_running,
1898 out, outsize, svg_p->restart);
1900 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1901 (unsigned long) sqc->procs_blocked,
1902 out + 1, outsize + 1, svg_p->restart);
1904 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1905 (unsigned long) sqc->nr_threads,
1906 out + 2, outsize + 2, svg_p->restart);
1908 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1909 (double) sqc->load_avg_1 / 100,
1910 out + 3, outsize + 3, svg_p->restart);
1912 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1913 (double) sqc->load_avg_5 / 100,
1914 out + 4, outsize + 4, svg_p->restart);
1916 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1917 (double) sqc->load_avg_15 / 100,
1918 out + 5, outsize + 5, svg_p->restart);
1921 if (action & F_END) {
1922 /* Fix min/max values for load average */
1923 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1924 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1925 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1927 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1928 spmin, spmax, out, outsize, svg_p, record_hdr);
1930 /* Free remaining structures */
1931 free_graphs(out, outsize, spmin, spmax);
1936 ***************************************************************************
1937 * Display disk statistics in SVG.
1940 * @a Activity structure with statistics.
1941 * @curr Index in array for current sample statistics.
1942 * @action Action expected from current function.
1943 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1944 * flag indicating that a restart record has been previously
1945 * found (.@restart) and time used for the X axis origin
1947 * @itv Interval of time in jiffies (only with F_MAIN action).
1948 * @record_hdr Pointer on record header of current stats sample.
1949 ***************************************************************************
1951 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1952 unsigned long long itv, struct record_header *record_hdr)
1954 struct stats_disk *sdc, *sdp, sdpzero;
1955 struct ext_disk_stats xds;
1956 int group[] = {1, 2, 2, 2, 1};
1957 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
1958 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
1959 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
1960 "Disk statistics (3)", "Disk statistics (4)",
1961 "Disk statistics (5)"};
1962 char *g_title[] = {"tps",
1963 "rd_sec/s", "wr_sec/s",
1964 "avgrq-sz", "avgqu-sz",
1967 int g_fields[] = {0, 1, 2};
1968 static double *spmin, *spmax;
1970 static int *outsize;
1971 char *item_name, *persist_dev_name;
1973 int i, j, k, pos, restart, *unregistered;
1975 if (action & F_BEGIN) {
1977 * Allocate arrays (#0..7) that will contain the graphs data
1978 * and the min/max values.
1979 * Also allocate one additional array (#8) for each disk device:
1980 * spmax + 8 will contain the device major number,
1981 * spmin + 8 will contain the device minor number,
1982 * outsize + 8 will contain a positive value (TRUE) if the device
1983 * has either still not been registered, or has been unregistered.
1985 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
1988 if (action & F_MAIN) {
1989 memset(&sdpzero, 0, STATS_DISK_SIZE);
1990 restart = svg_p->restart;
1992 * Mark previously registered devices as now
1993 * possibly unregistered for all graphs.
1995 for (k = 0; k < a->nr; k++) {
1996 unregistered = outsize + k * 9 + 8;
1997 if (*unregistered == FALSE) {
1998 *unregistered = MAYBE;
2002 /* For each device structure */
2003 for (i = 0; i < a->nr; i++) {
2004 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2005 if (!(sdc->major + sdc->minor))
2006 /* Empty structure: Ignore it */
2009 /* Look for corresponding graph */
2010 for (k = 0; k < a->nr; k++) {
2011 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2012 (sdc->minor == *(spmin + k * 9 + 8)))
2017 /* Graph not found: Look for first free entry */
2018 for (k = 0; k < a->nr; k++) {
2019 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2023 /* No free graph entry: Graph for this item won't be drawn */
2027 unregistered = outsize + pos + 8;
2029 j = check_disk_reg(a, curr, !curr, i);
2031 /* This is a newly registered interface. Previous stats are zero */
2035 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2039 * If current device was marked as previously unregistered,
2040 * then set restart variable to TRUE so that the graph will be
2041 * discontinuous, and mark it as now registered.
2043 if (*unregistered == TRUE) {
2046 *unregistered = FALSE;
2048 if (*(spmax + pos + 8) == -DBL_MAX) {
2049 /* Save device major and minor numbers (if not already done) */
2050 *(spmax + pos + 8) = sdc->major;
2051 *(spmin + pos + 8) = sdc->minor;
2054 /* Check for min/max values */
2055 save_extrema(1, 2, 0, (void *) sdc, (void *) sdp,
2056 itv, spmin + pos, spmax + pos, g_fields);
2058 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2059 if (xds.arqsz < *(spmin + pos + 3)) {
2060 *(spmin + pos + 3) = xds.arqsz;
2062 if (xds.arqsz > *(spmax + pos + 3)) {
2063 *(spmax + pos + 3) = xds.arqsz;
2065 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2066 if (aqusz < *(spmin + pos + 4)) {
2067 *(spmin + pos + 4) = aqusz;
2069 if (aqusz > *(spmax + pos + 4)) {
2070 *(spmax + pos + 4) = aqusz;
2072 if (xds.await < *(spmin + pos + 5)) {
2073 *(spmin + pos + 5) = xds.await;
2075 if (xds.await > *(spmax + pos + 5)) {
2076 *(spmax + pos + 5) = xds.await;
2078 if (xds.svctm < *(spmin + pos + 6)) {
2079 *(spmin + pos + 6) = xds.svctm;
2081 if (xds.svctm > *(spmax + pos + 6)) {
2082 *(spmax + pos + 6) = xds.svctm;
2084 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2085 *(spmin + pos + 7) = xds.util / 10.0;
2087 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2088 *(spmax + pos + 7) = xds.util / 10.0;
2092 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2093 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2094 out + pos, outsize + pos, restart);
2096 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2097 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv),
2098 out + pos + 1, outsize + pos + 1, restart);
2100 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2101 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv),
2102 out + pos + 2, outsize + pos + 2, restart);
2104 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2106 out + pos + 3, outsize + pos + 3, restart);
2108 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2110 out + pos + 4, outsize + pos + 4, restart);
2112 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2114 out + pos + 5, outsize + pos + 5, restart);
2116 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2118 out + pos + 6, outsize + pos + 6, restart);
2120 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2121 0.0, xds.util / 10.0,
2122 out + pos + 7, outsize + pos + 7, svg_p->dt);
2125 /* Mark devices not seen here as now unregistered */
2126 for (k = 0; k < a->nr; k++) {
2127 unregistered = outsize + k * 9 + 8;
2128 if (*unregistered != FALSE) {
2129 *unregistered = TRUE;
2134 if (action & F_END) {
2135 for (i = 0; i < a->nr; i++) {
2136 /* Check if there is something to display */
2142 persist_dev_name = NULL;
2144 if (DISPLAY_PERSIST_NAME_S(flags)) {
2145 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2149 if (persist_dev_name) {
2150 item_name = persist_dev_name;
2153 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2154 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2158 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2159 USE_PRETTY_OPTION(flags));
2163 draw_activity_graphs(a->g_nr, g_type,
2164 title, g_title, item_name, group,
2165 spmin + pos, spmax + pos, out + pos, outsize + pos,
2169 /* Free remaining structures */
2170 free_graphs(out, outsize, spmin, spmax);
2175 ***************************************************************************
2176 * Display network interfaces statistics in SVG.
2179 * @a Activity structure with statistics.
2180 * @curr Index in array for current sample statistics.
2181 * @action Action expected from current function.
2182 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2183 * flag indicating that a restart record has been previously
2184 * found (.@restart) and time used for the X axis origin
2186 * @itv Interval of time in jiffies (only with F_MAIN action).
2187 * @record_hdr Pointer on record header of current stats sample.
2188 ***************************************************************************
2190 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2191 unsigned long long itv, struct record_header *record_hdr)
2193 struct stats_net_dev *sndc, *sndp, sndzero;
2194 int group[] = {2, 2, 3, 1};
2195 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2197 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2198 "Network statistics (3)", "Network statistics (4)"};
2199 char *g_title[] = {"rxpck/s", "txpck/s",
2201 "rxcmp/s", "txcmp/s", "rxmcst/s",
2203 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2204 static double *spmin, *spmax;
2206 static int *outsize;
2208 double rxkb, txkb, ifutil;
2209 int i, j, k, pos, restart, *unregistered;
2211 if (action & F_BEGIN) {
2213 * Allocate arrays (#0..7) that will contain the graphs data
2214 * and the min/max values.
2215 * Also allocate one additional array (#8) for each interface:
2216 * out + 8 will contain the interface name,
2217 * outsize + 8 will contain a positive value (TRUE) if the interface
2218 * has either still not been registered, or has been unregistered.
2220 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2223 if (action & F_MAIN) {
2224 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2225 restart = svg_p->restart;
2227 * Mark previously registered interfaces as now
2228 * possibly unregistered for all graphs.
2230 for (k = 0; k < a->nr; k++) {
2231 unregistered = outsize + k * 9 + 8;
2232 if (*unregistered == FALSE) {
2233 *unregistered = MAYBE;
2237 /* For each network interfaces structure */
2238 for (i = 0; i < a->nr; i++) {
2239 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2240 if (!strcmp(sndc->interface, ""))
2241 /* Empty structure: This is the end of the list */
2244 /* Look for corresponding graph */
2245 for (k = 0; k < a->nr; k++) {
2246 item_name = *(out + k * 9 + 8);
2247 if (!strcmp(sndc->interface, item_name))
2252 /* Graph not found: Look for first free entry */
2253 for (k = 0; k < a->nr; k++) {
2254 item_name = *(out + k * 9 + 8);
2255 if (!strcmp(item_name, ""))
2259 /* No free graph entry: Graph for this item won't be drawn */
2264 unregistered = outsize + pos + 8;
2266 j = check_net_dev_reg(a, curr, !curr, i);
2268 /* This is a newly registered interface. Previous stats are zero */
2272 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2276 * If current interface was marked as previously unregistered,
2277 * then set restart variable to TRUE so that the graph will be
2278 * discontinuous, and mark it as now registered.
2280 if (*unregistered == TRUE) {
2283 *unregistered = FALSE;
2285 if (!item_name[0]) {
2286 /* Save network interface name (if not already done) */
2287 strncpy(item_name, sndc->interface, CHUNKSIZE);
2288 item_name[CHUNKSIZE - 1] = '\0';
2291 /* Check for min/max values */
2292 save_extrema(7, 0, 0, (void *) sndc, (void *) sndp,
2293 itv, spmin + pos, spmax + pos, g_fields);
2295 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2296 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2297 ifutil = compute_ifutil(sndc, rxkb, txkb);
2298 if (ifutil < *(spmin + pos + 7)) {
2299 *(spmin + pos + 7) = ifutil;
2301 if (ifutil > *(spmax + pos + 7)) {
2302 *(spmax + pos + 7) = ifutil;
2306 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2307 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2308 out + pos, outsize + pos, restart);
2310 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2311 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2312 out + pos + 1, outsize + pos + 1, restart);
2314 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2316 out + pos + 2, outsize + pos + 2, restart);
2318 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2320 out + pos + 3, outsize + pos + 3, restart);
2322 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2323 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2324 out + pos + 4, outsize + pos + 4, restart);
2326 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2327 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2328 out + pos + 5, outsize + pos + 5, restart);
2330 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2331 S_VALUE(sndp->multicast, sndc->multicast, itv),
2332 out + pos + 6, outsize + pos + 6, restart);
2334 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2336 out + pos + 7, outsize + pos + 7, svg_p->dt);
2339 /* Mark interfaces not seen here as now unregistered */
2340 for (k = 0; k < a->nr; k++) {
2341 unregistered = outsize + k * 9 + 8;
2342 if (*unregistered != FALSE) {
2343 *unregistered = TRUE;
2348 if (action & F_END) {
2349 for (i = 0; i < a->nr; i++) {
2351 * Check if there is something to display.
2352 * Don't test sndc->interface because maybe the network
2353 * interface has been registered later.
2359 /* Recalculate min and max values in kB, not in B */
2360 *(spmin + pos + 2) /= 1024;
2361 *(spmax + pos + 2) /= 1024;
2362 *(spmin + pos + 3) /= 1024;
2363 *(spmax + pos + 3) /= 1024;
2365 item_name = *(out + pos + 8);
2366 draw_activity_graphs(a->g_nr, g_type,
2367 title, g_title, item_name, group,
2368 spmin + pos, spmax + pos, out + pos, outsize + pos,
2372 /* Free remaining structures */
2373 free_graphs(out, outsize, spmin, spmax);
2378 ***************************************************************************
2379 * Display network interface errors statistics in SVG.
2382 * @a Activity structure with statistics.
2383 * @curr Index in array for current sample statistics.
2384 * @action Action expected from current function.
2385 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2386 * flag indicating that a restart record has been previously
2387 * found (.@restart) and time used for the X axis origin
2389 * @itv Interval of time in jiffies (only with F_MAIN action).
2390 * @record_hdr Pointer on record header of current stats sample.
2391 ***************************************************************************
2393 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2394 unsigned long long itv, struct record_header *record_hdr)
2396 struct stats_net_edev *snedc, *snedp, snedzero;
2397 int group[] = {2, 2, 2, 3};
2398 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2400 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2401 "Network errors statistics (3)", "Network errors statistics (4)"};
2402 char *g_title[] = {"rxerr/s", "txerr/s",
2403 "rxdrop/s", "txdrop/s",
2404 "rxfifo/s", "txfifo/s",
2405 "coll/s", "txcarr/s", "rxfram/s"};
2406 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2407 static double *spmin, *spmax;
2409 static int *outsize;
2411 int i, j, k, pos, restart, *unregistered;
2413 if (action & F_BEGIN) {
2415 * Allocate arrays (#0..8) that will contain the graphs data
2416 * and the min/max values.
2417 * Also allocate one additional array (#9) for each interface:
2418 * out + 9 will contain the interface name,
2419 * outsize + 9 will contain a positive value (TRUE) if the interface
2420 * has either still not been registered, or has been unregistered.
2422 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
2425 if (action & F_MAIN) {
2426 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2427 restart = svg_p->restart;
2429 * Mark previously registered interfaces as now
2430 * possibly unregistered for all graphs.
2432 for (k = 0; k < a->nr; k++) {
2433 unregistered = outsize + k * 10 + 9;
2434 if (*unregistered == FALSE) {
2435 *unregistered = MAYBE;
2439 /* For each network interfaces structure */
2440 for (i = 0; i < a->nr; i++) {
2441 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2442 if (!strcmp(snedc->interface, ""))
2443 /* Empty structure: This is the end of the list */
2446 /* Look for corresponding graph */
2447 for (k = 0; k < a->nr; k++) {
2448 item_name = *(out + k * 10 + 9);
2449 if (!strcmp(snedc->interface, item_name))
2454 /* Graph not found: Look for first free entry */
2455 for (k = 0; k < a->nr; k++) {
2456 item_name = *(out + k * 10 + 9);
2457 if (!strcmp(item_name, ""))
2461 /* No free graph entry: Graph for this item won't be drawn */
2466 unregistered = outsize + pos + 9;
2468 j = check_net_edev_reg(a, curr, !curr, i);
2470 /* This is a newly registered interface. Previous stats are zero */
2474 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2478 * If current interface was marked as previously unregistered,
2479 * then set restart variable to TRUE so that the graph will be
2480 * discontinuous, and mark it as now registered.
2482 if (*unregistered == TRUE) {
2485 *unregistered = FALSE;
2487 if (!item_name[0]) {
2488 /* Save network interface name (if not already done) */
2489 strncpy(item_name, snedc->interface, CHUNKSIZE);
2490 item_name[CHUNKSIZE - 1] = '\0';
2493 /* Check for min/max values */
2494 save_extrema(9, 0, 0, (void *) snedc, (void *) snedp,
2495 itv, spmin + pos, spmax + pos, g_fields);
2498 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2499 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2500 out + pos, outsize + pos, restart);
2502 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2503 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2504 out + pos + 1, outsize + pos + 1, restart);
2506 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2507 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2508 out + pos + 2, outsize + pos + 2, restart);
2510 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2511 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2512 out + pos + 3, outsize + pos + 3, restart);
2514 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2515 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2516 out + pos + 4, outsize + pos + 4, restart);
2518 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2519 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2520 out + pos + 5, outsize + pos + 5, restart);
2522 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2523 S_VALUE(snedp->collisions, snedc->collisions, itv),
2524 out + pos + 6, outsize + pos + 6, restart);
2526 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2527 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2528 out + pos + 7, outsize + pos + 7, restart);
2530 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2531 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2532 out + pos + 8, outsize + pos + 8, restart);
2535 /* Mark interfaces not seen here as now unregistered */
2536 for (k = 0; k < a->nr; k++) {
2537 unregistered = outsize + k * 10 + 9;
2538 if (*unregistered != FALSE) {
2539 *unregistered = TRUE;
2544 if (action & F_END) {
2545 for (i = 0; i < a->nr; i++) {
2547 * Check if there is something to display.
2548 * Don't test snedc->interface because maybe the network
2549 * interface has been registered later.
2555 item_name = *(out + pos + 9);
2556 draw_activity_graphs(a->g_nr, g_type,
2557 title, g_title, item_name, group,
2558 spmin + pos, spmax + pos, out + pos, outsize + pos,
2562 /* Free remaining structures */
2563 free_graphs(out, outsize, spmin, spmax);
2568 ***************************************************************************
2569 * Display NFS client statistics in SVG.
2572 * @a Activity structure with statistics.
2573 * @curr Index in array for current sample statistics.
2574 * @action Action expected from current function.
2575 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2576 * flag indicating that a restart record has been previously
2577 * found (.@restart) and time used for the X axis origin
2579 * @itv Interval of time in jiffies (only with F_MAIN action).
2580 * @record_hdr Pointer on record header of current stats sample.
2581 ***************************************************************************
2583 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2584 unsigned long long itv, struct record_header *record_hdr)
2586 struct stats_net_nfs
2587 *snnc = (struct stats_net_nfs *) a->buf[curr],
2588 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2589 int group[] = {2, 2, 2};
2590 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2591 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2592 "NFS client statistics (3)"};
2593 char *g_title[] = {"call/s", "retrans/s",
2594 "read/s", "write/s",
2595 "access/s", "getatt/s"};
2596 int g_fields[] = {0, 1, 2, 3, 4, 5};
2597 static double *spmin, *spmax;
2599 static int *outsize;
2601 if (action & F_BEGIN) {
2603 * Allocate arrays that will contain the graphs data
2604 * and the min/max values.
2606 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2609 if (action & F_MAIN) {
2610 /* Check for min/max values */
2611 save_extrema(0, 0, 6, (void *) a->buf[curr], (void *) a->buf[!curr],
2612 itv, spmin, spmax, g_fields);
2615 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2616 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2617 out, outsize, svg_p->restart);
2619 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2620 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2621 out + 1, outsize + 1, svg_p->restart);
2623 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2624 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2625 out + 2, outsize + 2, svg_p->restart);
2627 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2628 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2629 out + 3, outsize + 3, svg_p->restart);
2631 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2632 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2633 out + 4, outsize + 4, svg_p->restart);
2635 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2636 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2637 out + 5, outsize + 5, svg_p->restart);
2640 if (action & F_END) {
2641 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2642 spmin, spmax, out, outsize, svg_p, record_hdr);
2644 /* Free remaining structures */
2645 free_graphs(out, outsize, spmin, spmax);
2650 ***************************************************************************
2651 * Display NFS server statistics in SVG.
2654 * @a Activity structure with statistics.
2655 * @curr Index in array for current sample statistics.
2656 * @action Action expected from current function.
2657 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2658 * flag indicating that a restart record has been previously
2659 * found (.@restart) and time used for the X axis origin
2661 * @itv Interval of time in jiffies (only with F_MAIN action).
2662 * @record_hdr Pointer on record header of current stats sample.
2663 ***************************************************************************
2665 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2666 unsigned long long itv, struct record_header *record_hdr)
2668 struct stats_net_nfsd
2669 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2670 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2671 int group[] = {2, 3, 2, 2, 2};
2672 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2673 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2674 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2675 "NFS server statistics (3)", "NFS server statistics (4)",
2676 "NFS server statistics (5)"};
2677 char *g_title[] = {"scall/s", "badcall/s",
2678 "packet/s", "udp/s", "tcp/s",
2680 "sread/s", "swrite/s",
2681 "saccess/s", "sgetatt/s"};
2682 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2683 static double *spmin, *spmax;
2685 static int *outsize;
2687 if (action & F_BEGIN) {
2689 * Allocate arrays that will contain the graphs data
2690 * and the min/max values.
2692 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2695 if (action & F_MAIN) {
2696 /* Check for min/max values */
2697 save_extrema(0, 0, 11, (void *) a->buf[curr], (void *) a->buf[!curr],
2698 itv, spmin, spmax, g_fields);
2701 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2702 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2703 out, outsize, svg_p->restart);
2705 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2706 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2707 out + 1, outsize + 1, svg_p->restart);
2709 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2710 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2711 out + 2, outsize + 2, svg_p->restart);
2713 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2714 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2715 out + 3, outsize + 3, svg_p->restart);
2717 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2718 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2719 out + 4, outsize + 4, svg_p->restart);
2721 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2722 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2723 out + 5, outsize + 5, svg_p->restart);
2725 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2726 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2727 out + 6, outsize + 6, svg_p->restart);
2729 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2730 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2731 out + 7, outsize + 7, svg_p->restart);
2733 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2734 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2735 out + 8, outsize + 8, svg_p->restart);
2737 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2738 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2739 out + 9, outsize + 9, svg_p->restart);
2741 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2742 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2743 out + 10, outsize + 10, svg_p->restart);
2746 if (action & F_END) {
2747 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2748 spmin, spmax, out, outsize, svg_p, record_hdr);
2750 /* Free remaining structures */
2751 free_graphs(out, outsize, spmin, spmax);
2756 ***************************************************************************
2757 * Display network socket statistics in SVG.
2760 * @a Activity structure with statistics.
2761 * @curr Index in array for current sample statistics.
2762 * @action Action expected from current function.
2763 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2764 * flag indicating that a restart record has been previously
2765 * found (.@restart) and time used for the X axis origin
2767 * @itv Interval of time in jiffies (only with F_MAIN action).
2768 * @record_hdr Pointer on record header of current stats sample.
2769 ***************************************************************************
2771 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2772 unsigned long long itv, struct record_header *record_hdr)
2774 struct stats_net_sock
2775 *snsc = (struct stats_net_sock *) a->buf[curr];
2776 int group[] = {1, 5};
2777 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2778 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2779 char *g_title[] = {"~totsck",
2780 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2781 int g_fields[] = {0, 1, 5, 2, 3, 4};
2782 static double *spmin, *spmax;
2784 static int *outsize;
2786 if (action & F_BEGIN) {
2788 * Allocate arrays that will contain the graphs data
2789 * and the min/max values.
2791 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2794 if (action & F_MAIN) {
2795 /* Check for min/max values */
2796 save_extrema(0, 0, 6, (void *) a->buf[curr], NULL,
2797 itv, spmin, spmax, g_fields);
2799 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2800 (unsigned long) snsc->sock_inuse,
2801 out, outsize, svg_p->restart);
2803 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2804 (unsigned long) snsc->tcp_inuse,
2805 out + 1, outsize + 1, svg_p->restart);
2807 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2808 (unsigned long) snsc->udp_inuse,
2809 out + 2, outsize + 2, svg_p->restart);
2811 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2812 (unsigned long) snsc->raw_inuse,
2813 out + 3, outsize + 3, svg_p->restart);
2815 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2816 (unsigned long) snsc->frag_inuse,
2817 out + 4, outsize + 4, svg_p->restart);
2819 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2820 (unsigned long) snsc->tcp_tw,
2821 out + 5, outsize + 5, svg_p->restart);
2824 if (action & F_END) {
2825 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2826 spmin, spmax, out, outsize, svg_p, record_hdr);
2828 /* Free remaining structures */
2829 free_graphs(out, outsize, spmin, spmax);
2834 ***************************************************************************
2835 * Display IPv4 network statistics in SVG.
2838 * @a Activity structure with statistics.
2839 * @curr Index in array for current sample statistics.
2840 * @action Action expected from current function.
2841 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2842 * flag indicating that a restart record has been previously
2843 * found (.@restart) and time used for the X axis origin
2845 * @itv Interval of time in jiffies (only with F_MAIN action).
2846 * @record_hdr Pointer on record header of current stats sample.
2847 ***************************************************************************
2849 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2850 unsigned long long itv, struct record_header *record_hdr)
2853 *snic = (struct stats_net_ip *) a->buf[curr],
2854 *snip = (struct stats_net_ip *) a->buf[!curr];
2855 int group[] = {4, 2, 2};
2856 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2857 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2858 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2859 "asmrq/s", "asmok/s",
2860 "fragok/s", "fragcrt/s"};
2861 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2862 static double *spmin, *spmax;
2864 static int *outsize;
2866 if (action & F_BEGIN) {
2868 * Allocate arrays that will contain the graphs data
2869 * and the min/max values.
2871 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2874 if (action & F_MAIN) {
2875 /* Check for min/max values */
2876 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2877 itv, spmin, spmax, g_fields);
2880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2881 S_VALUE(snip->InReceives, snic->InReceives, itv),
2882 out, outsize, svg_p->restart);
2884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2885 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2886 out + 1, outsize + 1, svg_p->restart);
2888 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2889 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2890 out + 2, outsize + 2, svg_p->restart);
2892 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2893 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2894 out + 3, outsize + 3, svg_p->restart);
2896 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2897 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2898 out + 4, outsize + 4, svg_p->restart);
2900 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2901 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2902 out + 5, outsize + 5, svg_p->restart);
2904 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2905 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2906 out + 6, outsize + 6, svg_p->restart);
2908 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2909 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2910 out + 7, outsize + 7, svg_p->restart);
2913 if (action & F_END) {
2914 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2915 spmin, spmax, out, outsize, svg_p, record_hdr);
2917 /* Free remaining structures */
2918 free_graphs(out, outsize, spmin, spmax);
2923 ***************************************************************************
2924 * Display IPv4 network errors statistics in SVG.
2927 * @a Activity structure with statistics.
2928 * @curr Index in array for current sample statistics.
2929 * @action Action expected from current function.
2930 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2931 * flag indicating that a restart record has been previously
2932 * found (.@restart) and time used for the X axis origin
2934 * @itv Interval of time in jiffies (only with F_MAIN action).
2935 * @record_hdr Pointer on record header of current stats sample.
2936 ***************************************************************************
2938 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2939 unsigned long long itv, struct record_header *record_hdr)
2941 struct stats_net_eip
2942 *sneic = (struct stats_net_eip *) a->buf[curr],
2943 *sneip = (struct stats_net_eip *) a->buf[!curr];
2944 int group[] = {3, 2, 3};
2945 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2946 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
2947 "IPv4 network errors statistics (3)"};
2948 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
2949 "idisc/s", "odisc/s",
2950 "onort/s", "asmf/s", "fragf/s"};
2951 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2952 static double *spmin, *spmax;
2954 static int *outsize;
2956 if (action & F_BEGIN) {
2958 * Allocate arrays that will contain the graphs data
2959 * and the min/max values.
2961 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2964 if (action & F_MAIN) {
2965 /* Check for min/max values */
2966 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2967 itv, spmin, spmax, g_fields);
2970 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2971 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
2972 out, outsize, svg_p->restart);
2974 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2975 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
2976 out + 1, outsize + 1, svg_p->restart);
2978 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2979 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
2980 out + 2, outsize + 2, svg_p->restart);
2982 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2983 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
2984 out + 3, outsize + 3, svg_p->restart);
2986 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2987 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
2988 out + 4, outsize + 4, svg_p->restart);
2990 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2991 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
2992 out + 5, outsize + 5, svg_p->restart);
2994 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2995 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
2996 out + 6, outsize + 6, svg_p->restart);
2998 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2999 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3000 out + 7, outsize + 7, svg_p->restart);
3003 if (action & F_END) {
3004 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3005 spmin, spmax, out, outsize, svg_p, record_hdr);
3007 /* Free remaining structures */
3008 free_graphs(out, outsize, spmin, spmax);
3013 ***************************************************************************
3014 * Display ICMPv4 network statistics in SVG.
3017 * @a Activity structure with statistics.
3018 * @curr Index in array for current sample statistics.
3019 * @action Action expected from current function.
3020 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3021 * flag indicating that a restart record has been previously
3022 * found (.@restart) and time used for the X axis origin
3024 * @itv Interval of time in jiffies (only with F_MAIN action).
3025 * @record_hdr Pointer on record header of current stats sample.
3026 ***************************************************************************
3028 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3029 unsigned long long itv, struct record_header *record_hdr)
3031 struct stats_net_icmp
3032 *snic = (struct stats_net_icmp *) a->buf[curr],
3033 *snip = (struct stats_net_icmp *) a->buf[!curr];
3034 int group[] = {2, 4, 4, 4};
3035 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3037 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3038 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3039 char *g_title[] = {"imsg/s", "omsg/s",
3040 "iech/s", "iechr/s", "oech/s", "oechr/s",
3041 "itm/s", "itmr/s", "otm/s", "otmr/s",
3042 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3043 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3044 static double *spmin, *spmax;
3046 static int *outsize;
3048 if (action & F_BEGIN) {
3050 * Allocate arrays that will contain the graphs data
3051 * and the min/max values.
3053 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3056 if (action & F_MAIN) {
3057 /* Check for min/max values */
3058 save_extrema(0, 14, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3059 itv, spmin, spmax, g_fields);
3062 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3063 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3064 out, outsize, svg_p->restart);
3066 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3067 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3068 out + 1, outsize + 1, svg_p->restart);
3070 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3071 S_VALUE(snip->InEchos, snic->InEchos, itv),
3072 out + 2, outsize + 2, svg_p->restart);
3074 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3075 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3076 out + 3, outsize + 3, svg_p->restart);
3078 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3079 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3080 out + 4, outsize + 4, svg_p->restart);
3082 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3083 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3084 out + 5, outsize + 5, svg_p->restart);
3086 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3087 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3088 out + 6, outsize + 6, svg_p->restart);
3090 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3091 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3092 out + 7, outsize + 7, svg_p->restart);
3094 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3095 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3096 out + 8, outsize + 8, svg_p->restart);
3098 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3099 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3100 out + 9, outsize + 9, svg_p->restart);
3102 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3103 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3104 out + 10, outsize + 10, svg_p->restart);
3106 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3107 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3108 out + 11, outsize + 11, svg_p->restart);
3110 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3111 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3112 out + 12, outsize + 12, svg_p->restart);
3114 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3115 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3116 out + 13, outsize + 13, svg_p->restart);
3119 if (action & F_END) {
3120 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3121 spmin, spmax, out, outsize, svg_p, record_hdr);
3123 /* Free remaining structures */
3124 free_graphs(out, outsize, spmin, spmax);
3129 ***************************************************************************
3130 * Display ICMPv4 network errors statistics in SVG.
3133 * @a Activity structure with statistics.
3134 * @curr Index in array for current sample statistics.
3135 * @action Action expected from current function.
3136 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3137 * flag indicating that a restart record has been previously
3138 * found (.@restart) and time used for the X axis origin
3140 * @itv Interval of time in jiffies (only with F_MAIN action).
3141 * @record_hdr Pointer on record header of current stats sample.
3142 ***************************************************************************
3144 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3145 unsigned long long itv, struct record_header *record_hdr)
3147 struct stats_net_eicmp
3148 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3149 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3150 int group[] = {2, 2, 2, 2, 2, 2};
3151 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3152 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3153 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3154 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3155 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3156 char *g_title[] = {"ierr/s", "oerr/s",
3157 "idstunr/s", "odstunr/s",
3158 "itmex/s", "otmex/s",
3159 "iparmpb/s", "oparmpb/s",
3160 "isrcq/s", "osrcq/s",
3161 "iredir/s", "oredir/s"};
3162 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3163 static double *spmin, *spmax;
3165 static int *outsize;
3167 if (action & F_BEGIN) {
3169 * Allocate arrays that will contain the graphs data
3170 * and the min/max values.
3172 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3175 if (action & F_MAIN) {
3176 /* Check for min/max values */
3177 save_extrema(0, 12, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3178 itv, spmin, spmax, g_fields);
3181 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3182 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3183 out, outsize, svg_p->restart);
3185 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3186 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3187 out + 1, outsize + 1, svg_p->restart);
3189 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3190 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3191 out + 2, outsize + 2, svg_p->restart);
3193 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3194 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3195 out + 3, outsize + 3, svg_p->restart);
3197 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3198 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3199 out + 4, outsize + 4, svg_p->restart);
3201 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3202 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3203 out + 5, outsize + 5, svg_p->restart);
3205 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3206 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3207 out + 6, outsize + 6, svg_p->restart);
3209 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3210 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3211 out + 7, outsize + 7, svg_p->restart);
3213 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3214 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3215 out + 8, outsize + 8, svg_p->restart);
3217 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3218 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3219 out + 9, outsize + 9, svg_p->restart);
3221 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3222 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3223 out + 10, outsize + 10, svg_p->restart);
3225 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3226 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3227 out + 11, outsize + 11, svg_p->restart);
3230 if (action & F_END) {
3231 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3232 spmin, spmax, out, outsize, svg_p, record_hdr);
3234 /* Free remaining structures */
3235 free_graphs(out, outsize, spmin, spmax);
3240 ***************************************************************************
3241 * Display TCPv4 network statistics in SVG.
3244 * @a Activity structure with statistics.
3245 * @curr Index in array for current sample statistics.
3246 * @action Action expected from current function.
3247 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3248 * flag indicating that a restart record has been previously
3249 * found (.@restart) and time used for the X axis origin
3251 * @itv Interval of time in jiffies (only with F_MAIN action).
3252 * @record_hdr Pointer on record header of current stats sample.
3253 ***************************************************************************
3255 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3256 unsigned long long itv, struct record_header *record_hdr)
3258 struct stats_net_tcp
3259 *sntc = (struct stats_net_tcp *) a->buf[curr],
3260 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3261 int group[] = {2, 2};
3262 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3263 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3264 char *g_title[] = {"active/s", "passive/s",
3265 "iseg/s", "oseg/s"};
3266 int g_fields[] = {0, 1, 2, 3};
3267 static double *spmin, *spmax;
3269 static int *outsize;
3271 if (action & F_BEGIN) {
3273 * Allocate arrays that will contain the graphs data
3274 * and the min/max values.
3276 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3279 if (action & F_MAIN) {
3280 /* Check for min/max values */
3281 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3282 itv, spmin, spmax, g_fields);
3285 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3286 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3287 out, outsize, svg_p->restart);
3289 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3290 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3291 out + 1, outsize + 1, svg_p->restart);
3293 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3294 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3295 out + 2, outsize + 2, svg_p->restart);
3297 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3298 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3299 out + 3, outsize + 3, svg_p->restart);
3302 if (action & F_END) {
3303 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3304 spmin, spmax, out, outsize, svg_p, record_hdr);
3306 /* Free remaining structures */
3307 free_graphs(out, outsize, spmin, spmax);
3312 ***************************************************************************
3313 * Display TCPv4 network errors statistics in SVG.
3316 * @a Activity structure with statistics.
3317 * @curr Index in array for current sample statistics.
3318 * @action Action expected from current function.
3319 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3320 * flag indicating that a restart record has been previously
3321 * found (.@restart) and time used for the X axis origin
3323 * @itv Interval of time in jiffies (only with F_MAIN action).
3324 * @record_hdr Pointer on record header of current stats sample.
3325 ***************************************************************************
3327 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3328 unsigned long long itv, struct record_header *record_hdr)
3330 struct stats_net_etcp
3331 *snetc = (struct stats_net_etcp *) a->buf[curr],
3332 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3333 int group[] = {2, 3};
3334 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3335 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3336 char *g_title[] = {"atmptf/s", "estres/s",
3337 "retrans/s", "isegerr/s", "orsts/s"};
3338 int g_fields[] = {0, 1, 2, 3, 4};
3339 static double *spmin, *spmax;
3341 static int *outsize;
3343 if (action & F_BEGIN) {
3345 * Allocate arrays that will contain the graphs data
3346 * and the min/max values.
3348 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3351 if (action & F_MAIN) {
3352 /* Check for min/max values */
3353 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3354 itv, spmin, spmax, g_fields);
3357 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3358 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3359 out, outsize, svg_p->restart);
3361 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3362 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3363 out + 1, outsize + 1, svg_p->restart);
3365 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3366 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3367 out + 2, outsize + 2, svg_p->restart);
3369 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3370 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3371 out + 3, outsize + 3, svg_p->restart);
3373 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3374 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3375 out + 4, outsize + 4, svg_p->restart);
3378 if (action & F_END) {
3379 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3380 spmin, spmax, out, outsize, svg_p, record_hdr);
3382 /* Free remaining structures */
3383 free_graphs(out, outsize, spmin, spmax);
3388 ***************************************************************************
3389 * Display UDPv4 network statistics in SVG.
3392 * @a Activity structure with statistics.
3393 * @curr Index in array for current sample statistics.
3394 * @action Action expected from current function.
3395 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3396 * flag indicating that a restart record has been previously
3397 * found (.@restart) and time used for the X axis origin
3399 * @itv Interval of time in jiffies (only with F_MAIN action).
3400 * @record_hdr Pointer on record header of current stats sample.
3401 ***************************************************************************
3403 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3404 unsigned long long itv, struct record_header *record_hdr)
3406 struct stats_net_udp
3407 *snuc = (struct stats_net_udp *) a->buf[curr],
3408 *snup = (struct stats_net_udp *) a->buf[!curr];
3409 int group[] = {2, 2};
3410 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3411 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3412 char *g_title[] = {"idgm/s", "odgm/s",
3413 "noport/s", "idgmerr/s"};
3414 int g_fields[] = {0, 1, 2, 3};
3415 static double *spmin, *spmax;
3417 static int *outsize;
3419 if (action & F_BEGIN) {
3421 * Allocate arrays that will contain the graphs data
3422 * and the min/max values.
3424 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3427 if (action & F_MAIN) {
3428 /* Check for min/max values */
3429 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3430 itv, spmin, spmax, g_fields);
3433 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3434 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3435 out, outsize, svg_p->restart);
3437 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3438 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3439 out + 1, outsize + 1, svg_p->restart);
3441 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3442 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3443 out + 2, outsize + 2, svg_p->restart);
3445 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3446 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3447 out + 3, outsize + 3, svg_p->restart);
3450 if (action & F_END) {
3451 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3452 spmin, spmax, out, outsize, svg_p, record_hdr);
3454 /* Free remaining structures */
3455 free_graphs(out, outsize, spmin, spmax);
3460 ***************************************************************************
3461 * Display IPV6 network socket statistics in SVG.
3464 * @a Activity structure with statistics.
3465 * @curr Index in array for current sample statistics.
3466 * @action Action expected from current function.
3467 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3468 * flag indicating that a restart record has been previously
3469 * found (.@restart) and time used for the X axis origin
3471 * @itv Interval of time in jiffies (only with F_MAIN action).
3472 * @record_hdr Pointer on record header of current stats sample.
3473 ***************************************************************************
3475 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3476 unsigned long long itv, struct record_header *record_hdr)
3478 struct stats_net_sock6
3479 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3481 int g_type[] = {SVG_LINE_GRAPH};
3482 char *title[] = {"IPv6 network sockets"};
3483 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3484 int g_fields[] = {0, 1, 2, 3};
3485 static double *spmin, *spmax;
3487 static int *outsize;
3489 if (action & F_BEGIN) {
3491 * Allocate arrays that will contain the graphs data
3492 * and the min/max values.
3494 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3497 if (action & F_MAIN) {
3498 /* Check for min/max values */
3499 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
3500 itv, spmin, spmax, g_fields);
3502 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3503 (unsigned long) snsc->tcp6_inuse,
3504 out, outsize, svg_p->restart);
3506 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3507 (unsigned long) snsc->udp6_inuse,
3508 out + 1, outsize + 1, svg_p->restart);
3510 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3511 (unsigned long) snsc->raw6_inuse,
3512 out + 2, outsize + 2, svg_p->restart);
3514 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3515 (unsigned long) snsc->frag6_inuse,
3516 out + 3, outsize + 3, svg_p->restart);
3519 if (action & F_END) {
3520 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3521 spmin, spmax, out, outsize, svg_p, record_hdr);
3523 /* Free remaining structures */
3524 free_graphs(out, outsize, spmin, spmax);
3529 ***************************************************************************
3530 * Display IPv6 network statistics in SVG.
3533 * @a Activity structure with statistics.
3534 * @curr Index in array for current sample statistics.
3535 * @action Action expected from current function.
3536 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3537 * flag indicating that a restart record has been previously
3538 * found (.@restart) and time used for the X axis origin
3540 * @itv Interval of time in jiffies (only with F_MAIN action).
3541 * @record_hdr Pointer on record header of current stats sample.
3542 ***************************************************************************
3544 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3545 unsigned long long itv, struct record_header *record_hdr)
3547 struct stats_net_ip6
3548 *snic = (struct stats_net_ip6 *) a->buf[curr],
3549 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3550 int group[] = {4, 2, 2, 2};
3551 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3553 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3554 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3555 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3556 "asmrq6/s", "asmok6/s",
3557 "imcpck6/s", "omcpck6/s",
3558 "fragok6/s", "fragcr6/s"};
3559 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3560 static double *spmin, *spmax;
3562 static int *outsize;
3564 if (action & F_BEGIN) {
3566 * Allocate arrays that will contain the graphs data
3567 * and the min/max values.
3569 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3572 if (action & F_MAIN) {
3573 /* Check for min/max values */
3574 save_extrema(10, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3575 itv, spmin, spmax, g_fields);
3578 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3579 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3580 out, outsize, svg_p->restart);
3582 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3583 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3584 out + 1, outsize + 1, svg_p->restart);
3586 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3587 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3588 out + 2, outsize + 2, svg_p->restart);
3590 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3591 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3592 out + 3, outsize + 3, svg_p->restart);
3594 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3595 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3596 out + 4, outsize + 4, svg_p->restart);
3598 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3599 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3600 out + 5, outsize + 5, svg_p->restart);
3602 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3603 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3604 out + 6, outsize + 6, svg_p->restart);
3606 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3607 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3608 out + 7, outsize + 7, svg_p->restart);
3610 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3611 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3612 out + 8, outsize + 8, svg_p->restart);
3614 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3615 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3616 out + 9, outsize + 9, svg_p->restart);
3619 if (action & F_END) {
3620 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3621 spmin, spmax, out, outsize, svg_p, record_hdr);
3623 /* Free remaining structures */
3624 free_graphs(out, outsize, spmin, spmax);
3629 ***************************************************************************
3630 * Display IPv6 network errors statistics in SVG.
3633 * @a Activity structure with statistics.
3634 * @curr Index in array for current sample statistics.
3635 * @action Action expected from current function.
3636 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3637 * flag indicating that a restart record has been previously
3638 * found (.@restart) and time used for the X axis origin
3640 * @itv Interval of time in jiffies (only with F_MAIN action).
3641 * @record_hdr Pointer on record header of current stats sample.
3642 ***************************************************************************
3644 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3645 unsigned long long itv, struct record_header *record_hdr)
3647 struct stats_net_eip6
3648 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3649 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3650 int group[] = {4, 2, 2, 3};
3651 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3653 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3654 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3655 "IPv6 network errors statistics (5)"};
3656 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3657 "idisc6/s", "odisc6/s",
3658 "inort6/s", "onort6/s",
3659 "asmf6/s", "fragf6/s", "itrpck6/s"};
3660 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3661 static double *spmin, *spmax;
3663 static int *outsize;
3665 if (action & F_BEGIN) {
3667 * Allocate arrays that will contain the graphs data
3668 * and the min/max values.
3670 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3673 if (action & F_MAIN) {
3674 /* Check for min/max values */
3675 save_extrema(11, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3676 itv, spmin, spmax, g_fields);
3679 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3680 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3681 out, outsize, svg_p->restart);
3683 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3684 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3685 out + 1, outsize + 1, svg_p->restart);
3687 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3688 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3689 out + 2, outsize + 2, svg_p->restart);
3691 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3692 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3693 out + 3, outsize + 3, svg_p->restart);
3695 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3696 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3697 out + 4, outsize + 4, svg_p->restart);
3699 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3700 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3701 out + 5, outsize + 5, svg_p->restart);
3703 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3704 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3705 out + 6, outsize + 6, svg_p->restart);
3707 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3708 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3709 out + 7, outsize + 7, svg_p->restart);
3711 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3712 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3713 out + 8, outsize + 8, svg_p->restart);
3715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3716 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3717 out + 9, outsize + 9, svg_p->restart);
3719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3720 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3721 out + 10, outsize + 10, svg_p->restart);
3724 if (action & F_END) {
3725 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3726 spmin, spmax, out, outsize, svg_p, record_hdr);
3728 /* Free remaining structures */
3729 free_graphs(out, outsize, spmin, spmax);
3734 ***************************************************************************
3735 * Display ICMPv6 network statistics in SVG.
3738 * @a Activity structure with statistics.
3739 * @curr Index in array for current sample statistics.
3740 * @action Action expected from current function.
3741 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3742 * flag indicating that a restart record has been previously
3743 * found (.@restart) and time used for the X axis origin
3745 * @itv Interval of time in jiffies (only with F_MAIN action).
3746 * @record_hdr Pointer on record header of current stats sample.
3747 ***************************************************************************
3749 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3750 unsigned long long itv, struct record_header *record_hdr)
3752 struct stats_net_icmp6
3753 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3754 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3755 int group[] = {2, 3, 5, 3, 4};
3756 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3757 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3758 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3759 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3760 "ICMPv6 network statistics (5)"};
3761 char *g_title[] = {"imsg6/s", "omsg6/s",
3762 "iech6/s", "iechr6/s", "oechr6/s",
3763 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3764 "irtsol6/s", "ortsol6/s", "irtad6/s",
3765 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3766 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3767 static double *spmin, *spmax;
3769 static int *outsize;
3771 if (action & F_BEGIN) {
3773 * Allocate arrays that will contain the graphs data
3774 * and the min/max values.
3776 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3779 if (action & F_MAIN) {
3780 /* Check for min/max values */
3781 save_extrema(0, 17, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3782 itv, spmin, spmax, g_fields);
3785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3786 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3787 out, outsize, svg_p->restart);
3789 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3790 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3791 out + 1, outsize + 1, svg_p->restart);
3793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3794 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3795 out + 2, outsize + 2, svg_p->restart);
3797 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3798 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3799 out + 3, outsize + 3, svg_p->restart);
3801 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3802 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3803 out + 4, outsize + 4, svg_p->restart);
3805 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3806 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3807 out + 5, outsize + 5, svg_p->restart);
3809 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3810 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3811 out + 6, outsize + 6, svg_p->restart);
3813 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3814 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3815 out + 7, outsize + 7, svg_p->restart);
3817 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3818 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3819 out + 8, outsize + 8, svg_p->restart);
3821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3822 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3823 out + 9, outsize + 9, svg_p->restart);
3825 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3826 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3827 out + 10, outsize + 10, svg_p->restart);
3829 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3830 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3831 out + 11, outsize + 11, svg_p->restart);
3833 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3834 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3835 out + 12, outsize + 12, svg_p->restart);
3837 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3838 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3839 out + 13, outsize + 13, svg_p->restart);
3841 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3842 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3843 out + 14, outsize + 14, svg_p->restart);
3845 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3846 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3847 out + 15, outsize + 15, svg_p->restart);
3849 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3850 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3851 out + 16, outsize + 16, svg_p->restart);
3854 if (action & F_END) {
3855 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3856 spmin, spmax, out, outsize, svg_p, record_hdr);
3858 /* Free remaining structures */
3859 free_graphs(out, outsize, spmin, spmax);
3864 ***************************************************************************
3865 * Display ICMPv6 network errors statistics in SVG.
3868 * @a Activity structure with statistics.
3869 * @curr Index in array for current sample statistics.
3870 * @action Action expected from current function.
3871 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3872 * flag indicating that a restart record has been previously
3873 * found (.@restart) and time used for the X axis origin
3875 * @itv Interval of time in jiffies (only with F_MAIN action).
3876 * @record_hdr Pointer on record header of current stats sample.
3877 ***************************************************************************
3879 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3880 unsigned long long itv, struct record_header *record_hdr)
3882 struct stats_net_eicmp6
3883 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3884 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3885 int group[] = {1, 2, 2, 2, 2, 2};
3886 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3887 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3888 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3889 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3890 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3891 char *g_title[] = {"ierr6/s",
3892 "idtunr6/s", "odtunr6/s",
3893 "itmex6/s", "otmex6/s",
3894 "iprmpb6/s", "oprmpb6/s",
3895 "iredir6/s", "oredir6/s",
3896 "ipck2b6/s", "opck2b6/s"};
3897 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3898 static double *spmin, *spmax;
3900 static int *outsize;
3902 if (action & F_BEGIN) {
3904 * Allocate arrays that will contain the graphs data
3905 * and the min/max values.
3907 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3910 if (action & F_MAIN) {
3911 /* Check for min/max values */
3912 save_extrema(0, 11, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3913 itv, spmin, spmax, g_fields);
3916 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3917 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
3918 out, outsize, svg_p->restart);
3920 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3921 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
3922 out + 1, outsize + 1, svg_p->restart);
3924 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3925 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
3926 out + 2, outsize + 2, svg_p->restart);
3928 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3929 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
3930 out + 3, outsize + 3, svg_p->restart);
3932 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3933 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
3934 out + 4, outsize + 4, svg_p->restart);
3936 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3937 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
3938 out + 5, outsize + 5, svg_p->restart);
3940 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3941 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
3942 out + 6, outsize + 6, svg_p->restart);
3944 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3945 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
3946 out + 7, outsize + 7, svg_p->restart);
3948 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3949 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
3950 out + 8, outsize + 8, svg_p->restart);
3952 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3953 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
3954 out + 9, outsize + 9, svg_p->restart);
3956 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3957 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
3958 out + 10, outsize + 10, svg_p->restart);
3961 if (action & F_END) {
3962 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3963 spmin, spmax, out, outsize, svg_p, record_hdr);
3965 /* Free remaining structures */
3966 free_graphs(out, outsize, spmin, spmax);
3971 ***************************************************************************
3972 * Display UDPv6 network statistics in SVG.
3975 * @a Activity structure with statistics.
3976 * @curr Index in array for current sample statistics.
3977 * @action Action expected from current function.
3978 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3979 * flag indicating that a restart record has been previously
3980 * found (.@restart) and time used for the X axis origin
3982 * @itv Interval of time in jiffies (only with F_MAIN action).
3983 * @record_hdr Pointer on record header of current stats sample.
3984 ***************************************************************************
3986 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3987 unsigned long long itv, struct record_header *record_hdr)
3989 struct stats_net_udp6
3990 *snuc = (struct stats_net_udp6 *) a->buf[curr],
3991 *snup = (struct stats_net_udp6 *) a->buf[!curr];
3992 int group[] = {2, 2};
3993 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3994 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
3995 char *g_title[] = {"idgm6/s", "odgm6/s",
3996 "noport6/s", "idgmer6/s"};
3997 int g_fields[] = {0, 1, 2, 3};
3998 static double *spmin, *spmax;
4000 static int *outsize;
4002 if (action & F_BEGIN) {
4004 * Allocate arrays that will contain the graphs data
4005 * and the min/max values.
4007 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4010 if (action & F_MAIN) {
4011 /* Check for min/max values */
4012 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
4013 itv, spmin, spmax, g_fields);
4016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4017 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4018 out, outsize, svg_p->restart);
4020 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4021 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4022 out + 1, outsize + 1, svg_p->restart);
4024 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4025 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4026 out + 2, outsize + 2, svg_p->restart);
4028 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4029 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4030 out + 3, outsize + 3, svg_p->restart);
4033 if (action & F_END) {
4034 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4035 spmin, spmax, out, outsize, svg_p, record_hdr);
4037 /* Free remaining structures */
4038 free_graphs(out, outsize, spmin, spmax);
4043 ***************************************************************************
4044 * Display CPU frequency statistics in SVG.
4047 * @a Activity structure with statistics.
4048 * @curr Index in array for current sample statistics.
4049 * @action Action expected from current function.
4050 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4051 * flag indicating that a restart record has been previously
4052 * found (.@restart) and time used for the X axis origin
4054 * @itv Interval of time in jiffies (unused here).
4055 * @record_hdr Pointer on record header of current stats sample.
4056 ***************************************************************************
4058 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4059 unsigned long long itv, struct record_header *record_hdr)
4061 struct stats_pwr_cpufreq *spc, *spp;
4063 int g_type[] = {SVG_LINE_GRAPH};
4064 char *title[] = {"CPU frequency"};
4065 char *g_title[] = {"MHz"};
4066 static double *spmin, *spmax;
4068 static int *outsize;
4072 if (action & F_BEGIN) {
4074 * Allocate arrays that will contain the graphs data
4075 * and the min/max values.
4077 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4080 if (action & F_MAIN) {
4082 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4084 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4085 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4087 /* Should current CPU (including CPU "all") be displayed? */
4088 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4093 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4094 ((double) spp->cpufreq) / 100,
4095 ((double) spc->cpufreq) / 100,
4096 out + i, outsize + i, svg_p->restart, svg_p->dt,
4097 spmin + i, spmax + i);
4101 if (action & F_END) {
4102 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4104 /* Should current CPU (including CPU "all") be displayed? */
4105 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4110 /* This is CPU "all" */
4111 strcpy(item_name, "all");
4114 sprintf(item_name, "%d", i - 1);
4117 draw_activity_graphs(a->g_nr, g_type,
4118 title, g_title, item_name, group,
4119 spmin + i, spmax + i, out + i, outsize + i,
4123 /* Free remaining structures */
4124 free_graphs(out, outsize, spmin, spmax);
4129 ***************************************************************************
4130 * Display fan statistics in SVG.
4133 * @a Activity structure with statistics.
4134 * @curr Index in array for current sample statistics.
4135 * @action Action expected from current function.
4136 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4137 * flag indicating that a restart record has been previously
4138 * found (.@restart) and time used for the X axis origin
4140 * @itv Interval of time in jiffies (unused here).
4141 * @record_hdr Pointer on record header of current stats sample.
4142 ***************************************************************************
4144 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4145 unsigned long long itv, struct record_header *record_hdr)
4147 struct stats_pwr_fan *spc, *spp;
4149 int g_type[] = {SVG_LINE_GRAPH};
4150 char *title[] = {"Fan speed"};
4151 char *g_title[] = {"~rpm"};
4152 static double *spmin, *spmax;
4154 static int *outsize;
4155 char item_name[MAX_SENSORS_DEV_LEN + 8];
4158 if (action & F_BEGIN) {
4160 * Allocate arrays that will contain the graphs data
4161 * and the min/max values.
4163 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4166 if (action & F_MAIN) {
4168 for (i = 0; i < a->nr; i++) {
4170 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4171 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4174 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4177 out + i, outsize + i, svg_p->restart, svg_p->dt,
4178 spmin + i, spmax + i);
4182 if (action & F_END) {
4183 for (i = 0; i < a->nr; i++) {
4185 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4187 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4188 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4190 draw_activity_graphs(a->g_nr, g_type,
4191 title, g_title, item_name, group,
4192 spmin + i, spmax + i, out + i, outsize + i,
4196 /* Free remaining structures */
4197 free_graphs(out, outsize, spmin, spmax);
4202 ***************************************************************************
4203 * Display temperature statistics in SVG.
4206 * @a Activity structure with statistics.
4207 * @curr Index in array for current sample statistics.
4208 * @action Action expected from current function.
4209 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4210 * flag indicating that a restart record has been previously
4211 * found (.@restart) and time used for the X axis origin
4213 * @itv Interval of time in jiffies (unused here).
4214 * @record_hdr Pointer on record header of current stats sample.
4215 ***************************************************************************
4217 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4218 unsigned long long itv, struct record_header *record_hdr)
4220 struct stats_pwr_temp *spc;
4221 int group[] = {1, 1};
4222 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4223 char *title[] = {"Device temperature (1)",
4224 "Device temperature (2)"};
4225 char *g_title[] = {"~degC",
4227 static double *spmin, *spmax;
4229 static int *outsize;
4230 char item_name[MAX_SENSORS_DEV_LEN + 8];
4234 if (action & F_BEGIN) {
4236 * Allocate arrays that will contain the graphs data
4237 * and the min/max values.
4239 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4242 if (action & F_MAIN) {
4243 /* For each temperature sensor */
4244 for (i = 0; i < a->nr; i++) {
4246 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4248 /* Look for min/max values */
4249 if (spc->temp < *(spmin + 2 * i)) {
4250 *(spmin + 2 * i) = spc->temp;
4252 if (spc->temp > *(spmax + 2 * i)) {
4253 *(spmax + 2 * i) = spc->temp;
4255 tval = (spc->temp_max - spc->temp_min) ?
4256 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4258 if (tval < *(spmin + 2 * i + 1)) {
4259 *(spmin + 2 * i + 1) = tval;
4261 if (tval > *(spmax + 2 * i + 1)) {
4262 *(spmax + 2 * i + 1) = tval;
4266 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4268 out + 2 * i, outsize + 2 * i, svg_p->restart);
4270 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4272 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4276 if (action & F_END) {
4277 for (i = 0; i < a->nr; i++) {
4279 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4281 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4282 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4284 draw_activity_graphs(a->g_nr, g_type,
4285 title, g_title, item_name, group,
4286 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4290 /* Free remaining structures */
4291 free_graphs(out, outsize, spmin, spmax);
4296 ***************************************************************************
4297 * Display voltage inputs statistics in SVG.
4300 * @a Activity structure with statistics.
4301 * @curr Index in array for current sample statistics.
4302 * @action Action expected from current function.
4303 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4304 * flag indicating that a restart record has been previously
4305 * found (.@restart) and time used for the X axis origin
4307 * @itv Interval of time in jiffies (only with F_MAIN action).
4308 * @record_hdr Pointer on record header of current stats sample.
4309 ***************************************************************************
4311 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4312 unsigned long long itv, struct record_header *record_hdr)
4314 struct stats_pwr_in *spc;
4315 int group[] = {1, 1};
4316 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4317 char *title[] = {"Voltage inputs (1)",
4318 "Voltage inputs (2)"};
4319 char *g_title[] = {"inV",
4321 static double *spmin, *spmax;
4323 static int *outsize;
4324 char item_name[MAX_SENSORS_DEV_LEN + 8];
4328 if (action & F_BEGIN) {
4330 * Allocate arrays that will contain the graphs data
4331 * and the min/max values.
4333 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4336 if (action & F_MAIN) {
4337 /* For each temperature sensor */
4338 for (i = 0; i < a->nr; i++) {
4340 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4342 /* Look for min/max values */
4343 if (spc->in < *(spmin + 2 * i)) {
4344 *(spmin + 2 * i) = spc->in;
4346 if (spc->in > *(spmax + 2 * i)) {
4347 *(spmax + 2 * i) = spc->in;
4349 tval = (spc->in_max - spc->in_min) ?
4350 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4352 if (tval < *(spmin + 2 * i + 1)) {
4353 *(spmin + 2 * i + 1) = tval;
4355 if (tval > *(spmax + 2 * i + 1)) {
4356 *(spmax + 2 * i + 1) = tval;
4360 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4362 out + 2 * i, outsize + 2 * i, svg_p->restart);
4364 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4366 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4370 if (action & F_END) {
4371 for (i = 0; i < a->nr; i++) {
4373 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4375 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4376 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4378 draw_activity_graphs(a->g_nr, g_type,
4379 title, g_title, item_name, group,
4380 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4384 /* Free remaining structures */
4385 free_graphs(out, outsize, spmin, spmax);
4390 ***************************************************************************
4391 * Display huge pages statistics in SVG.
4394 * @a Activity structure with statistics.
4395 * @curr Index in array for current sample statistics.
4396 * @action Action expected from current function.
4397 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4398 * flag indicating that a restart record has been previously
4399 * found (.@restart) and time used for the X axis origin
4401 * @itv Interval of time in jiffies (only with F_MAIN action).
4402 * @record_hdr Pointer on record header of current stats sample.
4403 ***************************************************************************
4405 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4406 unsigned long long itv, struct record_header *record_hdr)
4409 *smc = (struct stats_huge *) a->buf[curr];
4410 int group[] = {2, 1};
4411 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4412 char *title[] = {"Huge pages utilization (1)",
4413 "Huge pages utilization (2)"};
4414 char *g_title[] = {"~kbhugfree", "~kbhugused",
4416 int g_fields[] = {0};
4417 static double *spmin, *spmax;
4419 static int *outsize;
4422 if (action & F_BEGIN) {
4424 * Allocate arrays that will contain the graphs data
4425 * and the min/max values.
4427 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4430 if (action & F_MAIN) {
4431 /* Check for min/max values */
4432 save_extrema(0, 1, 0, (void *) a->buf[curr], NULL,
4433 itv, spmin, spmax, g_fields);
4435 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4436 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4438 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4439 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4441 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4442 if (tval < *(spmin + 2)) {
4443 *(spmin + 2) = tval;
4445 if (tval > *(spmax + 2)) {
4446 *(spmax + 2) = tval;
4450 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4451 (unsigned long) smc->frhkb,
4452 out, outsize, svg_p->restart);
4454 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4455 (unsigned long) smc->tlhkb - smc->frhkb,
4456 out + 1, outsize + 1, svg_p->restart);
4458 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4460 out + 2, outsize + 2, svg_p->dt);
4463 if (action & F_END) {
4464 draw_activity_graphs(a->g_nr, g_type,
4465 title, g_title, NULL, group,
4466 spmin, spmax, out, outsize, svg_p, record_hdr);
4468 /* Free remaining structures */
4469 free_graphs(out, outsize, spmin, spmax);
4474 ***************************************************************************
4475 * Display filesystem statistics in SVG.
4478 * @a Activity structure with statistics.
4479 * @curr Index in array for current sample statistics.
4480 * @action Action expected from current function.
4481 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4482 * flag indicating that a restart record has been previously
4483 * found (.@restart) and time used for the X axis origin
4485 * @itv Interval of time in jiffies (unused here).
4486 * @record_hdr Pointer on record header of current stats sample.
4487 ***************************************************************************
4489 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4490 unsigned long long itv, struct record_header *record_hdr)
4492 struct stats_filesystem *sfc, *sfp;
4493 int group[] = {2, 2, 2, 1};
4494 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4495 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4496 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4497 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4498 char *g_title[] = {"~MBfsfree", "~MBfsused",
4499 "%ufsused", "%fsused",
4500 "Ifree/1000", "Iused/1000",
4502 static double *spmin, *spmax;
4504 static int *outsize;
4505 char *item_name = NULL;
4507 int i, k, pos, restart;
4509 if (action & F_BEGIN) {
4511 * Allocate arrays (#0..6) that will contain the graphs data
4512 * and the min/max values.
4513 * Also allocate two additional arrays (#7..8) for each filesystem:
4514 * out + 7 will contain the filesystem name,
4515 * out + 8 will contain the mount point.
4517 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
4520 if (action & F_MAIN) {
4521 /* For each filesystem structure */
4522 for (i = 0; i < a->nr; i++) {
4523 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4526 /* Size of filesystem is zero: We are at the end of the list */
4529 /* Look for corresponding graph */
4530 for (k = 0; k < a->nr; k++) {
4531 item_name = *(out + k * 9 + 7);
4532 if (!strcmp(sfc->fs_name, item_name))
4538 /* Graph not found: Look for first free entry */
4539 for (k = 0; k < a->nr; k++) {
4540 item_name = *(out + k * 9 + 7);
4541 if (!strcmp(item_name, ""))
4545 /* No free graph entry: Graph for this item won't be drawn */
4551 if (!item_name[0]) {
4552 /* Save filesystem name and mount point (if not already done) */
4553 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4554 item_name[CHUNKSIZE - 1] = '\0';
4555 item_name = *(out + pos + 8);
4556 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4557 item_name[CHUNKSIZE - 1] = '\0';
4561 for (k = 0; k < a->nr; k++) {
4562 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4563 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4564 /* Filesystem found in previous sample */
4565 restart = svg_p->restart;
4569 /* Check for min/max values */
4571 /* Compute fsfree min/max values */
4572 tval = (double) sfc->f_bfree;
4573 if (tval > *(spmax + pos)) {
4574 *(spmax + pos) = tval;
4576 if (tval < *(spmin + pos)) {
4577 *(spmin + pos) = tval;
4579 /* Compute fsused min/max values */
4580 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4581 if (tval > *(spmax + pos + 1)) {
4582 *(spmax + pos + 1) = tval;
4584 if (tval < *(spmin + pos + 1)) {
4585 *(spmin + pos + 1) = tval;
4587 /* Compute %ufsused min/max values */
4588 tval = sfc->f_blocks ?
4589 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4590 if (tval > *(spmax + pos + 2)) {
4591 *(spmax + pos + 2) = tval;
4593 if (tval < *(spmin + pos + 2)) {
4594 *(spmin + pos + 2) = tval;
4596 /* Compute %fsused min/max values */
4597 tval = sfc->f_blocks ?
4598 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4599 if (tval > *(spmax + pos + 3)) {
4600 *(spmax + pos + 3) = tval;
4602 if (tval < *(spmin + pos + 3)) {
4603 *(spmin + pos + 3) = tval;
4605 /* Compute Ifree min/max values */
4606 tval = (double) sfc->f_ffree;
4607 if (tval > *(spmax + pos + 4)) {
4608 *(spmax + pos + 4) = tval;
4610 if (tval < *(spmin + pos + 4)) {
4611 *(spmin + pos + 4) = tval;
4613 /* Compute Iused min/max values */
4614 tval = (double) (sfc->f_files - sfc->f_ffree);
4615 if (tval > *(spmax + pos + 5)) {
4616 *(spmax + pos + 5) = tval;
4618 if (tval < *(spmin + pos + 5)) {
4619 *(spmin + pos + 5) = tval;
4621 /* Compute %Iused min/max values */
4622 tval = sfc->f_files ?
4623 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4624 if (tval > *(spmax + pos + 6)) {
4625 *(spmax + pos + 6) = tval;
4627 if (tval < *(spmin + pos + 6)) {
4628 *(spmin + pos + 6) = tval;
4632 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4633 (double) sfc->f_bfree / 1024 / 1024,
4634 out + pos, outsize + pos, restart);
4636 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4637 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4638 out + pos + 1, outsize + pos + 1, restart);
4640 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4643 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4644 out + pos + 2, outsize + pos + 2, svg_p->dt);
4646 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4649 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4650 out + pos + 3, outsize + pos + 3, svg_p->dt);
4652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4653 ((double) sfc->f_ffree) / 1000,
4654 out + pos + 4, outsize + pos + 4, restart);
4656 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4657 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4658 out + pos + 5, outsize + pos + 5, restart);
4660 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4663 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4664 out + pos + 6, outsize + pos + 6, svg_p->dt);
4668 if (action & F_END) {
4670 for (i = 0; i < a->nr; i++) {
4672 /* Check if there is something to display */
4677 /* Conversion B -> MB and inodes/1000 */
4678 for (k = 0; k < 2; k++) {
4679 *(spmin + pos + k) /= (1024 * 1024);
4680 *(spmax + pos + k) /= (1024 * 1024);
4681 *(spmin + pos + 4 + k) /= 1000;
4682 *(spmax + pos + 4 + k) /= 1000;
4685 if (DISPLAY_MOUNT(a->opt_flags)) {
4686 item_name = *(out + pos + 8);
4689 item_name = *(out + pos + 7);
4692 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4693 spmin + pos, spmax + pos, out + pos, outsize + pos,
4697 /* Free remaining structures */
4698 free_graphs(out, outsize, spmin, spmax);
4703 ***************************************************************************
4704 * Display Fibre Channel HBA statistics in SVG.
4707 * @a Activity structure with statistics.
4708 * @curr Index in array for current sample statistics.
4709 * @action Action expected from current function.
4710 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4711 * flag indicating that a restart record has been previously
4712 * found (.@restart) and time used for the X axis origin
4714 * @itv Interval of time in jiffies (only with F_MAIN action).
4715 * @record_hdr Pointer on record header of current stats sample.
4716 ***************************************************************************
4718 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4719 unsigned long long itv, struct record_header *record_hdr)
4721 struct stats_fchost *sfcc, *sfcp;
4722 int group[] = {2, 2};
4723 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4724 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4725 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4726 "fch_rxw/s", "fch_txw/s"};
4727 int g_fields[] = {0, 1, 2, 3};
4728 static double *spmin, *spmax;
4730 static int *outsize;
4734 if (action & F_BEGIN) {
4736 * Allocate arrays (#0..3) that will contain the graphs data
4737 * and the min/max values.
4738 * Also allocate one additional array (#4) that will contain
4741 out = allocate_graph_lines(4 * a->nr, &outsize, &spmin, &spmax);
4744 if (action & F_MAIN) {
4745 /* For each FC HBA */
4746 for (i = 0; i < a->nr; i++) {
4748 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4749 if (!sfcc->fchost_name[0])
4750 /* We are at the end of the list */
4753 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
4756 item_name = *(out + pos + 4);
4757 if (!item_name[0]) {
4758 /* Save FC HBA name */
4759 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4760 item_name[CHUNKSIZE - 1] = '\0';
4763 /* Look for min/max values */
4764 save_extrema(0, 4, 0, (void *) sfcc, (void *) sfcp,
4765 itv, spmin + pos, spmax + pos, g_fields);
4768 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4769 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4770 out + pos, outsize + pos, svg_p->restart);
4772 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4773 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4774 out + pos + 1, outsize + pos + 1, svg_p->restart);
4776 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4777 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4778 out + pos + 2, outsize + pos + 2, svg_p->restart);
4780 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4781 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4782 out + pos + 3, outsize + pos + 3, svg_p->restart);
4786 if (action & F_END) {
4787 for (i = 0; i < a->nr; i++) {
4789 /* Check if there is something to display */
4794 item_name = *(out + pos + 4);
4795 draw_activity_graphs(a->g_nr, g_type,
4796 title, g_title, item_name, group,
4797 spmin + pos, spmax + pos, out + pos, outsize + pos,
4801 /* Free remaining structures */
4802 free_graphs(out, outsize, spmin, spmax);
4807 ***************************************************************************
4808 * Display softnet statistics in SVG.
4811 * @a Activity structure with statistics.
4812 * @curr Index in array for current sample statistics.
4813 * @action Action expected from current function.
4814 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4815 * flag indicating that a restart record has been previously
4816 * found (.@restart) and time used for the X axis origin
4818 * @itv Interval of time in jiffies (only with F_MAIN action).
4819 * @record_hdr Pointer on record header of current stats sample.
4820 ***************************************************************************
4822 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4823 unsigned long long itv, struct record_header *record_hdr)
4825 struct stats_softnet *ssnc, *ssnp;
4826 int group[] = {2, 3};
4827 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4828 char *title[] = {"Software-based network processing statistics (1)",
4829 "Software-based network processing statistics (2)"};
4830 char *g_title[] = {"total/s", "dropd/s",
4831 "squeezd/s", "rx_rps/s", "flw_lim/s"};
4832 int g_fields[] = {0, 1, 2, 3, 4};
4833 static double *spmin, *spmax;
4835 static int *outsize;
4839 if (action & F_BEGIN) {
4841 * Allocate arrays that will contain the graphs data
4842 * and the min/max values.
4844 out = allocate_graph_lines(5 * a->nr, &outsize, &spmin, &spmax);
4847 if (action & F_MAIN) {
4849 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4851 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
4852 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
4854 /* Should current CPU (including CPU "all") be displayed? */
4855 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4861 /* Check for min/max values */
4862 save_extrema(0, 0, 5, (void *) ssnc, (void *) ssnp,
4863 itv, spmin + pos, spmax + pos, g_fields);
4866 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4867 S_VALUE(ssnp->processed, ssnc->processed, itv),
4868 out + pos, outsize + pos, svg_p->restart);
4870 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4871 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
4872 out + pos + 1, outsize + pos + 1, svg_p->restart);
4874 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4875 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
4876 out + pos + 2, outsize + pos + 2, svg_p->restart);
4878 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4879 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
4880 out + pos + 3, outsize + pos + 3, svg_p->restart);
4882 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4883 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
4884 out + pos + 4, outsize + pos + 4, svg_p->restart);
4888 if (action & F_END) {
4889 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4891 /* Should current CPU (including CPU "all") be displayed? */
4892 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4899 /* This is CPU "all" */
4900 strcpy(item_name, "all");
4903 sprintf(item_name, "%d", i - 1);
4906 draw_activity_graphs(a->g_nr, g_type,
4907 title, g_title, item_name, group,
4908 spmin + pos, spmax + pos, out + pos, outsize + pos,
4912 /* Free remaining structures */
4913 free_graphs(out, outsize, spmin, spmax);