2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016 by Sebastien GODARD (sysstat <at> orange.fr)
5 ***************************************************************************
6 * This program is free software; you can redistribute it and/or modify it *
7 * under the terms of the GNU General Public License as published by the *
8 * Free Software Foundation; either version 2 of the License, or (at your *
9 * option) any later version. *
11 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * You should have received a copy of the GNU General Public License along *
17 * with this program; if not, write to the Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *
19 ***************************************************************************
31 #include "svg_stats.h"
36 #define _(string) gettext(string)
38 #define _(string) (string)
41 extern unsigned int flags;
42 extern unsigned int dm_major;
44 unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
45 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
46 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
47 0xcc3300, 0xbfbfbf, 0xffffbf, 0xff3300};
48 #define SVG_COLORS_IDX_MASK 0x0f
51 ***************************************************************************
52 * Compare the values of a statistics sample with the max and min values
53 * already found in previous samples for this same activity. If some new
54 * min or max values are found, then save them.
55 * 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 * @minv Array containing min values already found for this activity.
68 * @maxv Array containing max values already found for this activity.
71 * @minv Array containg the possible new min values for current activity.
72 * @maxv Array containg the possible new max values for current activity.
74 * NB: @minv and @maxv arrays contain values in the same order as the fields
75 * in the statistics structure.
76 ***************************************************************************
78 void save_extrema(int llu_nr, int lu_nr, int u_nr, void *cs, void *ps,
79 unsigned long long itv, double *spmin, double *spmax, int g_fields[])
81 unsigned long long *lluc, *llup;
82 unsigned long *luc, *lup;
83 unsigned int *uc, *up;
87 /* Compare unsigned long long fields */
88 lluc = (unsigned long long *) cs;
89 llup = (unsigned long long *) ps;
90 for (i = 0; i < llu_nr; i++, m++) {
92 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
96 * If no pointer on previous sample has been given
97 * then the value is not a per-second one.
101 if (val < *(spmin + g_fields[m])) {
102 *(spmin + g_fields[m]) = val;
104 if (val > *(spmax + g_fields[m])) {
105 *(spmax + g_fields[m]) = val;
107 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
109 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
113 /* Compare unsigned long fields */
114 luc = (unsigned long *) lluc;
115 lup = (unsigned long *) llup;
116 for (i = 0; i < lu_nr; i++, m++) {
118 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
123 if (val < *(spmin + g_fields[m])) {
124 *(spmin + g_fields[m]) = val;
126 if (val > *(spmax + g_fields[m])) {
127 *(spmax + g_fields[m]) = val;
129 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
131 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
135 /* Compare unsigned int fields */
136 uc = (unsigned int *) luc;
137 up = (unsigned int *) lup;
138 for (i = 0; i < u_nr; i++, m++) {
140 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
145 if (val < *(spmin + g_fields[m])) {
146 *(spmin + g_fields[m]) = val;
148 if (val > *(spmax + g_fields[m])) {
149 *(spmax + g_fields[m]) = val;
151 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
153 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
159 ***************************************************************************
160 * Find the min and max values of all the graphs that will be drawn in the
161 * same view. The graphs have their own min and max values in
162 * minv[pos...pos+n-1] and maxv[pos...pos+n-1].
165 * @pos Position in array for the first graph extrema value.
166 * @n Number of graphs to scan.
167 * @minv Array containing min values for graphs.
168 * @maxv Array containing max values for graphs.
171 * @gmin Global min value found.
172 * @gmax Global max value found.
173 ***************************************************************************
175 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
176 double *gmin, double *gmax)
180 *gmin = *(spmin + pos);
181 *gmax = *(spmax + pos);
183 for (i = 1; i < n; i++) {
184 if (*(spmin + pos + i) < *gmin) {
185 *gmin = *(spmin + pos + i);
187 if (*(spmax + pos + i) > *gmax) {
188 *gmax = *(spmax + pos + i);
194 ***************************************************************************
195 * Allocate arrays used to save graphs data, min and max values.
196 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
197 * array is returned. This is equivalent to "char data[][n]" where each
198 * element is of indeterminate size and will contain the graph data (eg.
199 * << path d="M12,14 L13,16..." ... >>.
200 * The size of element data[i] is given by outsize[i].
201 * Also allocate an array to save min values (equivalent to "double spmin[n]")
202 * and an array for max values (equivalent to "double spmax[n]").
205 * @n Number of graphs to draw for current activity.
208 * @outsize Array that will contain the sizes of each element in array
209 * of chars. Equivalent to "int outsize[n]" with
210 * outsize[n] = sizeof(data[][n]).
211 * @spmin Array that will contain min values for current activity.
212 * @spmax Array that will contain max values for current activity.
215 * Pointer on array of arrays of chars that will contain the graphs data.
217 * NB: @min and @max arrays contain values in the same order as the fields
218 * in the statistics structure.
219 ***************************************************************************
221 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
228 * Allocate an array of pointers. Each of these pointers will
229 * be an array of chars.
231 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
235 /* Allocate array that will contain the size of each array of chars */
236 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
240 /* Allocate array that will contain the min value of each graph */
241 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
245 /* Allocate array that will contain the max value of each graph */
246 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
250 /* Allocate arrays of chars that will contain graphs data */
251 for (i = 0; i < n; i++) {
252 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
257 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
258 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
259 *(*spmin + i) = DBL_MAX; /* Init min and max values */
260 *(*spmax + i) = -DBL_MAX;
267 ***************************************************************************
268 * Save SVG code for current graph.
271 * @data SVG code to append to current graph definition.
272 * @out Pointer on array of chars for current graph definition.
273 * @outsize Size of array of chars for current graph definition.
276 * @out Pointer on array of chars for current graph definition that
277 * has been updated with the addition of current sample data.
278 * @outsize Array that containing the (possibly new) sizes of each
279 * element in array of chars.
280 ***************************************************************************
282 void save_svg_data(char *data, char **out, int *outsize)
288 /* Determine space left in array */
289 len = *outsize - strlen(out_p) - 1;
290 if (strlen(data) >= len) {
292 * If current array of chars doesn't have enough space left
293 * then reallocate it with CHUNKSIZE more bytes.
295 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
297 *outsize += CHUNKSIZE;
300 strncat(out_p, data, len);
304 ***************************************************************************
305 * Update line graph definition by appending current X,Y coordinates.
308 * @timetag Timestamp in seconds since the epoch for current sample
309 * stats. Will be used as X coordinate.
310 * @value Value of current sample metric. Will be used as Y coordinate.
311 * @out Pointer on array of chars for current graph definition.
312 * @outsize Size of array of chars for current graph definition.
313 * @restart Set to TRUE if a RESTART record has been read since the last
317 * @out Pointer on array of chars for current graph definition that
318 * has been updated with the addition of current sample data.
319 * @outsize Array that containing the (possibly new) sizes of each
320 * element in array of chars.
321 ***************************************************************************
323 void lnappend(unsigned long timetag, double value, char **out, int *outsize, int restart)
327 /* Prepare additional graph definition data */
328 snprintf(data, 128, " %c%lu,%.2f", restart ? 'M' : 'L', timetag, value);
331 save_svg_data(data, out, outsize);
335 ***************************************************************************
336 * Update line graph definition by appending current X,Y coordinates. Use
337 * (unsigned long) integer values here.
340 * @timetag Timestamp in seconds since the epoch for current sample
341 * stats. Will be used as X coordinate.
342 * @value Value of current sample metric. Will be used as Y coordinate.
343 * @out Pointer on array of chars for current graph definition.
344 * @outsize Size of array of chars for current graph definition.
345 * @restart Set to TRUE if a RESTART record has been read since the last
349 * @out Pointer on array of chars for current graph definition that
350 * has been updated with the addition of current sample data.
351 * @outsize Array that containing the (possibly new) sizes of each
352 * element in array of chars.
353 ***************************************************************************
355 void lniappend(unsigned long timetag, unsigned long value, char **out, int *outsize,
360 /* Prepare additional graph definition data */
361 snprintf(data, 128, " %c%lu,%lu", restart ? 'M' : 'L', timetag, value);
364 save_svg_data(data, out, outsize);
368 ***************************************************************************
369 * Update bar graph definition by adding a new rectangle.
372 * @timetag Timestamp in seconds since the epoch for current sample
373 * stats. Will be used as X coordinate.
374 * @value Value of current sample metric. Will be used as rectangle
376 * @offset Offset for Y coordinate.
377 * @out Pointer on array of chars for current graph definition.
378 * @outsize Size of array of chars for current graph definition.
379 * @dt Interval of time in seconds between current and previous
383 * @out Pointer on array of chars for current graph definition that
384 * has been updated with the addition of current sample data.
385 * @outsize Array that containing the (possibly new) sizes of each
386 * element in array of chars.
387 ***************************************************************************
389 void brappend(unsigned long timetag, double offset, double value, char **out, int *outsize,
394 /* Prepare additional graph definition data */
395 if ((value == 0.0) || (dt == 0))
396 /* Dont draw a flat rectangle! */
399 snprintf(data, 128, "<rect x=\"%lu\" y=\"%.2f\" height=\"%.2f\" width=\"%lu\"/>",
400 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
403 save_svg_data(data, out, outsize);
408 ***************************************************************************
409 * Update CPU graph and min/max values for each metric.
412 * @timetag Timestamp in seconds since the epoch for current sample
413 * stats. Will be used as X coordinate.
414 * @offset Offset for Y coordinate.
415 * @value Value of current CPU metric. Will be used as rectangle
417 * @out Pointer on array of chars for current graph definition.
418 * @outsize Size of array of chars for current graph definition.
419 * @dt Interval of time in seconds between current and previous
421 * @spmin Min value already found for this CPU metric.
422 * @spmax Max value already found for this CPU metric.
425 * @offset New offset value, to use to draw next rectangle
426 * @out Pointer on array of chars for current graph definition that
427 * has been updated with the addition of current sample data.
428 * @outsize Array that containing the (possibly new) sizes of each
429 * element in array of chars.
430 ***************************************************************************
432 void cpuappend(unsigned long timetag, double *offset, double value, char **out, int *outsize,
433 unsigned long dt, double *spmin, double *spmax)
435 /* Save min and max values */
436 if (value < *spmin) {
439 if (value > *spmax) {
442 /* Prepare additional graph definition data */
443 brappend(timetag, *offset, value, out, outsize, dt);
449 ***************************************************************************
450 * Update rectangular graph and min/max values.
453 * @timetag Timestamp in seconds since the epoch for current sample
454 * stats. Will be used as X coordinate.
455 * @p_value Metric value for previous sample
456 * @value Metric value for current sample.
457 * @out Pointer on array of chars for current graph definition.
458 * @outsize Size of array of chars for current graph definition.
459 * @restart Set to TRUE if a RESTART record has been read since the last
461 * @dt Interval of time in seconds between current and previous
463 * @spmin Min value already found for this metric.
464 * @spmax Max value already found for this metric.
467 * @out Pointer on array of chars for current graph definition that
468 * has been updated with the addition of current sample data.
469 * @outsize Array that containing the (possibly new) sizes of each
470 * element in array of chars.
471 * @spmin Min value for this metric.
472 * @spmax Max value for this metric.
473 ***************************************************************************
475 void recappend(unsigned long timetag, double p_value, double value, char **out, int *outsize,
476 int restart, unsigned long dt, double *spmin, double *spmax)
478 char data[128], data1[128], data2[128];
480 /* Save min and max values */
481 if (value < *spmin) {
484 if (value > *spmax) {
487 /* Prepare additional graph definition data */
489 snprintf(data1, 128, " M%lu,%.2f", timetag - dt, p_value);
492 if (p_value != value) {
493 snprintf(data2, 128, " L%lu,%.2f", timetag, value);
496 snprintf(data, 128, "%s L%lu,%.2f%s", restart ? data1 : "", timetag, p_value,
497 p_value != value ? data2 : "");
500 save_svg_data(data, out, outsize);
504 ***************************************************************************
505 * Calculate 10 raised to the power of n.
508 * @n Power number to use.
511 * 10 raised to the power of n.
512 ***************************************************************************
514 unsigned int pwr10(int n)
519 for (i = 0; i < n; i++) {
527 ***************************************************************************
528 * Autoscale graphs of a given view.
531 * @asf_nr (Maximum) number of autoscale factors.
532 * @group Number of graphs in current view.
533 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
534 * @pos Position in array for the first graph in view.
535 * @gmax Global max value for all graphs in view.
536 * @spmax Array containing max values for graphs.
539 * @asfactor Autoscale factors (one for each graph).
540 ***************************************************************************
542 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
543 double gmax, double *spmax)
548 for (j = 0; j < asf_nr; j++) {
549 /* Init autoscale factors */
553 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
555 for (j = 0; (j < group) && (j < asf_nr); j++) {
556 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
559 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
560 if (strlen(val) > 0) {
561 asfactor[j] = pwr10(strlen(val) - 1);
568 ***************************************************************************
569 * Display background grid (horizontal lines) and corresponding graduations.
572 * @ypos Gap between two horizontal lines.
573 * @yfactor Scaling factor on Y axis.
574 * @lmax Max value for current view.
575 * @dp Number of decimal places for graduations.
576 ***************************************************************************
578 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
584 /* Display horizontal lines (except on X axis) */
586 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
587 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
588 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
592 * Display graduations.
593 * Use same rounded value for graduation numbers as for grid lines
594 * to make sure they are properly aligned.
596 sprintf(stmp, "%.2f", ypos * j);
597 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
598 "text-anchor: end\">%.*f.</text>\n",
599 (long) (atof(stmp) * yfactor), dp, ypos * j);
602 while (ypos * j <= lmax);
606 ***************************************************************************
607 * Display background grid (vertical lines) and corresponding graduations.
610 * @xpos Gap between two vertical lines.
611 * @xfactor Scaling factor on X axis.
612 * @v_gridnr Number of vertical lines to display.
613 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
614 ***************************************************************************
616 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
618 struct record_header stamp;
623 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
625 for (j = 0; (j <= v_gridnr) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
627 /* Display vertical lines */
628 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
629 set_record_timestamp_string(flags, &stamp, NULL, cur_time, 32, &rectime);
630 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
631 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
632 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
634 * Display graduations.
635 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
636 * In this case, we should rather display the exact time instead of only the hour.
638 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
639 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
640 "text-anchor: start\">%2dH</text>\n",
641 (long) (xpos * j * xfactor) - 8, rectime.tm_hour);
644 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
645 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
646 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
648 stamp.ust_time += xpos;
651 if (!PRINT_LOCAL_TIME(flags)) {
652 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
653 "text-anchor: end\">UTC</text>\n");
658 ***************************************************************************
659 * Calculate the value on the Y axis between two horizontal lines that will
660 * make the graph background grid.
663 * @lmax Max value reached for this graph.
666 * @dp Number of decimal places for Y graduations.
669 * Value between two horizontal lines.
670 ***************************************************************************
672 double ygrid(double lmax, int *dp)
683 n = (long) (lmax / SVG_H_GRIDNR);
686 return (lmax / SVG_H_GRIDNR);
688 snprintf(val, 32, "%ld", n);
695 return ((double) (((long) (n / e)) * e));
699 ***************************************************************************
700 * Calculate the value on the X axis between two vertical lines that will
701 * make the graph background grid.
704 * @timestart First data timestamp (X coordinate of the first data point).
705 * @timeend Last data timestamp (X coordinate of the last data point).
706 * @v_gridnr Number of vertical lines to display. Its value is normally
707 * SVG_V_GRIDNR, except when option "oneday" is used, in which
708 * case it is set to 12.
711 * Value between two vertical lines.
712 ***************************************************************************
714 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
716 if ((timeend - timestart) <= v_gridnr)
719 return ((timeend - timestart) / v_gridnr);
723 ***************************************************************************
724 * Free global graphs structures.
727 * @out Pointer on array of chars for each graph definition.
728 * @outsize Size of array of chars for each graph definition.
729 * @spmin Array containing min values for graphs.
730 * @spmax Array containing max values for graphs.
731 ***************************************************************************
733 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
750 ***************************************************************************
751 * Skip current view where all graphs have only zero values. This function
752 * is called when option "skipempty" has been used, or when "No data" have
753 * been found for current view.
756 * @out Pointer on array of chars for each graph definition.
757 * @pos Position of current view in the array of graphs definitions.
758 * @group Number of graphs in current view.
761 * @pos Position of next view in the array of graphs definitions.
762 ***************************************************************************
764 void skip_current_view(char **out, int *pos, int group)
769 for (j = 0; j < group; j++) {
770 out_p = *(out + *pos + j);
772 /* Even if not displayed, current graph data have to be freed */
780 ***************************************************************************
781 * Display all graphs for current activity.
784 * @g_nr Number of sets of graphs (views) to display.
785 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
786 * @title Titles for each set of graphs.
787 * @g_title Titles for each graph.
788 * @item_name Item (network interface, etc.) name.
789 * @group Indicate how graphs are grouped together to make sets.
790 * @spmin Array containing min values for graphs.
791 * @spmax Array containing max values for graphs.
792 * @out Pointer on array of chars for each graph definition.
793 * @outsize Size of array of chars for each graph definition.
794 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
795 * time for the first sample of stats (.@ust_time_first), and
796 * times used as start and end values on the X axis
797 * (.@ust_time_ref and .@ust_time_end).
798 * @record_hdr Pointer on record header of current stats sample.
799 ***************************************************************************
801 void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
802 int group[], double *spmin, double *spmax, char **out, int *outsize,
803 struct svg_parm *svg_p, struct record_header *record_hdr)
806 int i, j, dp, pos = 0, views_nr = 0;
808 unsigned int asfactor[16];
810 double lmax, xfactor, yfactor, ypos, gmin, gmax;
813 /* Translate to proper position for current activity */
814 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
816 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
818 /* For each set of graphs which are part of current activity */
819 for (i = 0; i < g_nr; i++) {
821 /* Get global min and max value for current set of graphs */
822 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
824 /* Don't display empty views if requested */
825 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
826 skip_current_view(out, &pos, group[i]);
829 /* Increment number of views actually displayed */
832 /* Graph background */
833 printf("<rect x=\"0\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
834 (views_nr - 1) * SVG_T_YSIZE,
835 SVG_V_YSIZE, SVG_V_XSIZE);
838 printf("<text x=\"0\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
839 20 + (views_nr - 1) * SVG_T_YSIZE, title[i]);
841 printf(" [%s]", item_name);
844 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
845 "(Min, Max values)</tspan>\n</text>\n",
846 5 + SVG_M_XSIZE + SVG_G_XSIZE,
847 25 + (views_nr - 1) * SVG_T_YSIZE);
850 * At least two samples are needed.
851 * And a min and max value should have been found.
853 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
854 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
856 printf("<text x=\"0\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
857 SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
858 skip_current_view(out, &pos, group[i]);
863 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
864 SVG_M_XSIZE, SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE,
865 SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE,
866 SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
868 /* Autoscaling graphs if needed */
869 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
872 for (j = 0; j < group[i]; j++) {
873 /* Set dp to TRUE (1) if current metric is based on integer values */
874 dp = (g_title[pos + j][0] == '~');
875 snprintf(val, 32, "x%u ", asfactor[j]);
876 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
877 "%s %s(%.*f, %.*f)</text>\n",
878 5 + SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE + j * 15,
879 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
880 asfactor[j] == 1 ? "" : val,
881 !dp * 2, *(spmin + pos + j) * asfactor[j],
882 !dp * 2, *(spmax + pos + j) * asfactor[j]);
885 /* Translate to proper position for current graph within current activity */
886 printf("<g transform=\"translate(%d,%d)\">\n",
887 SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
890 if (g_type[i] == SVG_LINE_GRAPH) {
891 /* For line graphs */
893 /* If all values are zero then set current max value to 1 */
899 /* Max value cannot be too small, else Y graduations will be meaningless */
900 if (lmax < SVG_H_GRIDNR * 0.01) {
901 lmax = SVG_H_GRIDNR * 0.01;
903 ypos = ygrid(lmax, &dp);
906 /* For bar graphs (used for %values) */
907 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
908 dp = 0; /* No decimals */
910 /* Max should be always 100% except for percentage values greater than 100% */
918 yfactor = (double) -SVG_G_YSIZE / lmax;
920 /* Display horizontal lines and graduations */
921 display_hgrid(ypos, yfactor, lmax, dp);
923 /* Set number of vertical lines to 12 when option "oneday" is used */
924 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
926 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
927 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
929 /* Display vertical lines and graduations */
930 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
932 /* Draw current graphs set */
933 for (j = 0; j < group[i]; j++) {
934 out_p = *(out + pos + j);
935 if (g_type[i] == SVG_LINE_GRAPH) {
937 printf("<path id=\"g%dp%d\" d=\"%s\" "
938 "style=\"vector-effect: non-scaling-stroke; "
939 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
940 "transform=\"scale(%f,%f)\"/>\n",
941 svg_p->graph_no, pos + j, out_p,
942 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
944 yfactor * asfactor[j]);
946 else if (*out_p) { /* Ignore flat bars */
948 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
949 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
950 printf("%s\n", out_p);
961 (svg_p->graph_no) += views_nr;
965 ***************************************************************************
966 * Display CPU statistics in SVG.
969 * @a Activity structure with statistics.
970 * @curr Index in array for current sample statistics.
971 * @action Action expected from current function.
972 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
973 * flag indicating that a restart record has been previously
974 * found (.@restart), and time used for the X axis origin
976 * @itv Interval of time in jiffies (only with F_MAIN action).
977 * @record_hdr Pointer on record header of current stats sample.
978 ***************************************************************************
980 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
981 unsigned long long g_itv, struct record_header *record_hdr)
983 struct stats_cpu *scc, *scp;
986 int g_type[] = {SVG_BAR_GRAPH};
987 char *title[] = {"CPU load"};
988 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
989 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
990 static double *spmin, *spmax;
995 int i, j, k, pos, cpu_offline;
997 if (action & F_BEGIN) {
999 * Allocate arrays that will contain the graphs data
1000 * and the min/max values.
1002 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
1005 if (action & F_MAIN) {
1007 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1009 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1010 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1012 /* Should current CPU (including CPU "all") be displayed? */
1013 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1020 if (i) { /* Don't test CPU "all" here */
1022 * If the CPU is offline then it is omited from /proc/stat:
1023 * All the fields couldn't have been read and the sum of them is zero.
1024 * (Remember that guest/guest_nice times are already included in
1027 if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys +
1028 scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal +
1029 scc->cpu_hardirq + scc->cpu_softirq) == 0) {
1031 * Set current struct fields (which have been set to zero)
1032 * to values from previous iteration. Hence their values won't
1033 * jump from zero when the CPU comes back online.
1042 * Recalculate interval for current proc.
1043 * If result is 0 then current CPU is a tickless one.
1045 g_itv = get_per_cpu_interval(scc, scp);
1046 cpu_offline = FALSE;
1049 if (!g_itv) { /* Current CPU is offline or tickless */
1051 val = (cpu_offline ? 0.0 /* Offline CPU: %idle = 0% */
1052 : 100.0); /* Tickless CPU: %idle = 100% */
1054 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1057 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1061 /* Check min/max values for %user, etc. */
1062 for (k = 0; k < j; k++) {
1063 if (0.0 < *(spmin + pos + k)) {
1064 *(spmin + pos + k) = 0.0;
1066 if (0.0 > *(spmax + pos + k)) {
1067 *(spmax + pos + k) = 0.0;
1072 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1074 out + pos + j, outsize + pos + j, svg_p->dt,
1075 spmin + pos + j, spmax + pos + j);
1080 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1082 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1083 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv),
1084 out + pos, outsize + pos, svg_p->dt,
1085 spmin + pos, spmax + pos);
1089 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1091 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1093 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1094 scc->cpu_user - scc->cpu_guest, g_itv),
1095 out + pos, outsize + pos, svg_p->dt,
1096 spmin + pos, spmax + pos);
1099 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1101 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1102 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv),
1103 out + pos + 1, outsize + pos + 1, svg_p->dt,
1104 spmin + pos + 1, spmax + pos + 1);
1108 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1110 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1112 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1113 scc->cpu_nice - scc->cpu_guest_nice, g_itv),
1114 out + pos + 1, outsize + pos + 1, svg_p->dt,
1115 spmin + pos + 1, spmax + pos + 1);
1118 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1120 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1122 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1123 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1125 out + pos + 2, outsize + pos + 2, svg_p->dt,
1126 spmin + pos + 2, spmax + pos + 2);
1130 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1131 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv),
1132 out + pos + 2, outsize + pos + 2, svg_p->dt,
1133 spmin + pos + 2, spmax + pos + 2);
1137 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1138 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
1139 out + pos + 3, outsize + pos + 3, svg_p->dt,
1140 spmin + pos + 3, spmax + pos + 3);
1142 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1143 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
1144 out + pos + 4, outsize + pos + 4, svg_p->dt,
1145 spmin + pos + 4, spmax + pos + 4);
1147 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1149 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1150 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv),
1151 out + pos + 5, outsize + pos + 5, svg_p->dt,
1152 spmin + pos + 5, spmax + pos + 5);
1154 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1155 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv),
1156 out + pos + 6, outsize + pos + 6, svg_p->dt,
1157 spmin + pos + 6, spmax + pos + 6);
1159 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1160 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv),
1161 out + pos + 7, outsize + pos + 7, svg_p->dt,
1162 spmin + pos + 7, spmax + pos + 7);
1164 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1165 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, g_itv),
1166 out + pos + 8, outsize + pos + 8, svg_p->dt,
1167 spmin + pos + 8, spmax + pos + 8);
1176 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1178 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1179 ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv)),
1180 out + pos + j, outsize + pos + j, svg_p->dt,
1181 spmin + pos + j, spmax + pos + j);
1185 if (action & F_END) {
1186 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1188 /* Should current CPU (including CPU "all") be displayed? */
1189 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1195 /* This is CPU "all" */
1196 strcpy(item_name, "all");
1199 sprintf(item_name, "%d", i - 1);
1202 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1203 draw_activity_graphs(a->g_nr, g_type,
1204 title, g_title1, item_name, group1,
1205 spmin + pos, spmax + pos, out + pos, outsize + pos,
1209 draw_activity_graphs(a->g_nr, g_type,
1210 title, g_title2, item_name, group2,
1211 spmin + pos, spmax + pos, out + pos, outsize + pos,
1216 /* Free remaining structures */
1217 free_graphs(out, outsize, spmin, spmax);
1222 ***************************************************************************
1223 * Display task creation and context switch statistics in SVG.
1226 * @a Activity structure with statistics.
1227 * @curr Index in array for current sample statistics.
1228 * @action Action expected from current function.
1229 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1230 * flag indicating that a restart record has been previously
1231 * found (.@restart) and time used for the X axis origin
1233 * @itv Interval of time in jiffies (only with F_MAIN action).
1234 * @record_hdr Pointer on record header of current stats sample.
1235 ***************************************************************************
1237 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1238 unsigned long long itv, struct record_header *record_hdr)
1241 *spc = (struct stats_pcsw *) a->buf[curr],
1242 *spp = (struct stats_pcsw *) a->buf[!curr];
1243 int group[] = {1, 1};
1244 int g_fields[] = {1, 0};
1245 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1246 char *title[] = {"Task creation", "Switching activity"};
1247 char *g_title[] = {"proc/s",
1249 static double *spmin, *spmax;
1251 static int *outsize;
1253 if (action & F_BEGIN) {
1255 * Allocate arrays that will contain the graphs data
1256 * and the min/max values.
1258 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1261 if (action & F_MAIN) {
1262 /* Check for min/max values */
1263 save_extrema(1, 1, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1264 itv, spmin, spmax, g_fields);
1266 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1267 S_VALUE(spp->processes, spc->processes, itv),
1268 out, outsize, svg_p->restart);
1270 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1271 S_VALUE(spp->context_switch, spc->context_switch, itv),
1272 out + 1, outsize + 1, svg_p->restart);
1275 if (action & F_END) {
1276 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1277 spmin, spmax, out, outsize, svg_p, record_hdr);
1279 /* Free remaining structures */
1280 free_graphs(out, outsize, spmin, spmax);
1285 ***************************************************************************
1286 * Display swap statistics in SVG.
1289 * @a Activity structure with statistics.
1290 * @curr Index in array for current sample statistics.
1291 * @action Action expected from current function.
1292 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1293 * flag indicating that a restart record has been previously
1294 * found (.@restart) and time used for the X axis origin
1296 * @itv Interval of time in jiffies (only with F_MAIN action).
1297 * @record_hdr Pointer on record header of current stats sample.
1298 ***************************************************************************
1300 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1301 unsigned long long itv, struct record_header *record_hdr)
1304 *ssc = (struct stats_swap *) a->buf[curr],
1305 *ssp = (struct stats_swap *) a->buf[!curr];
1307 int g_type[] = {SVG_LINE_GRAPH};
1308 char *title[] = {"Swap activity"};
1309 char *g_title[] = {"pswpin/s", "pswpout/s" };
1310 int g_fields[] = {0, 1};
1311 static double *spmin, *spmax;
1313 static int *outsize;
1315 if (action & F_BEGIN) {
1317 * Allocate arrays that will contain the graphs data
1318 * and the min/max values.
1320 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1323 if (action & F_MAIN) {
1324 /* Check for min/max values */
1325 save_extrema(0, 2, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1326 itv, spmin, spmax, g_fields);
1328 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1329 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1330 out, outsize, svg_p->restart);
1332 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1333 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1334 out + 1, outsize + 1, svg_p->restart);
1337 if (action & F_END) {
1338 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1339 spmin, spmax, out, outsize, svg_p, record_hdr);
1341 /* Free remaining structures */
1342 free_graphs(out, outsize, spmin, spmax);
1347 ***************************************************************************
1348 * Display paging statistics in SVG.
1351 * @a Activity structure with statistics.
1352 * @curr Index in array for current sample statistics.
1353 * @action Action expected from current function.
1354 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1355 * flag indicating that a restart record has been previously
1356 * found (.@restart) and time used for the X axis origin
1358 * @itv Interval of time in jiffies (only with F_MAIN action).
1359 * @record_hdr Pointer on record header of current stats sample.
1360 ***************************************************************************
1362 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1363 unsigned long long itv, struct record_header *record_hdr)
1366 *spc = (struct stats_paging *) a->buf[curr],
1367 *spp = (struct stats_paging *) a->buf[!curr];
1368 int group[] = {2, 2, 4};
1369 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1370 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1371 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1372 "fault/s", "majflt/s",
1373 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1374 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1375 static double *spmin, *spmax;
1377 static int *outsize;
1379 if (action & F_BEGIN) {
1381 * Allocate arrays that will contain the graphs data
1382 * and the min/max values.
1384 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1387 if (action & F_MAIN) {
1388 /* Check for min/max values */
1389 save_extrema(0, 8, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1390 itv, spmin, spmax, g_fields);
1392 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1393 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1394 out, outsize, svg_p->restart);
1396 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1397 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1398 out + 1, outsize + 1, svg_p->restart);
1400 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1401 S_VALUE(spp->pgfault, spc->pgfault, itv),
1402 out + 2, outsize + 2, svg_p->restart);
1404 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1405 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1406 out + 3, outsize + 3, svg_p->restart);
1408 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1409 S_VALUE(spp->pgfree, spc->pgfree, itv),
1410 out + 4, outsize + 4, svg_p->restart);
1412 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1413 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1414 out + 5, outsize + 5, svg_p->restart);
1416 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1417 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1418 out + 6, outsize + 6, svg_p->restart);
1420 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1421 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1422 out + 7, outsize + 7, svg_p->restart);
1425 if (action & F_END) {
1426 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1427 spmin, spmax, out, outsize, svg_p, record_hdr);
1429 /* Free remaining structures */
1430 free_graphs(out, outsize, spmin, spmax);
1435 ***************************************************************************
1436 * Display I/O and transfer rate statistics in SVG.
1439 * @a Activity structure with statistics.
1440 * @curr Index in array for current sample statistics.
1441 * @action Action expected from current function.
1442 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1443 * flag indicating that a restart record has been previously
1444 * found (.@restart) and time used for the X axis origin
1446 * @itv Interval of time in jiffies (only with F_MAIN action).
1447 * @record_hdr Pointer on record header of current stats sample.
1448 ***************************************************************************
1450 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1451 unsigned long long itv, struct record_header *record_hdr)
1454 *sic = (struct stats_io *) a->buf[curr],
1455 *sip = (struct stats_io *) a->buf[!curr];
1456 int group[] = {3, 2};
1457 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1458 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1459 char *g_title[] = {"tps", "rtps", "wtps",
1460 "bread/s", "bwrtn/s"};
1461 int g_fields[] = {0, 1, 2, 3, 4};
1462 static double *spmin, *spmax;
1464 static int *outsize;
1466 if (action & F_BEGIN) {
1468 * Allocate arrays that will contain the graphs data
1469 * and the min/max values.
1471 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1474 if (action & F_MAIN) {
1475 /* Check for min/max values */
1476 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1477 itv, spmin, spmax, g_fields);
1480 * If we get negative values, this is probably because
1481 * one or more devices/filesystems have been unmounted.
1482 * We display 0.0 in this case though we should rather tell
1483 * the user that the value cannot be calculated here.
1486 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1487 sic->dk_drive < sip->dk_drive ? 0.0 :
1488 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1489 out, outsize, svg_p->restart);
1491 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1492 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1493 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1494 out + 1, outsize + 1, svg_p->restart);
1496 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1497 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1498 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1499 out + 2, outsize + 2, svg_p->restart);
1501 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1502 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1503 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1504 out + 3, outsize + 3, svg_p->restart);
1506 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1507 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1508 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1509 out + 4, outsize + 4, svg_p->restart);
1512 if (action & F_END) {
1513 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1514 spmin, spmax, out, outsize, svg_p, record_hdr);
1516 /* Free remaining structures */
1517 free_graphs(out, outsize, spmin, spmax);
1522 ***************************************************************************
1523 * Display memory statistics in SVG.
1526 * @a Activity structure with statistics.
1527 * @curr Index in array for current sample statistics.
1528 * @action Action expected from current function.
1529 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1530 * flag indicating that a restart record has been previously
1531 * found (.@restart) and time used for the X axis origin
1533 * @itv Interval of time in jiffies (only with F_MAIN action).
1534 * @record_hdr Pointer on record header of current stats sample.
1535 ***************************************************************************
1537 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1538 unsigned long long itv, struct record_header *record_hdr)
1541 *smc = (struct stats_memory *) a->buf[curr];
1542 int group1[] = {2, 1, 3, 1, 3, 5};
1543 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1544 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1545 int group2[] = {3, 1, 1};
1546 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1547 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1548 "Memory utilization (3)", "Memory utilization (4)",
1549 "Memory utilization (5)", "Memory utilization (6)"};
1550 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1551 "Swap utilization (3)"};
1552 char *g_title1[] = {"MBmemfree", "MBmemused", "%memused", "MBbuffers",
1553 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1554 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1556 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1558 int g_fields[] = {0, 3, 4, 20, 15, 21, 17, 5, 7, 8, 9, 10, 11, 12, 13, 14};
1559 static double *spmin, *spmax;
1561 static int *outsize;
1565 if (action & F_BEGIN) {
1567 * Allocate arrays that will contain the graphs data
1568 * and the min/max values.
1570 out = allocate_graph_lines(22, &outsize, &spmin, &spmax);
1573 if (action & F_MAIN) {
1574 /* Check for min/max values */
1575 save_extrema(0, 16, 0, (void *) a->buf[curr], NULL,
1576 itv, spmin, spmax, g_fields);
1577 /* Compute %memused min/max values */
1578 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1579 if (tval > *(spmax + 2)) {
1580 *(spmax + 2) = tval;
1582 if (tval < *(spmin + 2)) {
1583 *(spmin + 2) = tval;
1585 /* Compute %commit min/max values */
1586 tval = (smc->tlmkb + smc->tlskb) ?
1587 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1588 if (tval > *(spmax + 6)) {
1589 *(spmax + 6) = tval;
1591 if (tval < *(spmin + 6)) {
1592 *(spmin + 6) = tval;
1594 /* Compute %swpused min/max values */
1596 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1597 if (tval > *(spmax + 18)) {
1598 *(spmax + 18) = tval;
1600 if (tval < *(spmin + 18)) {
1601 *(spmin + 18) = tval;
1603 /* Compute %swpcad min/max values */
1604 tval = (smc->tlskb - smc->frskb) ?
1605 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1606 if (tval > *(spmax + 19)) {
1607 *(spmax + 19) = tval;
1609 if (tval < *(spmin + 19)) {
1610 *(spmin + 19) = tval;
1612 /* Compute memused min/max values in MB */
1613 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1614 if (tval > *(spmax + 1)) {
1615 *(spmax + 1) = tval;
1617 if (tval < *(spmin + 1)) {
1618 *(spmin + 1) = tval;
1620 /* Compute swpused min/max values in MB */
1621 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1622 if (tval > *(spmax + 16)) {
1623 *(spmax + 16) = tval;
1625 if (tval < *(spmin + 16)) {
1626 *(spmin + 16) = tval;
1630 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1631 ((double) smc->frmkb) / 1024,
1632 out, outsize, svg_p->restart);
1634 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1635 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1636 out + 1, outsize + 1, svg_p->restart);
1638 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1639 ((double) smc->bufkb) / 1024,
1640 out + 3, outsize + 3, svg_p->restart);
1642 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1643 ((double) smc->camkb) / 1024,
1644 out + 4, outsize + 4, svg_p->restart);
1646 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1647 ((double) smc->frskb) / 1024,
1648 out + 15, outsize + 15, svg_p->restart);
1650 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1651 ((double) (smc->tlskb - smc->frskb)) / 1024,
1652 out + 16, outsize + 16, svg_p->restart);
1654 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1655 ((double) smc->caskb) / 1024,
1656 out + 17, outsize + 17, svg_p->restart);
1658 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1659 ((double) smc->comkb) / 1024,
1660 out + 5, outsize + 5, svg_p->restart);
1662 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1663 ((double) smc->activekb) / 1024,
1664 out + 7, outsize + 7, svg_p->restart);
1666 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1667 ((double) smc->inactkb) / 1024,
1668 out + 8, outsize + 8, svg_p->restart);
1670 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1671 ((double) smc->dirtykb) / 1024,
1672 out + 9, outsize + 9, svg_p->restart);
1674 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1675 ((double) smc->anonpgkb) / 1024,
1676 out + 10, outsize + 10, svg_p->restart);
1678 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1679 ((double) smc->slabkb) / 1024,
1680 out + 11, outsize + 11, svg_p->restart);
1682 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1683 ((double) smc->kstackkb) / 1024,
1684 out + 12, outsize + 12, svg_p->restart);
1686 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1687 ((double) smc->pgtblkb) / 1024,
1688 out + 13, outsize + 13, svg_p->restart);
1690 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1691 ((double) smc->vmusedkb) / 1024,
1692 out + 14, outsize + 14, svg_p->restart);
1694 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1697 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1698 out + 2, outsize + 2, svg_p->dt);
1700 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1702 (smc->tlmkb + smc->tlskb) ?
1703 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1704 out + 6, outsize + 6, svg_p->dt);
1706 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1709 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1710 out + 18, outsize + 18, svg_p->dt);
1712 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1714 (smc->tlskb - smc->frskb) ?
1715 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1716 out + 19, outsize + 19, svg_p->dt);
1719 if (action & F_END) {
1721 /* Conversion kB -> MB */
1722 for (i = 0; i < 16; i++) {
1723 *(spmin + g_fields[i]) /= 1024;
1724 *(spmax + g_fields[i]) /= 1024;
1727 if (DISPLAY_MEM_AMT(a->opt_flags)) {
1728 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1729 g_type1, title1, g_title1, NULL, group1,
1730 spmin, spmax, out, outsize, svg_p, record_hdr);
1733 if (DISPLAY_SWAP(a->opt_flags)) {
1734 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1735 spmin + 15, spmax + 15, out + 15, outsize + 15,
1739 /* Free remaining structures */
1740 free_graphs(out, outsize, spmin, spmax);
1745 ***************************************************************************
1746 * Display kernel tables statistics in SVG.
1749 * @a Activity structure with statistics.
1750 * @curr Index in array for current sample statistics.
1751 * @action Action expected from current function.
1752 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1753 * flag indicating that a restart record has been previously
1754 * found (.@restart) and time used for the X axis origin
1756 * @itv Interval of time in jiffies (only with F_MAIN action).
1757 * @record_hdr Pointer on record header of current stats sample.
1758 ***************************************************************************
1760 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1761 unsigned long long itv, struct record_header *record_hdr)
1763 struct stats_ktables
1764 *skc = (struct stats_ktables *) a->buf[curr];
1765 int group[] = {3, 1};
1766 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1767 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1768 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1770 int g_fields[] = {1, 2, 0, 3};
1771 static double *spmin, *spmax;
1773 static int *outsize;
1775 if (action & F_BEGIN) {
1777 * Allocate arrays that will contain the graphs data
1778 * and the min/max values.
1780 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1783 if (action & F_MAIN) {
1784 /* Check for min/max values */
1785 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
1786 itv, spmin, spmax, g_fields);
1788 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1789 (unsigned long) skc->dentry_stat,
1790 out, outsize, svg_p->restart);
1792 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1793 (unsigned long) skc->file_used,
1794 out + 1, outsize + 1, svg_p->restart);
1796 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1797 (unsigned long) skc->inode_used,
1798 out + 2, outsize + 2, svg_p->restart);
1800 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1801 (unsigned long) skc->pty_nr,
1802 out + 3, outsize + 3, svg_p->restart);
1805 if (action & F_END) {
1806 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1807 spmin, spmax, out, outsize, svg_p, record_hdr);
1809 /* Free remaining structures */
1810 free_graphs(out, outsize, spmin, spmax);
1815 ***************************************************************************
1816 * Display queue and load statistics in SVG.
1819 * @a Activity structure with statistics.
1820 * @curr Index in array for current sample statistics.
1821 * @action Action expected from current function.
1822 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1823 * flag indicating that a restart record has been previously
1824 * found (.@restart) and time used for the X axis origin
1826 * @itv Interval of time in jiffies (only with F_MAIN action).
1827 * @record_hdr Pointer on record header of current stats sample.
1828 ***************************************************************************
1830 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1831 unsigned long long itv, struct record_header *record_hdr)
1834 *sqc = (struct stats_queue *) a->buf[curr];
1835 int group[] = {2, 1, 3};
1836 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1837 char *title[] = {"Queue length", "Task list", "Load average"};
1838 char *g_title[] = {"~runq-sz", "~blocked",
1840 "ldavg-1", "ldavg-5", "ldavg-15"};
1841 int g_fields[] = {0, 1, 3, 4, 5, 2};
1842 static double *spmin, *spmax;
1844 static int *outsize;
1846 if (action & F_BEGIN) {
1848 * Allocate arrays that will contain the graphs data
1849 * and the min/max values.
1851 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1854 if (action & F_MAIN) {
1855 /* Check for min/max values */
1856 save_extrema(0, 2, 4, (void *) a->buf[curr], NULL,
1857 itv, spmin, spmax, g_fields);
1859 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1860 (unsigned long) sqc->nr_running,
1861 out, outsize, svg_p->restart);
1863 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1864 (unsigned long) sqc->procs_blocked,
1865 out + 1, outsize + 1, svg_p->restart);
1867 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1868 (unsigned long) sqc->nr_threads,
1869 out + 2, outsize + 2, svg_p->restart);
1871 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1872 (double) sqc->load_avg_1 / 100,
1873 out + 3, outsize + 3, svg_p->restart);
1875 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1876 (double) sqc->load_avg_5 / 100,
1877 out + 4, outsize + 4, svg_p->restart);
1879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1880 (double) sqc->load_avg_15 / 100,
1881 out + 5, outsize + 5, svg_p->restart);
1884 if (action & F_END) {
1885 /* Fix min/max values for load average */
1886 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1887 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1888 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1890 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1891 spmin, spmax, out, outsize, svg_p, record_hdr);
1893 /* Free remaining structures */
1894 free_graphs(out, outsize, spmin, spmax);
1899 ***************************************************************************
1900 * Display disk statistics in SVG.
1903 * @a Activity structure with statistics.
1904 * @curr Index in array for current sample statistics.
1905 * @action Action expected from current function.
1906 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1907 * flag indicating that a restart record has been previously
1908 * found (.@restart) and time used for the X axis origin
1910 * @itv Interval of time in jiffies (only with F_MAIN action).
1911 * @record_hdr Pointer on record header of current stats sample.
1912 ***************************************************************************
1914 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1915 unsigned long long itv, struct record_header *record_hdr)
1917 struct stats_disk *sdc, *sdp;
1918 struct ext_disk_stats xds;
1919 int group[] = {1, 2, 2, 2, 1};
1920 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
1921 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
1922 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
1923 "Disk statistics (3)", "Disk statistics (4)",
1924 "Disk statistics (5)"};
1925 char *g_title[] = {"tps",
1926 "rd_sec/s", "wr_sec/s",
1927 "avgrq-sz", "avgqu-sz",
1930 int g_fields[] = {0, 1, 2};
1931 static double *spmin, *spmax;
1933 static int *outsize;
1934 char *item_name, *persist_dev_name;
1936 int i, j, k, pos, restart, *unregistered;
1938 if (action & F_BEGIN) {
1940 * Allocate arrays (#0..7) that will contain the graphs data
1941 * and the min/max values.
1942 * Also allocate one additional array (#8) for each disk device:
1943 * spmax + 8 will contain the device major number,
1944 * spmin + 8 will contain the device minor number,
1945 * outsize + 8 will contain a positive value (TRUE) if the device
1946 * has either still not been registered, or has been unregistered.
1948 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
1951 if (action & F_MAIN) {
1952 restart = svg_p->restart;
1954 * Mark previously registered devices as now
1955 * possibly unregistered for all graphs.
1957 for (k = 0; k < a->nr; k++) {
1958 unregistered = outsize + k * 9 + 8;
1959 if (*unregistered == FALSE) {
1960 *unregistered = MAYBE;
1964 /* For each device structure */
1965 for (i = 0; i < a->nr; i++) {
1966 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
1967 if (!(sdc->major + sdc->minor))
1968 /* Empty structure: Ignore it */
1971 /* Look for corresponding graph */
1972 for (k = 0; k < a->nr; k++) {
1973 if ((sdc->major == *(spmax + k * 9 + 8)) &&
1974 (sdc->minor == *(spmin + k * 9 + 8)))
1979 /* Graph not found: Look for first free entry */
1980 for (k = 0; k < a->nr; k++) {
1981 if (*(spmax + k * 9 + 8) == -DBL_MAX)
1985 /* No free graph entry: Graph for this item won't be drawn */
1989 unregistered = outsize + pos + 8;
1991 j = check_disk_reg(a, curr, !curr, i);
1992 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
1995 * If current device was marked as previously unregistered,
1996 * then set restart variable to TRUE so that the graph will be
1997 * discontinuous, and mark it as now registered.
1999 if (*unregistered == TRUE) {
2002 *unregistered = FALSE;
2004 if (*(spmax + pos + 8) == -DBL_MAX) {
2005 /* Save device major and minor numbers (if not already done) */
2006 *(spmax + pos + 8) = sdc->major;
2007 *(spmin + pos + 8) = sdc->minor;
2010 /* Check for min/max values */
2011 save_extrema(1, 2, 0, (void *) sdc, (void *) sdp,
2012 itv, spmin + pos, spmax + pos, g_fields);
2014 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2015 if (xds.arqsz < *(spmin + pos + 3)) {
2016 *(spmin + pos + 3) = xds.arqsz;
2018 if (xds.arqsz > *(spmax + pos + 3)) {
2019 *(spmax + pos + 3) = xds.arqsz;
2021 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2022 if (aqusz < *(spmin + pos + 4)) {
2023 *(spmin + pos + 4) = aqusz;
2025 if (aqusz > *(spmax + pos + 4)) {
2026 *(spmax + pos + 4) = aqusz;
2028 if (xds.await < *(spmin + pos + 5)) {
2029 *(spmin + pos + 5) = xds.await;
2031 if (xds.await > *(spmax + pos + 5)) {
2032 *(spmax + pos + 5) = xds.await;
2034 if (xds.svctm < *(spmin + pos + 6)) {
2035 *(spmin + pos + 6) = xds.svctm;
2037 if (xds.svctm > *(spmax + pos + 6)) {
2038 *(spmax + pos + 6) = xds.svctm;
2040 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2041 *(spmin + pos + 7) = xds.util / 10.0;
2043 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2044 *(spmax + pos + 7) = xds.util / 10.0;
2048 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2049 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2050 out + pos, outsize + pos, restart);
2052 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2053 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv),
2054 out + pos + 1, outsize + pos + 1, restart);
2056 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2057 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv),
2058 out + pos + 2, outsize + pos + 2, restart);
2060 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2062 out + pos + 3, outsize + pos + 3, restart);
2064 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2066 out + pos + 4, outsize + pos + 4, restart);
2068 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2070 out + pos + 5, outsize + pos + 5, restart);
2072 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2074 out + pos + 6, outsize + pos + 6, restart);
2076 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2077 0.0, xds.util / 10.0,
2078 out + pos + 7, outsize + pos + 7, svg_p->dt);
2081 /* Mark devices not seen here as now unregistered */
2082 for (k = 0; k < a->nr; k++) {
2083 unregistered = outsize + k * 9 + 8;
2084 if (*unregistered != FALSE) {
2085 *unregistered = TRUE;
2090 if (action & F_END) {
2091 for (i = 0; i < a->nr; i++) {
2092 /* Check if there is something to display */
2098 persist_dev_name = NULL;
2100 if (DISPLAY_PERSIST_NAME_S(flags)) {
2101 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2105 if (persist_dev_name) {
2106 item_name = persist_dev_name;
2109 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2110 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2114 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2115 USE_PRETTY_OPTION(flags));
2119 draw_activity_graphs(a->g_nr, g_type,
2120 title, g_title, item_name, group,
2121 spmin + pos, spmax + pos, out + pos, outsize + pos,
2125 /* Free remaining structures */
2126 free_graphs(out, outsize, spmin, spmax);
2131 ***************************************************************************
2132 * Display network interfaces statistics in SVG.
2135 * @a Activity structure with statistics.
2136 * @curr Index in array for current sample statistics.
2137 * @action Action expected from current function.
2138 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2139 * flag indicating that a restart record has been previously
2140 * found (.@restart) and time used for the X axis origin
2142 * @itv Interval of time in jiffies (only with F_MAIN action).
2143 * @record_hdr Pointer on record header of current stats sample.
2144 ***************************************************************************
2146 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2147 unsigned long long itv, struct record_header *record_hdr)
2149 struct stats_net_dev *sndc, *sndp;
2150 int group[] = {2, 2, 3, 1};
2151 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2153 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2154 "Network statistics (3)", "Network statistics (4)"};
2155 char *g_title[] = {"rxpck/s", "txpck/s",
2157 "rxcmp/s", "txcmp/s", "rxmcst/s",
2159 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2160 static double *spmin, *spmax;
2162 static int *outsize;
2164 double rxkb, txkb, ifutil;
2165 int i, j, k, pos, restart, *unregistered;
2167 if (action & F_BEGIN) {
2169 * Allocate arrays (#0..7) that will contain the graphs data
2170 * and the min/max values.
2171 * Also allocate one additional array (#8) for each interface:
2172 * out + 8 will contain the interface name,
2173 * outsize + 8 will contain a positive value (TRUE) if the interface
2174 * has either still not been registered, or has been unregistered.
2176 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2179 if (action & F_MAIN) {
2180 restart = svg_p->restart;
2182 * Mark previously registered interfaces as now
2183 * possibly unregistered for all graphs.
2185 for (k = 0; k < a->nr; k++) {
2186 unregistered = outsize + k * 9 + 8;
2187 if (*unregistered == FALSE) {
2188 *unregistered = MAYBE;
2192 /* For each network interfaces structure */
2193 for (i = 0; i < a->nr; i++) {
2194 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2195 if (!strcmp(sndc->interface, ""))
2196 /* Empty structure: Ignore it */
2199 /* Look for corresponding graph */
2200 for (k = 0; k < a->nr; k++) {
2201 item_name = *(out + k * 9 + 8);
2202 if (!strcmp(sndc->interface, item_name))
2207 /* Graph not found: Look for first free entry */
2208 for (k = 0; k < a->nr; k++) {
2209 item_name = *(out + k * 9 + 8);
2210 if (!strcmp(item_name, ""))
2214 /* No free graph entry: Graph for this item won't be drawn */
2219 unregistered = outsize + pos + 8;
2221 j = check_net_dev_reg(a, curr, !curr, i);
2222 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2225 * If current interface was marked as previously unregistered,
2226 * then set restart variable to TRUE so that the graph will be
2227 * discontinuous, and mark it as now registered.
2229 if (*unregistered == TRUE) {
2232 *unregistered = FALSE;
2234 if (!item_name[0]) {
2235 /* Save network interface name (if not already done) */
2236 strncpy(item_name, sndc->interface, CHUNKSIZE);
2237 item_name[CHUNKSIZE - 1] = '\0';
2240 /* Check for min/max values */
2241 save_extrema(7, 0, 0, (void *) sndc, (void *) sndp,
2242 itv, spmin + pos, spmax + pos, g_fields);
2244 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2245 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2246 ifutil = compute_ifutil(sndc, rxkb, txkb);
2247 if (ifutil < *(spmin + pos + 7)) {
2248 *(spmin + pos + 7) = ifutil;
2250 if (ifutil > *(spmax + pos + 7)) {
2251 *(spmax + pos + 7) = ifutil;
2255 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2256 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2257 out + pos, outsize + pos, restart);
2259 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2260 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2261 out + pos + 1, outsize + pos + 1, restart);
2263 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2265 out + pos + 2, outsize + pos + 2, restart);
2267 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2269 out + pos + 3, outsize + pos + 3, restart);
2271 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2272 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2273 out + pos + 4, outsize + pos + 4, restart);
2275 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2276 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2277 out + pos + 5, outsize + pos + 5, restart);
2279 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2280 S_VALUE(sndp->multicast, sndc->multicast, itv),
2281 out + pos + 6, outsize + pos + 6, restart);
2283 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2285 out + pos + 7, outsize + pos + 7, svg_p->dt);
2288 /* Mark interfaces not seen here as now unregistered */
2289 for (k = 0; k < a->nr; k++) {
2290 unregistered = outsize + k * 9 + 8;
2291 if (*unregistered != FALSE) {
2292 *unregistered = TRUE;
2297 if (action & F_END) {
2298 for (i = 0; i < a->nr; i++) {
2300 * Check if there is something to display.
2301 * Don't test sndc->interface because maybe the network
2302 * interface has been registered later.
2308 /* Recalculate min and max values in kB, not in B */
2309 *(spmin + pos + 2) /= 1024;
2310 *(spmax + pos + 2) /= 1024;
2311 *(spmin + pos + 3) /= 1024;
2312 *(spmax + pos + 3) /= 1024;
2314 item_name = *(out + pos + 8);
2315 draw_activity_graphs(a->g_nr, g_type,
2316 title, g_title, item_name, group,
2317 spmin + pos, spmax + pos, out + pos, outsize + pos,
2321 /* Free remaining structures */
2322 free_graphs(out, outsize, spmin, spmax);
2327 ***************************************************************************
2328 * Display network interface errors statistics in SVG.
2331 * @a Activity structure with statistics.
2332 * @curr Index in array for current sample statistics.
2333 * @action Action expected from current function.
2334 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2335 * flag indicating that a restart record has been previously
2336 * found (.@restart) and time used for the X axis origin
2338 * @itv Interval of time in jiffies (only with F_MAIN action).
2339 * @record_hdr Pointer on record header of current stats sample.
2340 ***************************************************************************
2342 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2343 unsigned long long itv, struct record_header *record_hdr)
2345 struct stats_net_edev *snedc, *snedp;
2346 int group[] = {2, 2, 2, 3};
2347 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2349 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2350 "Network errors statistics (3)", "Network errors statistics (4)"};
2351 char *g_title[] = {"rxerr/s", "txerr/s",
2352 "rxdrop/s", "txdrop/s",
2353 "rxfifo/s", "txfifo/s",
2354 "coll/s", "txcarr/s", "rxfram/s"};
2355 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2356 static double *spmin, *spmax;
2358 static int *outsize;
2360 int i, j, k, pos, restart, *unregistered;
2362 if (action & F_BEGIN) {
2364 * Allocate arrays (#0..8) that will contain the graphs data
2365 * and the min/max values.
2366 * Also allocate one additional array (#9) for each interface:
2367 * out + 9 will contain the interface name,
2368 * outsize + 9 will contain a positive value (TRUE) if the interface
2369 * has either still not been registered, or has been unregistered.
2371 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
2374 if (action & F_MAIN) {
2375 restart = svg_p->restart;
2377 * Mark previously registered interfaces as now
2378 * possibly unregistered for all graphs.
2380 for (k = 0; k < a->nr; k++) {
2381 unregistered = outsize + k * 10 + 9;
2382 if (*unregistered == FALSE) {
2383 *unregistered = MAYBE;
2387 /* For each network interfaces structure */
2388 for (i = 0; i < a->nr; i++) {
2389 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2390 if (!strcmp(snedc->interface, ""))
2391 /* Empty structure: Ignore it */
2394 /* Look for corresponding graph */
2395 for (k = 0; k < a->nr; k++) {
2396 item_name = *(out + k * 10 + 9);
2397 if (!strcmp(snedc->interface, item_name))
2402 /* Graph not found: Look for first free entry */
2403 for (k = 0; k < a->nr; k++) {
2404 item_name = *(out + k * 10 + 9);
2405 if (!strcmp(item_name, ""))
2409 /* No free graph entry: Graph for this item won't be drawn */
2414 unregistered = outsize + pos + 9;
2416 j = check_net_edev_reg(a, curr, !curr, i);
2417 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2420 * If current interface was marked as previously unregistered,
2421 * then set restart variable to TRUE so that the graph will be
2422 * discontinuous, and mark it as now registered.
2424 if (*unregistered == TRUE) {
2427 *unregistered = FALSE;
2429 if (!item_name[0]) {
2430 /* Save network interface name (if not already done) */
2431 strncpy(item_name, snedc->interface, CHUNKSIZE);
2432 item_name[CHUNKSIZE - 1] = '\0';
2435 /* Check for min/max values */
2436 save_extrema(9, 0, 0, (void *) snedc, (void *) snedp,
2437 itv, spmin + pos, spmax + pos, g_fields);
2440 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2441 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2442 out + pos, outsize + pos, restart);
2444 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2445 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2446 out + pos + 1, outsize + pos + 1, restart);
2448 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2449 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2450 out + pos + 2, outsize + pos + 2, restart);
2452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2453 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2454 out + pos + 3, outsize + pos + 3, restart);
2456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2457 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2458 out + pos + 4, outsize + pos + 4, restart);
2460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2461 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2462 out + pos + 5, outsize + pos + 5, restart);
2464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2465 S_VALUE(snedp->collisions, snedc->collisions, itv),
2466 out + pos + 6, outsize + pos + 6, restart);
2468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2469 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2470 out + pos + 7, outsize + pos + 7, restart);
2472 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2473 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2474 out + pos + 8, outsize + pos + 8, restart);
2477 /* Mark interfaces not seen here as now unregistered */
2478 for (k = 0; k < a->nr; k++) {
2479 unregistered = outsize + k * 10 + 9;
2480 if (*unregistered != FALSE) {
2481 *unregistered = TRUE;
2486 if (action & F_END) {
2487 for (i = 0; i < a->nr; i++) {
2489 * Check if there is something to display.
2490 * Don't test snedc->interface because maybe the network
2491 * interface has been registered later.
2497 item_name = *(out + pos + 9);
2498 draw_activity_graphs(a->g_nr, g_type,
2499 title, g_title, item_name, group,
2500 spmin + pos, spmax + pos, out + pos, outsize + pos,
2504 /* Free remaining structures */
2505 free_graphs(out, outsize, spmin, spmax);
2510 ***************************************************************************
2511 * Display NFS client statistics in SVG.
2514 * @a Activity structure with statistics.
2515 * @curr Index in array for current sample statistics.
2516 * @action Action expected from current function.
2517 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2518 * flag indicating that a restart record has been previously
2519 * found (.@restart) and time used for the X axis origin
2521 * @itv Interval of time in jiffies (only with F_MAIN action).
2522 * @record_hdr Pointer on record header of current stats sample.
2523 ***************************************************************************
2525 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2526 unsigned long long itv, struct record_header *record_hdr)
2528 struct stats_net_nfs
2529 *snnc = (struct stats_net_nfs *) a->buf[curr],
2530 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2531 int group[] = {2, 2, 2};
2532 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2533 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2534 "NFS client statistics (3)"};
2535 char *g_title[] = {"call/s", "retrans/s",
2536 "read/s", "write/s",
2537 "access/s", "getatt/s"};
2538 int g_fields[] = {0, 1, 2, 3, 4, 5};
2539 static double *spmin, *spmax;
2541 static int *outsize;
2543 if (action & F_BEGIN) {
2545 * Allocate arrays that will contain the graphs data
2546 * and the min/max values.
2548 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2551 if (action & F_MAIN) {
2552 /* Check for min/max values */
2553 save_extrema(0, 0, 6, (void *) a->buf[curr], (void *) a->buf[!curr],
2554 itv, spmin, spmax, g_fields);
2557 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2558 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2559 out, outsize, svg_p->restart);
2561 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2562 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2563 out + 1, outsize + 1, svg_p->restart);
2565 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2566 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2567 out + 2, outsize + 2, svg_p->restart);
2569 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2570 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2571 out + 3, outsize + 3, svg_p->restart);
2573 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2574 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2575 out + 4, outsize + 4, svg_p->restart);
2577 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2578 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2579 out + 5, outsize + 5, svg_p->restart);
2582 if (action & F_END) {
2583 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2584 spmin, spmax, out, outsize, svg_p, record_hdr);
2586 /* Free remaining structures */
2587 free_graphs(out, outsize, spmin, spmax);
2592 ***************************************************************************
2593 * Display NFS server statistics in SVG.
2596 * @a Activity structure with statistics.
2597 * @curr Index in array for current sample statistics.
2598 * @action Action expected from current function.
2599 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2600 * flag indicating that a restart record has been previously
2601 * found (.@restart) and time used for the X axis origin
2603 * @itv Interval of time in jiffies (only with F_MAIN action).
2604 * @record_hdr Pointer on record header of current stats sample.
2605 ***************************************************************************
2607 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2608 unsigned long long itv, struct record_header *record_hdr)
2610 struct stats_net_nfsd
2611 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2612 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2613 int group[] = {2, 3, 2, 2, 2};
2614 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2615 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2616 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2617 "NFS server statistics (3)", "NFS server statistics (4)",
2618 "NFS server statistics (5)"};
2619 char *g_title[] = {"scall/s", "badcall/s",
2620 "packet/s", "udp/s", "tcp/s",
2622 "sread/s", "swrite/s",
2623 "saccess/s", "sgetatt/s"};
2624 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2625 static double *spmin, *spmax;
2627 static int *outsize;
2629 if (action & F_BEGIN) {
2631 * Allocate arrays that will contain the graphs data
2632 * and the min/max values.
2634 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2637 if (action & F_MAIN) {
2638 /* Check for min/max values */
2639 save_extrema(0, 0, 11, (void *) a->buf[curr], (void *) a->buf[!curr],
2640 itv, spmin, spmax, g_fields);
2643 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2644 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2645 out, outsize, svg_p->restart);
2647 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2648 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2649 out + 1, outsize + 1, svg_p->restart);
2651 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2652 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2653 out + 2, outsize + 2, svg_p->restart);
2655 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2656 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2657 out + 3, outsize + 3, svg_p->restart);
2659 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2660 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2661 out + 4, outsize + 4, svg_p->restart);
2663 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2664 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2665 out + 5, outsize + 5, svg_p->restart);
2667 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2668 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2669 out + 6, outsize + 6, svg_p->restart);
2671 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2672 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2673 out + 7, outsize + 7, svg_p->restart);
2675 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2676 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2677 out + 8, outsize + 8, svg_p->restart);
2679 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2680 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2681 out + 9, outsize + 9, svg_p->restart);
2683 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2684 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2685 out + 10, outsize + 10, svg_p->restart);
2688 if (action & F_END) {
2689 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2690 spmin, spmax, out, outsize, svg_p, record_hdr);
2692 /* Free remaining structures */
2693 free_graphs(out, outsize, spmin, spmax);
2698 ***************************************************************************
2699 * Display network socket statistics in SVG.
2702 * @a Activity structure with statistics.
2703 * @curr Index in array for current sample statistics.
2704 * @action Action expected from current function.
2705 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2706 * flag indicating that a restart record has been previously
2707 * found (.@restart) and time used for the X axis origin
2709 * @itv Interval of time in jiffies (only with F_MAIN action).
2710 * @record_hdr Pointer on record header of current stats sample.
2711 ***************************************************************************
2713 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2714 unsigned long long itv, struct record_header *record_hdr)
2716 struct stats_net_sock
2717 *snsc = (struct stats_net_sock *) a->buf[curr];
2718 int group[] = {1, 5};
2719 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2720 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2721 char *g_title[] = {"~totsck",
2722 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2723 int g_fields[] = {0, 1, 5, 2, 3, 4};
2724 static double *spmin, *spmax;
2726 static int *outsize;
2728 if (action & F_BEGIN) {
2730 * Allocate arrays that will contain the graphs data
2731 * and the min/max values.
2733 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2736 if (action & F_MAIN) {
2737 /* Check for min/max values */
2738 save_extrema(0, 0, 6, (void *) a->buf[curr], NULL,
2739 itv, spmin, spmax, g_fields);
2741 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2742 (unsigned long) snsc->sock_inuse,
2743 out, outsize, svg_p->restart);
2745 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2746 (unsigned long) snsc->tcp_inuse,
2747 out + 1, outsize + 1, svg_p->restart);
2749 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2750 (unsigned long) snsc->udp_inuse,
2751 out + 2, outsize + 2, svg_p->restart);
2753 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2754 (unsigned long) snsc->raw_inuse,
2755 out + 3, outsize + 3, svg_p->restart);
2757 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2758 (unsigned long) snsc->frag_inuse,
2759 out + 4, outsize + 4, svg_p->restart);
2761 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2762 (unsigned long) snsc->tcp_tw,
2763 out + 5, outsize + 5, svg_p->restart);
2766 if (action & F_END) {
2767 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2768 spmin, spmax, out, outsize, svg_p, record_hdr);
2770 /* Free remaining structures */
2771 free_graphs(out, outsize, spmin, spmax);
2776 ***************************************************************************
2777 * Display IPv4 network statistics in SVG.
2780 * @a Activity structure with statistics.
2781 * @curr Index in array for current sample statistics.
2782 * @action Action expected from current function.
2783 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2784 * flag indicating that a restart record has been previously
2785 * found (.@restart) and time used for the X axis origin
2787 * @itv Interval of time in jiffies (only with F_MAIN action).
2788 * @record_hdr Pointer on record header of current stats sample.
2789 ***************************************************************************
2791 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2792 unsigned long long itv, struct record_header *record_hdr)
2795 *snic = (struct stats_net_ip *) a->buf[curr],
2796 *snip = (struct stats_net_ip *) a->buf[!curr];
2797 int group[] = {4, 2, 2};
2798 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2799 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2800 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2801 "asmrq/s", "asmok/s",
2802 "fragok/s", "fragcrt/s"};
2803 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2804 static double *spmin, *spmax;
2806 static int *outsize;
2808 if (action & F_BEGIN) {
2810 * Allocate arrays that will contain the graphs data
2811 * and the min/max values.
2813 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2816 if (action & F_MAIN) {
2817 /* Check for min/max values */
2818 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2819 itv, spmin, spmax, g_fields);
2822 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2823 S_VALUE(snip->InReceives, snic->InReceives, itv),
2824 out, outsize, svg_p->restart);
2826 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2827 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2828 out + 1, outsize + 1, svg_p->restart);
2830 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2831 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2832 out + 2, outsize + 2, svg_p->restart);
2834 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2835 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2836 out + 3, outsize + 3, svg_p->restart);
2838 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2839 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2840 out + 4, outsize + 4, svg_p->restart);
2842 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2843 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2844 out + 5, outsize + 5, svg_p->restart);
2846 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2847 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2848 out + 6, outsize + 6, svg_p->restart);
2850 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2851 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2852 out + 7, outsize + 7, svg_p->restart);
2855 if (action & F_END) {
2856 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2857 spmin, spmax, out, outsize, svg_p, record_hdr);
2859 /* Free remaining structures */
2860 free_graphs(out, outsize, spmin, spmax);
2865 ***************************************************************************
2866 * Display IPv4 network errors statistics in SVG.
2869 * @a Activity structure with statistics.
2870 * @curr Index in array for current sample statistics.
2871 * @action Action expected from current function.
2872 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2873 * flag indicating that a restart record has been previously
2874 * found (.@restart) and time used for the X axis origin
2876 * @itv Interval of time in jiffies (only with F_MAIN action).
2877 * @record_hdr Pointer on record header of current stats sample.
2878 ***************************************************************************
2880 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2881 unsigned long long itv, struct record_header *record_hdr)
2883 struct stats_net_eip
2884 *sneic = (struct stats_net_eip *) a->buf[curr],
2885 *sneip = (struct stats_net_eip *) a->buf[!curr];
2886 int group[] = {3, 2, 3};
2887 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2888 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
2889 "IPv4 network errors statistics (3)"};
2890 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
2891 "idisc/s", "odisc/s",
2892 "onort/s", "asmf/s", "fragf/s"};
2893 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2894 static double *spmin, *spmax;
2896 static int *outsize;
2898 if (action & F_BEGIN) {
2900 * Allocate arrays that will contain the graphs data
2901 * and the min/max values.
2903 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2906 if (action & F_MAIN) {
2907 /* Check for min/max values */
2908 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2909 itv, spmin, spmax, g_fields);
2912 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2913 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
2914 out, outsize, svg_p->restart);
2916 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2917 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
2918 out + 1, outsize + 1, svg_p->restart);
2920 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2921 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
2922 out + 2, outsize + 2, svg_p->restart);
2924 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2925 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
2926 out + 3, outsize + 3, svg_p->restart);
2928 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2929 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
2930 out + 4, outsize + 4, svg_p->restart);
2932 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2933 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
2934 out + 5, outsize + 5, svg_p->restart);
2936 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2937 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
2938 out + 6, outsize + 6, svg_p->restart);
2940 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2941 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
2942 out + 7, outsize + 7, svg_p->restart);
2945 if (action & F_END) {
2946 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2947 spmin, spmax, out, outsize, svg_p, record_hdr);
2949 /* Free remaining structures */
2950 free_graphs(out, outsize, spmin, spmax);
2955 ***************************************************************************
2956 * Display ICMPv4 network statistics in SVG.
2959 * @a Activity structure with statistics.
2960 * @curr Index in array for current sample statistics.
2961 * @action Action expected from current function.
2962 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2963 * flag indicating that a restart record has been previously
2964 * found (.@restart) and time used for the X axis origin
2966 * @itv Interval of time in jiffies (only with F_MAIN action).
2967 * @record_hdr Pointer on record header of current stats sample.
2968 ***************************************************************************
2970 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2971 unsigned long long itv, struct record_header *record_hdr)
2973 struct stats_net_icmp
2974 *snic = (struct stats_net_icmp *) a->buf[curr],
2975 *snip = (struct stats_net_icmp *) a->buf[!curr];
2976 int group[] = {2, 4, 4, 4};
2977 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2979 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
2980 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
2981 char *g_title[] = {"imsg/s", "omsg/s",
2982 "iech/s", "iechr/s", "oech/s", "oechr/s",
2983 "itm/s", "itmr/s", "otm/s", "otmr/s",
2984 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
2985 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
2986 static double *spmin, *spmax;
2988 static int *outsize;
2990 if (action & F_BEGIN) {
2992 * Allocate arrays that will contain the graphs data
2993 * and the min/max values.
2995 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
2998 if (action & F_MAIN) {
2999 /* Check for min/max values */
3000 save_extrema(0, 14, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3001 itv, spmin, spmax, g_fields);
3004 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3005 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3006 out, outsize, svg_p->restart);
3008 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3009 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3010 out + 1, outsize + 1, svg_p->restart);
3012 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3013 S_VALUE(snip->InEchos, snic->InEchos, itv),
3014 out + 2, outsize + 2, svg_p->restart);
3016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3017 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3018 out + 3, outsize + 3, svg_p->restart);
3020 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3021 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3022 out + 4, outsize + 4, svg_p->restart);
3024 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3025 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3026 out + 5, outsize + 5, svg_p->restart);
3028 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3029 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3030 out + 6, outsize + 6, svg_p->restart);
3032 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3033 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3034 out + 7, outsize + 7, svg_p->restart);
3036 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3037 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3038 out + 8, outsize + 8, svg_p->restart);
3040 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3041 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3042 out + 9, outsize + 9, svg_p->restart);
3044 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3045 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3046 out + 10, outsize + 10, svg_p->restart);
3048 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3049 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3050 out + 11, outsize + 11, svg_p->restart);
3052 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3053 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3054 out + 12, outsize + 12, svg_p->restart);
3056 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3057 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3058 out + 13, outsize + 13, svg_p->restart);
3061 if (action & F_END) {
3062 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3063 spmin, spmax, out, outsize, svg_p, record_hdr);
3065 /* Free remaining structures */
3066 free_graphs(out, outsize, spmin, spmax);
3071 ***************************************************************************
3072 * Display ICMPv4 network errors statistics in SVG.
3075 * @a Activity structure with statistics.
3076 * @curr Index in array for current sample statistics.
3077 * @action Action expected from current function.
3078 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3079 * flag indicating that a restart record has been previously
3080 * found (.@restart) and time used for the X axis origin
3082 * @itv Interval of time in jiffies (only with F_MAIN action).
3083 * @record_hdr Pointer on record header of current stats sample.
3084 ***************************************************************************
3086 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3087 unsigned long long itv, struct record_header *record_hdr)
3089 struct stats_net_eicmp
3090 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3091 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3092 int group[] = {2, 2, 2, 2, 2, 2};
3093 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3094 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3095 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3096 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3097 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3098 char *g_title[] = {"ierr/s", "oerr/s",
3099 "idstunr/s", "odstunr/s",
3100 "itmex/s", "otmex/s",
3101 "iparmpb/s", "oparmpb/s",
3102 "isrcq/s", "osrcq/s",
3103 "iredir/s", "oredir/s"};
3104 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3105 static double *spmin, *spmax;
3107 static int *outsize;
3109 if (action & F_BEGIN) {
3111 * Allocate arrays that will contain the graphs data
3112 * and the min/max values.
3114 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3117 if (action & F_MAIN) {
3118 /* Check for min/max values */
3119 save_extrema(0, 12, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3120 itv, spmin, spmax, g_fields);
3123 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3124 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3125 out, outsize, svg_p->restart);
3127 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3128 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3129 out + 1, outsize + 1, svg_p->restart);
3131 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3132 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3133 out + 2, outsize + 2, svg_p->restart);
3135 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3136 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3137 out + 3, outsize + 3, svg_p->restart);
3139 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3140 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3141 out + 4, outsize + 4, svg_p->restart);
3143 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3144 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3145 out + 5, outsize + 5, svg_p->restart);
3147 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3148 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3149 out + 6, outsize + 6, svg_p->restart);
3151 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3152 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3153 out + 7, outsize + 7, svg_p->restart);
3155 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3156 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3157 out + 8, outsize + 8, svg_p->restart);
3159 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3160 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3161 out + 9, outsize + 9, svg_p->restart);
3163 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3164 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3165 out + 10, outsize + 10, svg_p->restart);
3167 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3168 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3169 out + 11, outsize + 11, svg_p->restart);
3172 if (action & F_END) {
3173 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3174 spmin, spmax, out, outsize, svg_p, record_hdr);
3176 /* Free remaining structures */
3177 free_graphs(out, outsize, spmin, spmax);
3182 ***************************************************************************
3183 * Display TCPv4 network statistics in SVG.
3186 * @a Activity structure with statistics.
3187 * @curr Index in array for current sample statistics.
3188 * @action Action expected from current function.
3189 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3190 * flag indicating that a restart record has been previously
3191 * found (.@restart) and time used for the X axis origin
3193 * @itv Interval of time in jiffies (only with F_MAIN action).
3194 * @record_hdr Pointer on record header of current stats sample.
3195 ***************************************************************************
3197 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3198 unsigned long long itv, struct record_header *record_hdr)
3200 struct stats_net_tcp
3201 *sntc = (struct stats_net_tcp *) a->buf[curr],
3202 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3203 int group[] = {2, 2};
3204 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3205 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3206 char *g_title[] = {"active/s", "passive/s",
3207 "iseg/s", "oseg/s"};
3208 int g_fields[] = {0, 1, 2, 3};
3209 static double *spmin, *spmax;
3211 static int *outsize;
3213 if (action & F_BEGIN) {
3215 * Allocate arrays that will contain the graphs data
3216 * and the min/max values.
3218 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3221 if (action & F_MAIN) {
3222 /* Check for min/max values */
3223 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3224 itv, spmin, spmax, g_fields);
3227 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3228 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3229 out, outsize, svg_p->restart);
3231 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3232 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3233 out + 1, outsize + 1, svg_p->restart);
3235 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3236 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3237 out + 2, outsize + 2, svg_p->restart);
3239 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3240 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3241 out + 3, outsize + 3, svg_p->restart);
3244 if (action & F_END) {
3245 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3246 spmin, spmax, out, outsize, svg_p, record_hdr);
3248 /* Free remaining structures */
3249 free_graphs(out, outsize, spmin, spmax);
3254 ***************************************************************************
3255 * Display TCPv4 network errors statistics in SVG.
3258 * @a Activity structure with statistics.
3259 * @curr Index in array for current sample statistics.
3260 * @action Action expected from current function.
3261 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3262 * flag indicating that a restart record has been previously
3263 * found (.@restart) and time used for the X axis origin
3265 * @itv Interval of time in jiffies (only with F_MAIN action).
3266 * @record_hdr Pointer on record header of current stats sample.
3267 ***************************************************************************
3269 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3270 unsigned long long itv, struct record_header *record_hdr)
3272 struct stats_net_etcp
3273 *snetc = (struct stats_net_etcp *) a->buf[curr],
3274 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3275 int group[] = {2, 3};
3276 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3277 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3278 char *g_title[] = {"atmptf/s", "estres/s",
3279 "retrans/s", "isegerr/s", "orsts/s"};
3280 int g_fields[] = {0, 1, 2, 3, 4};
3281 static double *spmin, *spmax;
3283 static int *outsize;
3285 if (action & F_BEGIN) {
3287 * Allocate arrays that will contain the graphs data
3288 * and the min/max values.
3290 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3293 if (action & F_MAIN) {
3294 /* Check for min/max values */
3295 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3296 itv, spmin, spmax, g_fields);
3299 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3300 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3301 out, outsize, svg_p->restart);
3303 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3304 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3305 out + 1, outsize + 1, svg_p->restart);
3307 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3308 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3309 out + 2, outsize + 2, svg_p->restart);
3311 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3312 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3313 out + 3, outsize + 3, svg_p->restart);
3315 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3316 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3317 out + 4, outsize + 4, svg_p->restart);
3320 if (action & F_END) {
3321 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3322 spmin, spmax, out, outsize, svg_p, record_hdr);
3324 /* Free remaining structures */
3325 free_graphs(out, outsize, spmin, spmax);
3330 ***************************************************************************
3331 * Display UDPv4 network statistics in SVG.
3334 * @a Activity structure with statistics.
3335 * @curr Index in array for current sample statistics.
3336 * @action Action expected from current function.
3337 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3338 * flag indicating that a restart record has been previously
3339 * found (.@restart) and time used for the X axis origin
3341 * @itv Interval of time in jiffies (only with F_MAIN action).
3342 * @record_hdr Pointer on record header of current stats sample.
3343 ***************************************************************************
3345 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3346 unsigned long long itv, struct record_header *record_hdr)
3348 struct stats_net_udp
3349 *snuc = (struct stats_net_udp *) a->buf[curr],
3350 *snup = (struct stats_net_udp *) a->buf[!curr];
3351 int group[] = {2, 2};
3352 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3353 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3354 char *g_title[] = {"idgm/s", "odgm/s",
3355 "noport/s", "idgmerr/s"};
3356 int g_fields[] = {0, 1, 2, 3};
3357 static double *spmin, *spmax;
3359 static int *outsize;
3361 if (action & F_BEGIN) {
3363 * Allocate arrays that will contain the graphs data
3364 * and the min/max values.
3366 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3369 if (action & F_MAIN) {
3370 /* Check for min/max values */
3371 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3372 itv, spmin, spmax, g_fields);
3375 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3376 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3377 out, outsize, svg_p->restart);
3379 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3380 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3381 out + 1, outsize + 1, svg_p->restart);
3383 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3384 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3385 out + 2, outsize + 2, svg_p->restart);
3387 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3388 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3389 out + 3, outsize + 3, svg_p->restart);
3392 if (action & F_END) {
3393 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3394 spmin, spmax, out, outsize, svg_p, record_hdr);
3396 /* Free remaining structures */
3397 free_graphs(out, outsize, spmin, spmax);
3402 ***************************************************************************
3403 * Display IPV6 network socket statistics in SVG.
3406 * @a Activity structure with statistics.
3407 * @curr Index in array for current sample statistics.
3408 * @action Action expected from current function.
3409 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3410 * flag indicating that a restart record has been previously
3411 * found (.@restart) and time used for the X axis origin
3413 * @itv Interval of time in jiffies (only with F_MAIN action).
3414 * @record_hdr Pointer on record header of current stats sample.
3415 ***************************************************************************
3417 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3418 unsigned long long itv, struct record_header *record_hdr)
3420 struct stats_net_sock6
3421 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3423 int g_type[] = {SVG_LINE_GRAPH};
3424 char *title[] = {"IPv6 network sockets"};
3425 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3426 int g_fields[] = {0, 1, 2, 3};
3427 static double *spmin, *spmax;
3429 static int *outsize;
3431 if (action & F_BEGIN) {
3433 * Allocate arrays that will contain the graphs data
3434 * and the min/max values.
3436 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3439 if (action & F_MAIN) {
3440 /* Check for min/max values */
3441 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
3442 itv, spmin, spmax, g_fields);
3444 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3445 (unsigned long) snsc->tcp6_inuse,
3446 out, outsize, svg_p->restart);
3448 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3449 (unsigned long) snsc->udp6_inuse,
3450 out + 1, outsize + 1, svg_p->restart);
3452 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3453 (unsigned long) snsc->raw6_inuse,
3454 out + 2, outsize + 2, svg_p->restart);
3456 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3457 (unsigned long) snsc->frag6_inuse,
3458 out + 3, outsize + 3, svg_p->restart);
3461 if (action & F_END) {
3462 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3463 spmin, spmax, out, outsize, svg_p, record_hdr);
3465 /* Free remaining structures */
3466 free_graphs(out, outsize, spmin, spmax);
3471 ***************************************************************************
3472 * Display IPv6 network statistics in SVG.
3475 * @a Activity structure with statistics.
3476 * @curr Index in array for current sample statistics.
3477 * @action Action expected from current function.
3478 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3479 * flag indicating that a restart record has been previously
3480 * found (.@restart) and time used for the X axis origin
3482 * @itv Interval of time in jiffies (only with F_MAIN action).
3483 * @record_hdr Pointer on record header of current stats sample.
3484 ***************************************************************************
3486 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3487 unsigned long long itv, struct record_header *record_hdr)
3489 struct stats_net_ip6
3490 *snic = (struct stats_net_ip6 *) a->buf[curr],
3491 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3492 int group[] = {4, 2, 2, 2};
3493 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3495 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3496 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3497 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3498 "asmrq6/s", "asmok6/s",
3499 "imcpck6/s", "omcpck6/s",
3500 "fragok6/s", "fragcr6/s"};
3501 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3502 static double *spmin, *spmax;
3504 static int *outsize;
3506 if (action & F_BEGIN) {
3508 * Allocate arrays that will contain the graphs data
3509 * and the min/max values.
3511 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3514 if (action & F_MAIN) {
3515 /* Check for min/max values */
3516 save_extrema(10, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3517 itv, spmin, spmax, g_fields);
3520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3521 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3522 out, outsize, svg_p->restart);
3524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3525 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3526 out + 1, outsize + 1, svg_p->restart);
3528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3529 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3530 out + 2, outsize + 2, svg_p->restart);
3532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3533 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3534 out + 3, outsize + 3, svg_p->restart);
3536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3537 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3538 out + 4, outsize + 4, svg_p->restart);
3540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3541 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3542 out + 5, outsize + 5, svg_p->restart);
3544 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3545 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3546 out + 6, outsize + 6, svg_p->restart);
3548 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3549 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3550 out + 7, outsize + 7, svg_p->restart);
3552 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3553 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3554 out + 8, outsize + 8, svg_p->restart);
3556 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3557 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3558 out + 9, outsize + 9, svg_p->restart);
3561 if (action & F_END) {
3562 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3563 spmin, spmax, out, outsize, svg_p, record_hdr);
3565 /* Free remaining structures */
3566 free_graphs(out, outsize, spmin, spmax);
3571 ***************************************************************************
3572 * Display IPv6 network errors statistics in SVG.
3575 * @a Activity structure with statistics.
3576 * @curr Index in array for current sample statistics.
3577 * @action Action expected from current function.
3578 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3579 * flag indicating that a restart record has been previously
3580 * found (.@restart) and time used for the X axis origin
3582 * @itv Interval of time in jiffies (only with F_MAIN action).
3583 * @record_hdr Pointer on record header of current stats sample.
3584 ***************************************************************************
3586 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3587 unsigned long long itv, struct record_header *record_hdr)
3589 struct stats_net_eip6
3590 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3591 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3592 int group[] = {4, 2, 2, 3};
3593 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3595 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3596 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3597 "IPv6 network errors statistics (5)"};
3598 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3599 "idisc6/s", "odisc6/s",
3600 "inort6/s", "onort6/s",
3601 "asmf6/s", "fragf6/s", "itrpck6/s"};
3602 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3603 static double *spmin, *spmax;
3605 static int *outsize;
3607 if (action & F_BEGIN) {
3609 * Allocate arrays that will contain the graphs data
3610 * and the min/max values.
3612 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3615 if (action & F_MAIN) {
3616 /* Check for min/max values */
3617 save_extrema(11, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3618 itv, spmin, spmax, g_fields);
3621 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3622 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3623 out, outsize, svg_p->restart);
3625 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3626 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3627 out + 1, outsize + 1, svg_p->restart);
3629 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3630 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3631 out + 2, outsize + 2, svg_p->restart);
3633 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3634 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3635 out + 3, outsize + 3, svg_p->restart);
3637 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3638 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3639 out + 4, outsize + 4, svg_p->restart);
3641 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3642 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3643 out + 5, outsize + 5, svg_p->restart);
3645 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3646 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3647 out + 6, outsize + 6, svg_p->restart);
3649 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3650 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3651 out + 7, outsize + 7, svg_p->restart);
3653 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3654 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3655 out + 8, outsize + 8, svg_p->restart);
3657 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3658 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3659 out + 9, outsize + 9, svg_p->restart);
3661 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3662 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3663 out + 10, outsize + 10, svg_p->restart);
3666 if (action & F_END) {
3667 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3668 spmin, spmax, out, outsize, svg_p, record_hdr);
3670 /* Free remaining structures */
3671 free_graphs(out, outsize, spmin, spmax);
3676 ***************************************************************************
3677 * Display ICMPv6 network statistics in SVG.
3680 * @a Activity structure with statistics.
3681 * @curr Index in array for current sample statistics.
3682 * @action Action expected from current function.
3683 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3684 * flag indicating that a restart record has been previously
3685 * found (.@restart) and time used for the X axis origin
3687 * @itv Interval of time in jiffies (only with F_MAIN action).
3688 * @record_hdr Pointer on record header of current stats sample.
3689 ***************************************************************************
3691 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3692 unsigned long long itv, struct record_header *record_hdr)
3694 struct stats_net_icmp6
3695 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3696 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3697 int group[] = {2, 3, 5, 3, 4};
3698 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3699 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3700 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3701 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3702 "ICMPv6 network statistics (5)"};
3703 char *g_title[] = {"imsg6/s", "omsg6/s",
3704 "iech6/s", "iechr6/s", "oechr6/s",
3705 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3706 "irtsol6/s", "ortsol6/s", "irtad6/s",
3707 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3708 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3709 static double *spmin, *spmax;
3711 static int *outsize;
3713 if (action & F_BEGIN) {
3715 * Allocate arrays that will contain the graphs data
3716 * and the min/max values.
3718 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3721 if (action & F_MAIN) {
3722 /* Check for min/max values */
3723 save_extrema(0, 17, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3724 itv, spmin, spmax, g_fields);
3727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3728 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3729 out, outsize, svg_p->restart);
3731 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3732 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3733 out + 1, outsize + 1, svg_p->restart);
3735 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3736 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3737 out + 2, outsize + 2, svg_p->restart);
3739 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3740 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3741 out + 3, outsize + 3, svg_p->restart);
3743 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3744 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3745 out + 4, outsize + 4, svg_p->restart);
3747 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3748 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3749 out + 5, outsize + 5, svg_p->restart);
3751 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3752 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3753 out + 6, outsize + 6, svg_p->restart);
3755 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3756 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3757 out + 7, outsize + 7, svg_p->restart);
3759 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3760 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3761 out + 8, outsize + 8, svg_p->restart);
3763 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3764 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3765 out + 9, outsize + 9, svg_p->restart);
3767 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3768 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3769 out + 10, outsize + 10, svg_p->restart);
3771 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3772 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3773 out + 11, outsize + 11, svg_p->restart);
3775 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3776 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3777 out + 12, outsize + 12, svg_p->restart);
3779 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3780 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3781 out + 13, outsize + 13, svg_p->restart);
3783 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3784 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3785 out + 14, outsize + 14, svg_p->restart);
3787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3788 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3789 out + 15, outsize + 15, svg_p->restart);
3791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3792 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3793 out + 16, outsize + 16, svg_p->restart);
3796 if (action & F_END) {
3797 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3798 spmin, spmax, out, outsize, svg_p, record_hdr);
3800 /* Free remaining structures */
3801 free_graphs(out, outsize, spmin, spmax);
3806 ***************************************************************************
3807 * Display ICMPv6 network errors statistics in SVG.
3810 * @a Activity structure with statistics.
3811 * @curr Index in array for current sample statistics.
3812 * @action Action expected from current function.
3813 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3814 * flag indicating that a restart record has been previously
3815 * found (.@restart) and time used for the X axis origin
3817 * @itv Interval of time in jiffies (only with F_MAIN action).
3818 * @record_hdr Pointer on record header of current stats sample.
3819 ***************************************************************************
3821 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3822 unsigned long long itv, struct record_header *record_hdr)
3824 struct stats_net_eicmp6
3825 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3826 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3827 int group[] = {1, 2, 2, 2, 2, 2};
3828 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3829 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3830 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3831 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3832 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3833 char *g_title[] = {"ierr6/s",
3834 "idtunr6/s", "odtunr6/s",
3835 "itmex6/s", "otmex6/s",
3836 "iprmpb6/s", "oprmpb6/s",
3837 "iredir6/s", "oredir6/s",
3838 "ipck2b6/s", "opck2b6/s"};
3839 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3840 static double *spmin, *spmax;
3842 static int *outsize;
3844 if (action & F_BEGIN) {
3846 * Allocate arrays that will contain the graphs data
3847 * and the min/max values.
3849 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3852 if (action & F_MAIN) {
3853 /* Check for min/max values */
3854 save_extrema(0, 11, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3855 itv, spmin, spmax, g_fields);
3858 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3859 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
3860 out, outsize, svg_p->restart);
3862 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3863 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
3864 out + 1, outsize + 1, svg_p->restart);
3866 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3867 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
3868 out + 2, outsize + 2, svg_p->restart);
3870 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3871 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
3872 out + 3, outsize + 3, svg_p->restart);
3874 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3875 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
3876 out + 4, outsize + 4, svg_p->restart);
3878 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3879 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
3880 out + 5, outsize + 5, svg_p->restart);
3882 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3883 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
3884 out + 6, outsize + 6, svg_p->restart);
3886 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3887 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
3888 out + 7, outsize + 7, svg_p->restart);
3890 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3891 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
3892 out + 8, outsize + 8, svg_p->restart);
3894 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3895 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
3896 out + 9, outsize + 9, svg_p->restart);
3898 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3899 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
3900 out + 10, outsize + 10, svg_p->restart);
3903 if (action & F_END) {
3904 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3905 spmin, spmax, out, outsize, svg_p, record_hdr);
3907 /* Free remaining structures */
3908 free_graphs(out, outsize, spmin, spmax);
3913 ***************************************************************************
3914 * Display UDPv6 network statistics in SVG.
3917 * @a Activity structure with statistics.
3918 * @curr Index in array for current sample statistics.
3919 * @action Action expected from current function.
3920 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3921 * flag indicating that a restart record has been previously
3922 * found (.@restart) and time used for the X axis origin
3924 * @itv Interval of time in jiffies (only with F_MAIN action).
3925 * @record_hdr Pointer on record header of current stats sample.
3926 ***************************************************************************
3928 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3929 unsigned long long itv, struct record_header *record_hdr)
3931 struct stats_net_udp6
3932 *snuc = (struct stats_net_udp6 *) a->buf[curr],
3933 *snup = (struct stats_net_udp6 *) a->buf[!curr];
3934 int group[] = {2, 2};
3935 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3936 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
3937 char *g_title[] = {"idgm6/s", "odgm6/s",
3938 "noport6/s", "idgmer6/s"};
3939 int g_fields[] = {0, 1, 2, 3};
3940 static double *spmin, *spmax;
3942 static int *outsize;
3944 if (action & F_BEGIN) {
3946 * Allocate arrays that will contain the graphs data
3947 * and the min/max values.
3949 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3952 if (action & F_MAIN) {
3953 /* Check for min/max values */
3954 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3955 itv, spmin, spmax, g_fields);
3958 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3959 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
3960 out, outsize, svg_p->restart);
3962 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3963 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
3964 out + 1, outsize + 1, svg_p->restart);
3966 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3967 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
3968 out + 2, outsize + 2, svg_p->restart);
3970 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3971 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
3972 out + 3, outsize + 3, svg_p->restart);
3975 if (action & F_END) {
3976 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3977 spmin, spmax, out, outsize, svg_p, record_hdr);
3979 /* Free remaining structures */
3980 free_graphs(out, outsize, spmin, spmax);
3985 ***************************************************************************
3986 * Display CPU frequency statistics in SVG.
3989 * @a Activity structure with statistics.
3990 * @curr Index in array for current sample statistics.
3991 * @action Action expected from current function.
3992 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3993 * flag indicating that a restart record has been previously
3994 * found (.@restart) and time used for the X axis origin
3996 * @itv Interval of time in jiffies (unused here).
3997 * @record_hdr Pointer on record header of current stats sample.
3998 ***************************************************************************
4000 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4001 unsigned long long itv, struct record_header *record_hdr)
4003 struct stats_pwr_cpufreq *spc, *spp;
4005 int g_type[] = {SVG_LINE_GRAPH};
4006 char *title[] = {"CPU frequency"};
4007 char *g_title[] = {"MHz"};
4008 static double *spmin, *spmax;
4010 static int *outsize;
4014 if (action & F_BEGIN) {
4016 * Allocate arrays that will contain the graphs data
4017 * and the min/max values.
4019 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4022 if (action & F_MAIN) {
4024 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4026 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4027 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4029 /* Should current CPU (including CPU "all") be displayed? */
4030 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4035 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4036 ((double) spp->cpufreq) / 100,
4037 ((double) spc->cpufreq) / 100,
4038 out + i, outsize + i, svg_p->restart, svg_p->dt,
4039 spmin + i, spmax + i);
4043 if (action & F_END) {
4044 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4046 /* Should current CPU (including CPU "all") be displayed? */
4047 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4052 /* This is CPU "all" */
4053 strcpy(item_name, "all");
4056 sprintf(item_name, "%d", i - 1);
4059 draw_activity_graphs(a->g_nr, g_type,
4060 title, g_title, item_name, group,
4061 spmin + i, spmax + i, out + i, outsize + i,
4065 /* Free remaining structures */
4066 free_graphs(out, outsize, spmin, spmax);
4071 ***************************************************************************
4072 * Display fan statistics in SVG.
4075 * @a Activity structure with statistics.
4076 * @curr Index in array for current sample statistics.
4077 * @action Action expected from current function.
4078 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4079 * flag indicating that a restart record has been previously
4080 * found (.@restart) and time used for the X axis origin
4082 * @itv Interval of time in jiffies (unused here).
4083 * @record_hdr Pointer on record header of current stats sample.
4084 ***************************************************************************
4086 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4087 unsigned long long itv, struct record_header *record_hdr)
4089 struct stats_pwr_fan *spc, *spp;
4091 int g_type[] = {SVG_LINE_GRAPH};
4092 char *title[] = {"Fan speed"};
4093 char *g_title[] = {"~rpm"};
4094 static double *spmin, *spmax;
4096 static int *outsize;
4097 char item_name[MAX_SENSORS_DEV_LEN + 8];
4100 if (action & F_BEGIN) {
4102 * Allocate arrays that will contain the graphs data
4103 * and the min/max values.
4105 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4108 if (action & F_MAIN) {
4110 for (i = 0; i < a->nr; i++) {
4112 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4113 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4116 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4119 out + i, outsize + i, svg_p->restart, svg_p->dt,
4120 spmin + i, spmax + i);
4124 if (action & F_END) {
4125 for (i = 0; i < a->nr; i++) {
4127 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4129 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4130 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4132 draw_activity_graphs(a->g_nr, g_type,
4133 title, g_title, item_name, group,
4134 spmin + i, spmax + i, out + i, outsize + i,
4138 /* Free remaining structures */
4139 free_graphs(out, outsize, spmin, spmax);
4144 ***************************************************************************
4145 * Display temperature statistics in SVG.
4148 * @a Activity structure with statistics.
4149 * @curr Index in array for current sample statistics.
4150 * @action Action expected from current function.
4151 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4152 * flag indicating that a restart record has been previously
4153 * found (.@restart) and time used for the X axis origin
4155 * @itv Interval of time in jiffies (unused here).
4156 * @record_hdr Pointer on record header of current stats sample.
4157 ***************************************************************************
4159 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4160 unsigned long long itv, struct record_header *record_hdr)
4162 struct stats_pwr_temp *spc;
4163 int group[] = {1, 1};
4164 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4165 char *title[] = {"Device temperature (1)",
4166 "Device temperature (2)"};
4167 char *g_title[] = {"~degC",
4169 static double *spmin, *spmax;
4171 static int *outsize;
4172 char item_name[MAX_SENSORS_DEV_LEN + 8];
4176 if (action & F_BEGIN) {
4178 * Allocate arrays that will contain the graphs data
4179 * and the min/max values.
4181 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4184 if (action & F_MAIN) {
4185 /* For each temperature sensor */
4186 for (i = 0; i < a->nr; i++) {
4188 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4190 /* Look for min/max values */
4191 if (spc->temp < *(spmin + 2 * i)) {
4192 *(spmin + 2 * i) = spc->temp;
4194 if (spc->temp > *(spmax + 2 * i)) {
4195 *(spmax + 2 * i) = spc->temp;
4197 tval = (spc->temp_max - spc->temp_min) ?
4198 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4200 if (tval < *(spmin + 2 * i + 1)) {
4201 *(spmin + 2 * i + 1) = tval;
4203 if (tval > *(spmax + 2 * i + 1)) {
4204 *(spmax + 2 * i + 1) = tval;
4208 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4210 out + 2 * i, outsize + 2 * i, svg_p->restart);
4212 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4214 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4218 if (action & F_END) {
4219 for (i = 0; i < a->nr; i++) {
4221 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4223 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4224 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4226 draw_activity_graphs(a->g_nr, g_type,
4227 title, g_title, item_name, group,
4228 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4232 /* Free remaining structures */
4233 free_graphs(out, outsize, spmin, spmax);
4238 ***************************************************************************
4239 * Display voltage inputs statistics in SVG.
4242 * @a Activity structure with statistics.
4243 * @curr Index in array for current sample statistics.
4244 * @action Action expected from current function.
4245 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4246 * flag indicating that a restart record has been previously
4247 * found (.@restart) and time used for the X axis origin
4249 * @itv Interval of time in jiffies (only with F_MAIN action).
4250 * @record_hdr Pointer on record header of current stats sample.
4251 ***************************************************************************
4253 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4254 unsigned long long itv, struct record_header *record_hdr)
4256 struct stats_pwr_in *spc;
4257 int group[] = {1, 1};
4258 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4259 char *title[] = {"Voltage inputs (1)",
4260 "Voltage inputs (2)"};
4261 char *g_title[] = {"inV",
4263 static double *spmin, *spmax;
4265 static int *outsize;
4266 char item_name[MAX_SENSORS_DEV_LEN + 8];
4270 if (action & F_BEGIN) {
4272 * Allocate arrays that will contain the graphs data
4273 * and the min/max values.
4275 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4278 if (action & F_MAIN) {
4279 /* For each temperature sensor */
4280 for (i = 0; i < a->nr; i++) {
4282 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4284 /* Look for min/max values */
4285 if (spc->in < *(spmin + 2 * i)) {
4286 *(spmin + 2 * i) = spc->in;
4288 if (spc->in > *(spmax + 2 * i)) {
4289 *(spmax + 2 * i) = spc->in;
4291 tval = (spc->in_max - spc->in_min) ?
4292 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4294 if (tval < *(spmin + 2 * i + 1)) {
4295 *(spmin + 2 * i + 1) = tval;
4297 if (tval > *(spmax + 2 * i + 1)) {
4298 *(spmax + 2 * i + 1) = tval;
4302 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4304 out + 2 * i, outsize + 2 * i, svg_p->restart);
4306 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4308 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4312 if (action & F_END) {
4313 for (i = 0; i < a->nr; i++) {
4315 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4317 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4318 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4320 draw_activity_graphs(a->g_nr, g_type,
4321 title, g_title, item_name, group,
4322 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4326 /* Free remaining structures */
4327 free_graphs(out, outsize, spmin, spmax);
4332 ***************************************************************************
4333 * Display huge pages statistics in SVG.
4336 * @a Activity structure with statistics.
4337 * @curr Index in array for current sample statistics.
4338 * @action Action expected from current function.
4339 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4340 * flag indicating that a restart record has been previously
4341 * found (.@restart) and time used for the X axis origin
4343 * @itv Interval of time in jiffies (only with F_MAIN action).
4344 * @record_hdr Pointer on record header of current stats sample.
4345 ***************************************************************************
4347 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4348 unsigned long long itv, struct record_header *record_hdr)
4351 *smc = (struct stats_huge *) a->buf[curr];
4352 int group[] = {2, 1};
4353 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4354 char *title[] = {"Huge pages utilization (1)",
4355 "Huge pages utilization (2)"};
4356 char *g_title[] = {"~kbhugfree", "~kbhugused",
4358 int g_fields[] = {0};
4359 static double *spmin, *spmax;
4361 static int *outsize;
4364 if (action & F_BEGIN) {
4366 * Allocate arrays that will contain the graphs data
4367 * and the min/max values.
4369 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4372 if (action & F_MAIN) {
4373 /* Check for min/max values */
4374 save_extrema(0, 1, 0, (void *) a->buf[curr], NULL,
4375 itv, spmin, spmax, g_fields);
4377 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4378 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4380 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4381 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4383 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4384 if (tval < *(spmin + 2)) {
4385 *(spmin + 2) = tval;
4387 if (tval > *(spmax + 2)) {
4388 *(spmax + 2) = tval;
4392 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4393 (unsigned long) smc->frhkb,
4394 out, outsize, svg_p->restart);
4396 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4397 (unsigned long) smc->tlhkb - smc->frhkb,
4398 out + 1, outsize + 1, svg_p->restart);
4400 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4402 out + 2, outsize + 2, svg_p->dt);
4405 if (action & F_END) {
4406 draw_activity_graphs(a->g_nr, g_type,
4407 title, g_title, NULL, group,
4408 spmin, spmax, out, outsize, svg_p, record_hdr);
4410 /* Free remaining structures */
4411 free_graphs(out, outsize, spmin, spmax);
4416 ***************************************************************************
4417 * Display filesystem statistics in SVG.
4420 * @a Activity structure with statistics.
4421 * @curr Index in array for current sample statistics.
4422 * @action Action expected from current function.
4423 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4424 * flag indicating that a restart record has been previously
4425 * found (.@restart) and time used for the X axis origin
4427 * @itv Interval of time in jiffies (unused here).
4428 * @record_hdr Pointer on record header of current stats sample.
4429 ***************************************************************************
4431 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4432 unsigned long long itv, struct record_header *record_hdr)
4434 struct stats_filesystem *sfc, *sfp;
4435 int group[] = {2, 2, 2, 1};
4436 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4437 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4438 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4439 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4440 char *g_title[] = {"~MBfsfree", "~MBfsused",
4441 "%ufsused", "%fsused",
4442 "Ifree/1000", "Iused/1000",
4444 static double *spmin, *spmax;
4446 static int *outsize;
4449 int i, k, pos, restart;
4451 if (action & F_BEGIN) {
4453 * Allocate arrays (#0..6) that will contain the graphs data
4454 * and the min/max values.
4455 * Also allocate two additional arrays (#7..8) for each filesystem:
4456 * out + 7 will contain the filesystem name,
4457 * out + 8 will contain the mount point.
4459 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
4462 if (action & F_MAIN) {
4463 /* For each filesystem structure */
4464 for (i = 0; i < a->nr; i++) {
4465 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4468 /* Size of filesystem is zero: We are at the end of the list */
4471 /* Look for corresponding graph */
4472 for (k = 0; k < a->nr; k++) {
4473 item_name = *(out + k * 9 + 7);
4474 if (!strcmp(sfc->fs_name, item_name))
4480 /* Graph not found: Look for first free entry */
4481 for (k = 0; k < a->nr; k++) {
4482 item_name = *(out + k * 9 + 7);
4483 if (!strcmp(item_name, ""))
4487 /* No free graph entry: Graph for this item won't be drawn */
4493 if (!item_name[0]) {
4494 /* Save filesystem name and mount point (if not already done) */
4495 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4496 item_name[CHUNKSIZE - 1] = '\0';
4497 item_name = *(out + pos + 8);
4498 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4499 item_name[CHUNKSIZE - 1] = '\0';
4503 for (k = 0; k < a->nr; k++) {
4504 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4505 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4506 /* Filesystem found in previous sample */
4507 restart = svg_p->restart;
4511 /* Check for min/max values */
4513 /* Compute fsfree min/max values */
4514 tval = (double) sfc->f_bfree;
4515 if (tval > *(spmax + pos)) {
4516 *(spmax + pos) = tval;
4518 if (tval < *(spmin + pos)) {
4519 *(spmin + pos) = tval;
4521 /* Compute fsused min/max values */
4522 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4523 if (tval > *(spmax + pos + 1)) {
4524 *(spmax + pos + 1) = tval;
4526 if (tval < *(spmin + pos + 1)) {
4527 *(spmin + pos + 1) = tval;
4529 /* Compute %ufsused min/max values */
4530 tval = sfc->f_blocks ?
4531 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4532 if (tval > *(spmax + pos + 2)) {
4533 *(spmax + pos + 2) = tval;
4535 if (tval < *(spmin + pos + 2)) {
4536 *(spmin + pos + 2) = tval;
4538 /* Compute %fsused min/max values */
4539 tval = sfc->f_blocks ?
4540 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4541 if (tval > *(spmax + pos + 3)) {
4542 *(spmax + pos + 3) = tval;
4544 if (tval < *(spmin + pos + 3)) {
4545 *(spmin + pos + 3) = tval;
4547 /* Compute Ifree min/max values */
4548 tval = (double) sfc->f_ffree;
4549 if (tval > *(spmax + pos + 4)) {
4550 *(spmax + pos + 4) = tval;
4552 if (tval < *(spmin + pos + 4)) {
4553 *(spmin + pos + 4) = tval;
4555 /* Compute Iused min/max values */
4556 tval = (double) (sfc->f_files - sfc->f_ffree);
4557 if (tval > *(spmax + pos + 5)) {
4558 *(spmax + pos + 5) = tval;
4560 if (tval < *(spmin + pos + 5)) {
4561 *(spmin + pos + 5) = tval;
4563 /* Compute %Iused min/max values */
4564 tval = sfc->f_files ?
4565 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4566 if (tval > *(spmax + pos + 6)) {
4567 *(spmax + pos + 6) = tval;
4569 if (tval < *(spmin + pos + 6)) {
4570 *(spmin + pos + 6) = tval;
4574 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4575 (double) sfc->f_bfree / 1024 / 1024,
4576 out + pos, outsize + pos, restart);
4578 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4579 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4580 out + pos + 1, outsize + pos + 1, restart);
4582 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4585 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4586 out + pos + 2, outsize + pos + 2, svg_p->dt);
4588 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4591 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4592 out + pos + 3, outsize + pos + 3, svg_p->dt);
4594 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4595 ((double) sfc->f_ffree) / 1000,
4596 out + pos + 4, outsize + pos + 4, restart);
4598 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4599 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4600 out + pos + 5, outsize + pos + 5, restart);
4602 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4605 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4606 out + pos + 6, outsize + pos + 6, svg_p->dt);
4610 if (action & F_END) {
4612 for (i = 0; i < a->nr; i++) {
4614 /* Check if there is something to display */
4619 /* Conversion B -> MB and inodes/1000 */
4620 for (k = 0; k < 2; k++) {
4621 *(spmin + pos + k) /= (1024 * 1024);
4622 *(spmax + pos + k) /= (1024 * 1024);
4623 *(spmin + pos + 4 + k) /= 1000;
4624 *(spmax + pos + 4 + k) /= 1000;
4627 if (DISPLAY_MOUNT(a->opt_flags)) {
4628 item_name = *(out + pos + 8);
4631 item_name = *(out + pos + 7);
4634 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4635 spmin + pos, spmax + pos, out + pos, outsize + pos,
4639 /* Free remaining structures */
4640 free_graphs(out, outsize, spmin, spmax);
4645 ***************************************************************************
4646 * Display Fibre Channel HBA statistics in SVG.
4649 * @a Activity structure with statistics.
4650 * @curr Index in array for current sample statistics.
4651 * @action Action expected from current function.
4652 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4653 * flag indicating that a restart record has been previously
4654 * found (.@restart) and time used for the X axis origin
4656 * @itv Interval of time in jiffies (only with F_MAIN action).
4657 * @record_hdr Pointer on record header of current stats sample.
4658 ***************************************************************************
4660 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4661 unsigned long long itv, struct record_header *record_hdr)
4663 struct stats_fchost *sfcc, *sfcp;
4664 int group[] = {2, 2};
4665 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4666 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4667 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4668 "fch_rxw/s", "fch_txw/s"};
4669 int g_fields[] = {0, 1, 2, 3};
4670 static double *spmin, *spmax;
4672 static int *outsize;
4676 if (action & F_BEGIN) {
4678 * Allocate arrays (#0..3) that will contain the graphs data
4679 * and the min/max values.
4680 * Also allocate one additional array (#4) that will contain
4683 out = allocate_graph_lines(4 * a->nr, &outsize, &spmin, &spmax);
4686 if (action & F_MAIN) {
4687 /* For each FC HBA */
4688 for (i = 0; i < a->nr; i++) {
4690 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4691 if (!sfcc->fchost_name[0])
4692 /* We are at the end of the list */
4695 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
4698 item_name = *(out + pos + 4);
4699 if (!item_name[0]) {
4700 /* Save FC HBA name */
4701 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4702 item_name[CHUNKSIZE - 1] = '\0';
4705 /* Look for min/max values */
4706 save_extrema(0, 4, 0, (void *) sfcc, (void *) sfcp,
4707 itv, spmin + pos, spmax + pos, g_fields);
4710 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4711 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4712 out + pos, outsize + pos, svg_p->restart);
4714 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4715 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4716 out + pos + 1, outsize + pos + 1, svg_p->restart);
4718 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4719 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4720 out + pos + 2, outsize + pos + 2, svg_p->restart);
4722 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4723 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4724 out + pos + 3, outsize + pos + 3, svg_p->restart);
4728 if (action & F_END) {
4729 for (i = 0; i < a->nr; i++) {
4731 /* Check if there is something to display */
4736 item_name = *(out + pos + 4);
4737 draw_activity_graphs(a->g_nr, g_type,
4738 title, g_title, item_name, group,
4739 spmin + pos, spmax + pos, out + pos, outsize + pos,
4743 /* Free remaining structures */
4744 free_graphs(out, outsize, spmin, spmax);