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 * @spmin Array containing min values already found for this activity.
68 * @spmax Array containing max values already found for this activity.
69 * @g_fields Index in spmin/spmax arrays where extrema values for each
70 * activity metric will be saved. As a consequence spmin/spmax
71 * arrays mau contain values in a different order than that of
72 * the fields in the statistics structure.
75 * @spmin Array containg the possible new min values for current activity.
76 * @spmax Array containg the possible new max values for current activity.
77 ***************************************************************************
79 void save_extrema(int llu_nr, int lu_nr, int u_nr, void *cs, void *ps,
80 unsigned long long itv, double *spmin, double *spmax, int g_fields[])
82 unsigned long long *lluc, *llup;
83 unsigned long *luc, *lup;
84 unsigned int *uc, *up;
88 /* Compare unsigned long long fields */
89 lluc = (unsigned long long *) cs;
90 llup = (unsigned long long *) ps;
91 for (i = 0; i < llu_nr; i++, m++) {
93 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
97 * If no pointer on previous sample has been given
98 * then the value is not a per-second one.
100 val = (double) *lluc;
102 if (val < *(spmin + g_fields[m])) {
103 *(spmin + g_fields[m]) = val;
105 if (val > *(spmax + g_fields[m])) {
106 *(spmax + g_fields[m]) = val;
108 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
110 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
114 /* Compare unsigned long fields */
115 luc = (unsigned long *) lluc;
116 lup = (unsigned long *) llup;
117 for (i = 0; i < lu_nr; i++, m++) {
119 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
124 if (val < *(spmin + g_fields[m])) {
125 *(spmin + g_fields[m]) = val;
127 if (val > *(spmax + g_fields[m])) {
128 *(spmax + g_fields[m]) = val;
130 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
132 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
136 /* Compare unsigned int fields */
137 uc = (unsigned int *) luc;
138 up = (unsigned int *) lup;
139 for (i = 0; i < u_nr; i++, m++) {
141 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
146 if (val < *(spmin + g_fields[m])) {
147 *(spmin + g_fields[m]) = val;
149 if (val > *(spmax + g_fields[m])) {
150 *(spmax + g_fields[m]) = val;
152 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
154 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
160 ***************************************************************************
161 * Find the min and max values of all the graphs that will be drawn in the
162 * same view. The graphs have their own min and max values in
163 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
166 * @pos Position in array for the first graph extrema value.
167 * @n Number of graphs to scan.
168 * @spmin Array containing min values for graphs.
169 * @spmax Array containing max values for graphs.
172 * @gmin Global min value found.
173 * @gmax Global max value found.
174 ***************************************************************************
176 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
177 double *gmin, double *gmax)
181 *gmin = *(spmin + pos);
182 *gmax = *(spmax + pos);
184 for (i = 1; i < n; i++) {
185 if (*(spmin + pos + i) < *gmin) {
186 *gmin = *(spmin + pos + i);
188 if (*(spmax + pos + i) > *gmax) {
189 *gmax = *(spmax + pos + i);
195 ***************************************************************************
196 * Allocate arrays used to save graphs data, min and max values.
197 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
198 * array is returned. This is equivalent to "char data[][n]" where each
199 * element is of indeterminate size and will contain the graph data (eg.
200 * << path d="M12,14 L13,16..." ... >>.
201 * The size of element data[i] is given by outsize[i].
202 * Also allocate an array to save min values (equivalent to "double spmin[n]")
203 * and an array for max values (equivalent to "double spmax[n]").
206 * @n Number of graphs to draw for current activity.
209 * @outsize Array that will contain the sizes of each element in array
210 * of chars. Equivalent to "int outsize[n]" with
211 * outsize[n] = sizeof(data[][n]).
212 * @spmin Array that will contain min values for current activity.
213 * @spmax Array that will contain max values for current activity.
216 * Pointer on array of arrays of chars that will contain the graphs data.
218 * NB: @min and @max arrays contain values in the same order as the fields
219 * in the statistics structure.
220 ***************************************************************************
222 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
229 * Allocate an array of pointers. Each of these pointers will
230 * be an array of chars.
232 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
236 /* Allocate array that will contain the size of each array of chars */
237 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
241 /* Allocate array that will contain the min value of each graph */
242 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
246 /* Allocate array that will contain the max value of each graph */
247 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
251 /* Allocate arrays of chars that will contain graphs data */
252 for (i = 0; i < n; i++) {
253 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
258 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
259 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
260 *(*spmin + i) = DBL_MAX; /* Init min and max values */
261 *(*spmax + i) = -DBL_MAX;
268 ***************************************************************************
269 * Save SVG code for current graph.
272 * @data SVG code to append to current graph definition.
273 * @out Pointer on array of chars for current graph definition.
274 * @outsize Size of array of chars for current graph definition.
277 * @out Pointer on array of chars for current graph definition that
278 * has been updated with the addition of current sample data.
279 * @outsize Array that containing the (possibly new) sizes of each
280 * element in array of chars.
281 ***************************************************************************
283 void save_svg_data(char *data, char **out, int *outsize)
289 /* Determine space left in array */
290 len = *outsize - strlen(out_p) - 1;
291 if (strlen(data) >= len) {
293 * If current array of chars doesn't have enough space left
294 * then reallocate it with CHUNKSIZE more bytes.
296 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
298 *outsize += CHUNKSIZE;
301 strncat(out_p, data, len);
305 ***************************************************************************
306 * Update line graph definition by appending current X,Y coordinates.
309 * @timetag Timestamp in seconds since the epoch for current sample
310 * stats. Will be used as X coordinate.
311 * @value Value of current sample metric. Will be used as Y coordinate.
312 * @out Pointer on array of chars for current graph definition.
313 * @outsize Size of array of chars for current graph definition.
314 * @restart Set to TRUE if a RESTART record has been read since the last
318 * @out Pointer on array of chars for current graph definition that
319 * has been updated with the addition of current sample data.
320 * @outsize Array that containing the (possibly new) sizes of each
321 * element in array of chars.
322 ***************************************************************************
324 void lnappend(unsigned long timetag, double value, char **out, int *outsize, int restart)
328 /* Prepare additional graph definition data */
329 snprintf(data, 128, " %c%lu,%.2f", restart ? 'M' : 'L', timetag, value);
332 save_svg_data(data, out, outsize);
336 ***************************************************************************
337 * Update line graph definition by appending current X,Y coordinates. Use
338 * (unsigned long) integer values here.
341 * @timetag Timestamp in seconds since the epoch for current sample
342 * stats. Will be used as X coordinate.
343 * @value Value of current sample metric. Will be used as Y coordinate.
344 * @out Pointer on array of chars for current graph definition.
345 * @outsize Size of array of chars for current graph definition.
346 * @restart Set to TRUE if a RESTART record has been read since the last
350 * @out Pointer on array of chars for current graph definition that
351 * has been updated with the addition of current sample data.
352 * @outsize Array that containing the (possibly new) sizes of each
353 * element in array of chars.
354 ***************************************************************************
356 void lniappend(unsigned long timetag, unsigned long value, char **out, int *outsize,
361 /* Prepare additional graph definition data */
362 snprintf(data, 128, " %c%lu,%lu", restart ? 'M' : 'L', timetag, value);
365 save_svg_data(data, out, outsize);
369 ***************************************************************************
370 * Update bar graph definition by adding a new rectangle.
373 * @timetag Timestamp in seconds since the epoch for current sample
374 * stats. Will be used as X coordinate.
375 * @value Value of current sample metric. Will be used as rectangle
377 * @offset Offset for Y coordinate.
378 * @out Pointer on array of chars for current graph definition.
379 * @outsize Size of array of chars for current graph definition.
380 * @dt Interval of time in seconds between current and previous
384 * @out Pointer on array of chars for current graph definition that
385 * has been updated with the addition of current sample data.
386 * @outsize Array that containing the (possibly new) sizes of each
387 * element in array of chars.
388 ***************************************************************************
390 void brappend(unsigned long timetag, double offset, double value, char **out, int *outsize,
395 /* Prepare additional graph definition data */
396 if ((value == 0.0) || (dt == 0))
397 /* Dont draw a flat rectangle! */
400 snprintf(data, 128, "<rect x=\"%lu\" y=\"%.2f\" height=\"%.2f\" width=\"%lu\"/>",
401 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
404 save_svg_data(data, out, outsize);
409 ***************************************************************************
410 * Update CPU graph and min/max values for each metric.
413 * @timetag Timestamp in seconds since the epoch for current sample
414 * stats. Will be used as X coordinate.
415 * @offset Offset for Y coordinate.
416 * @value Value of current CPU metric. Will be used as rectangle
418 * @out Pointer on array of chars for current graph definition.
419 * @outsize Size of array of chars for current graph definition.
420 * @dt Interval of time in seconds between current and previous
422 * @spmin Min value already found for this CPU metric.
423 * @spmax Max value already found for this CPU metric.
426 * @offset New offset value, to use to draw next rectangle
427 * @out Pointer on array of chars for current graph definition that
428 * has been updated with the addition of current sample data.
429 * @outsize Array that containing the (possibly new) sizes of each
430 * element in array of chars.
431 ***************************************************************************
433 void cpuappend(unsigned long timetag, double *offset, double value, char **out, int *outsize,
434 unsigned long dt, double *spmin, double *spmax)
436 /* Save min and max values */
437 if (value < *spmin) {
440 if (value > *spmax) {
443 /* Prepare additional graph definition data */
444 brappend(timetag, *offset, value, out, outsize, dt);
450 ***************************************************************************
451 * Update rectangular graph and min/max values.
454 * @timetag Timestamp in seconds since the epoch for current sample
455 * stats. Will be used as X coordinate.
456 * @p_value Metric value for previous sample
457 * @value Metric value for current sample.
458 * @out Pointer on array of chars for current graph definition.
459 * @outsize Size of array of chars for current graph definition.
460 * @restart Set to TRUE if a RESTART record has been read since the last
462 * @dt Interval of time in seconds between current and previous
464 * @spmin Min value already found for this metric.
465 * @spmax Max value already found for this metric.
468 * @out Pointer on array of chars for current graph definition that
469 * has been updated with the addition of current sample data.
470 * @outsize Array that containing the (possibly new) sizes of each
471 * element in array of chars.
472 * @spmin Min value for this metric.
473 * @spmax Max value for this metric.
474 ***************************************************************************
476 void recappend(unsigned long timetag, double p_value, double value, char **out, int *outsize,
477 int restart, unsigned long dt, double *spmin, double *spmax)
479 char data[128], data1[128], data2[128];
481 /* Save min and max values */
482 if (value < *spmin) {
485 if (value > *spmax) {
488 /* Prepare additional graph definition data */
490 snprintf(data1, 128, " M%lu,%.2f", timetag - dt, p_value);
493 if (p_value != value) {
494 snprintf(data2, 128, " L%lu,%.2f", timetag, value);
497 snprintf(data, 128, "%s L%lu,%.2f%s", restart ? data1 : "", timetag, p_value,
498 p_value != value ? data2 : "");
501 save_svg_data(data, out, outsize);
505 ***************************************************************************
506 * Calculate 10 raised to the power of n.
509 * @n Power number to use.
512 * 10 raised to the power of n.
513 ***************************************************************************
515 unsigned int pwr10(int n)
520 for (i = 0; i < n; i++) {
528 ***************************************************************************
529 * Autoscale graphs of a given view.
532 * @asf_nr (Maximum) number of autoscale factors.
533 * @group Number of graphs in current view.
534 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
535 * @pos Position in array for the first graph in view.
536 * @gmax Global max value for all graphs in view.
537 * @spmax Array containing max values for graphs.
540 * @asfactor Autoscale factors (one for each graph).
541 ***************************************************************************
543 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
544 double gmax, double *spmax)
549 for (j = 0; j < asf_nr; j++) {
550 /* Init autoscale factors */
554 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
556 for (j = 0; (j < group) && (j < asf_nr); j++) {
557 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
560 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
561 if (strlen(val) > 0) {
562 asfactor[j] = pwr10(strlen(val) - 1);
569 ***************************************************************************
570 * Display background grid (horizontal lines) and corresponding graduations.
573 * @ypos Gap between two horizontal lines.
574 * @yfactor Scaling factor on Y axis.
575 * @lmax Max value for current view.
576 * @dp Number of decimal places for graduations.
577 ***************************************************************************
579 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
585 /* Display horizontal lines (except on X axis) */
587 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
588 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
589 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
593 * Display graduations.
594 * Use same rounded value for graduation numbers as for grid lines
595 * to make sure they are properly aligned.
597 sprintf(stmp, "%.2f", ypos * j);
598 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
599 "text-anchor: end\">%.*f.</text>\n",
600 (long) (atof(stmp) * yfactor), dp, ypos * j);
603 while (ypos * j <= lmax);
607 ***************************************************************************
608 * Display background grid (vertical lines) and corresponding graduations.
611 * @xpos Gap between two vertical lines.
612 * @xfactor Scaling factor on X axis.
613 * @v_gridnr Number of vertical lines to display.
614 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
615 ***************************************************************************
617 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
619 struct record_header stamp;
621 char cur_time[TIMESTAMP_LEN];
624 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
626 for (j = 0; (j <= v_gridnr) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
628 /* Display vertical lines */
629 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
630 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
631 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
632 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
633 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
635 * Display graduations.
636 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
637 * In this case, we should rather display the exact time instead of only the hour.
639 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
640 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
641 "text-anchor: start\">%2dH</text>\n",
642 (long) (xpos * j * xfactor) - 8, rectime.tm_hour);
645 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
646 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
647 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
649 stamp.ust_time += xpos;
652 if (!PRINT_LOCAL_TIME(flags)) {
653 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
654 "text-anchor: end\">UTC</text>\n");
659 ***************************************************************************
660 * Calculate the value on the Y axis between two horizontal lines that will
661 * make the graph background grid.
664 * @lmax Max value reached for this graph.
667 * @dp Number of decimal places for Y graduations.
670 * Value between two horizontal lines.
671 ***************************************************************************
673 double ygrid(double lmax, int *dp)
684 n = (long) (lmax / SVG_H_GRIDNR);
687 return (lmax / SVG_H_GRIDNR);
689 snprintf(val, 32, "%ld", n);
696 return ((double) (((long) (n / e)) * e));
700 ***************************************************************************
701 * Calculate the value on the X axis between two vertical lines that will
702 * make the graph background grid.
705 * @timestart First data timestamp (X coordinate of the first data point).
706 * @timeend Last data timestamp (X coordinate of the last data point).
707 * @v_gridnr Number of vertical lines to display. Its value is normally
708 * SVG_V_GRIDNR, except when option "oneday" is used, in which
709 * case it is set to 12.
712 * Value between two vertical lines.
713 ***************************************************************************
715 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
717 if ((timeend - timestart) <= v_gridnr)
720 return ((timeend - timestart) / v_gridnr);
724 ***************************************************************************
725 * Free global graphs structures.
728 * @out Pointer on array of chars for each graph definition.
729 * @outsize Size of array of chars for each graph definition.
730 * @spmin Array containing min values for graphs.
731 * @spmax Array containing max values for graphs.
732 ***************************************************************************
734 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
751 ***************************************************************************
752 * Skip current view where all graphs have only zero values. This function
753 * is called when option "skipempty" has been used, or when "No data" have
754 * been found for current view.
757 * @out Pointer on array of chars for each graph definition.
758 * @pos Position of current view in the array of graphs definitions.
759 * @group Number of graphs in current view.
762 * @pos Position of next view in the array of graphs definitions.
763 ***************************************************************************
765 void skip_current_view(char **out, int *pos, int group)
770 for (j = 0; j < group; j++) {
771 out_p = *(out + *pos + j);
773 /* Even if not displayed, current graph data have to be freed */
781 ***************************************************************************
782 * Display all graphs for current activity.
785 * @g_nr Number of sets of graphs (views) to display.
786 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
787 * @title Titles for each set of graphs.
788 * @g_title Titles for each graph.
789 * @item_name Item (network interface, etc.) name.
790 * @group Indicate how graphs are grouped together to make sets.
791 * @spmin Array containing min values for graphs.
792 * @spmax Array containing max values for graphs.
793 * @out Pointer on array of chars for each graph definition.
794 * @outsize Size of array of chars for each graph definition.
795 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
796 * time for the first sample of stats (.@ust_time_first), and
797 * times used as start and end values on the X axis
798 * (.@ust_time_ref and .@ust_time_end).
799 * @record_hdr Pointer on record header of current stats sample.
800 ***************************************************************************
802 void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
803 int group[], double *spmin, double *spmax, char **out, int *outsize,
804 struct svg_parm *svg_p, struct record_header *record_hdr)
807 int i, j, dp, pos = 0, views_nr = 0;
809 unsigned int asfactor[16];
811 double lmax, xfactor, yfactor, ypos, gmin, gmax;
814 /* Translate to proper position for current activity */
815 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
817 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
819 /* For each set of graphs which are part of current activity */
820 for (i = 0; i < g_nr; i++) {
822 /* Get global min and max value for current set of graphs */
823 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
825 /* Don't display empty views if requested */
826 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
827 skip_current_view(out, &pos, group[i]);
830 /* Increment number of views actually displayed */
833 /* Graph background */
834 printf("<rect x=\"0\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
835 (views_nr - 1) * SVG_T_YSIZE,
836 SVG_V_YSIZE, SVG_V_XSIZE);
839 printf("<text x=\"0\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
840 20 + (views_nr - 1) * SVG_T_YSIZE, title[i]);
842 printf(" [%s]", item_name);
845 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
846 "(Min, Max values)</tspan>\n</text>\n",
847 5 + SVG_M_XSIZE + SVG_G_XSIZE,
848 25 + (views_nr - 1) * SVG_T_YSIZE);
851 * At least two samples are needed.
852 * And a min and max value should have been found.
854 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
855 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
857 printf("<text x=\"0\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
858 SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
859 skip_current_view(out, &pos, group[i]);
864 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
865 SVG_M_XSIZE, SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE,
866 SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE,
867 SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
869 /* Autoscaling graphs if needed */
870 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
873 for (j = 0; j < group[i]; j++) {
874 /* Set dp to TRUE (1) if current metric is based on integer values */
875 dp = (g_title[pos + j][0] == '~');
876 snprintf(val, 32, "x%u ", asfactor[j]);
877 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
878 "%s %s(%.*f, %.*f)</text>\n",
879 5 + SVG_M_XSIZE + SVG_G_XSIZE, SVG_M_YSIZE + (views_nr - 1) * SVG_T_YSIZE + j * 15,
880 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
881 asfactor[j] == 1 ? "" : val,
882 !dp * 2, *(spmin + pos + j) * asfactor[j],
883 !dp * 2, *(spmax + pos + j) * asfactor[j]);
886 /* Translate to proper position for current graph within current activity */
887 printf("<g transform=\"translate(%d,%d)\">\n",
888 SVG_M_XSIZE, SVG_M_YSIZE + SVG_G_YSIZE + (views_nr - 1) * SVG_T_YSIZE);
891 if (g_type[i] == SVG_LINE_GRAPH) {
892 /* For line graphs */
894 /* If all values are zero then set current max value to 1 */
900 /* Max value cannot be too small, else Y graduations will be meaningless */
901 if (lmax < SVG_H_GRIDNR * 0.01) {
902 lmax = SVG_H_GRIDNR * 0.01;
904 ypos = ygrid(lmax, &dp);
907 /* For bar graphs (used for %values) */
908 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
909 dp = 0; /* No decimals */
911 /* Max should be always 100% except for percentage values greater than 100% */
919 yfactor = (double) -SVG_G_YSIZE / lmax;
921 /* Display horizontal lines and graduations */
922 display_hgrid(ypos, yfactor, lmax, dp);
924 /* Set number of vertical lines to 12 when option "oneday" is used */
925 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
927 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
928 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
930 /* Display vertical lines and graduations */
931 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
933 /* Draw current graphs set */
934 for (j = 0; j < group[i]; j++) {
935 out_p = *(out + pos + j);
936 if (g_type[i] == SVG_LINE_GRAPH) {
938 printf("<path id=\"g%dp%d\" d=\"%s\" "
939 "style=\"vector-effect: non-scaling-stroke; "
940 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
941 "transform=\"scale(%f,%f)\"/>\n",
942 svg_p->graph_no, pos + j, out_p,
943 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
945 yfactor * asfactor[j]);
947 else if (*out_p) { /* Ignore flat bars */
949 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
950 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
951 printf("%s\n", out_p);
962 (svg_p->graph_no) += views_nr;
966 ***************************************************************************
967 * Display CPU statistics in SVG.
970 * @a Activity structure with statistics.
971 * @curr Index in array for current sample statistics.
972 * @action Action expected from current function.
973 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
974 * flag indicating that a restart record has been previously
975 * found (.@restart), and time used for the X axis origin
977 * @itv Interval of time in jiffies (only with F_MAIN action).
978 * @record_hdr Pointer on record header of current stats sample.
979 ***************************************************************************
981 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
982 unsigned long long g_itv, struct record_header *record_hdr)
984 struct stats_cpu *scc, *scp;
987 int g_type[] = {SVG_BAR_GRAPH};
988 char *title[] = {"CPU load"};
989 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
990 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
991 static double *spmin, *spmax;
996 int i, j, k, pos, cpu_offline;
998 if (action & F_BEGIN) {
1000 * Allocate arrays that will contain the graphs data
1001 * and the min/max values.
1003 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
1006 if (action & F_MAIN) {
1008 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1010 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1011 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1013 /* Should current CPU (including CPU "all") be displayed? */
1014 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1021 if (i) { /* Don't test CPU "all" here */
1023 * If the CPU is offline then it is omited from /proc/stat:
1024 * All the fields couldn't have been read and the sum of them is zero.
1025 * (Remember that guest/guest_nice times are already included in
1028 if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys +
1029 scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal +
1030 scc->cpu_hardirq + scc->cpu_softirq) == 0) {
1032 * Set current struct fields (which have been set to zero)
1033 * to values from previous iteration. Hence their values won't
1034 * jump from zero when the CPU comes back online.
1043 * Recalculate interval for current proc.
1044 * If result is 0 then current CPU is a tickless one.
1046 g_itv = get_per_cpu_interval(scc, scp);
1047 cpu_offline = FALSE;
1050 if (!g_itv) { /* Current CPU is offline or tickless */
1052 val = (cpu_offline ? 0.0 /* Offline CPU: %idle = 0% */
1053 : 100.0); /* Tickless CPU: %idle = 100% */
1055 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1058 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1062 /* Check min/max values for %user, etc. */
1063 for (k = 0; k < j; k++) {
1064 if (0.0 < *(spmin + pos + k)) {
1065 *(spmin + pos + k) = 0.0;
1067 if (0.0 > *(spmax + pos + k)) {
1068 *(spmax + pos + k) = 0.0;
1073 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1075 out + pos + j, outsize + pos + j, svg_p->dt,
1076 spmin + pos + j, spmax + pos + j);
1081 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1083 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1084 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv),
1085 out + pos, outsize + pos, svg_p->dt,
1086 spmin + pos, spmax + pos);
1090 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1092 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1094 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1095 scc->cpu_user - scc->cpu_guest, g_itv),
1096 out + pos, outsize + pos, svg_p->dt,
1097 spmin + pos, spmax + pos);
1100 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1102 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1103 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv),
1104 out + pos + 1, outsize + pos + 1, svg_p->dt,
1105 spmin + pos + 1, spmax + pos + 1);
1109 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1111 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1113 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1114 scc->cpu_nice - scc->cpu_guest_nice, g_itv),
1115 out + pos + 1, outsize + pos + 1, svg_p->dt,
1116 spmin + pos + 1, spmax + pos + 1);
1119 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1121 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1123 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1124 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1126 out + pos + 2, outsize + pos + 2, svg_p->dt,
1127 spmin + pos + 2, spmax + pos + 2);
1131 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1132 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv),
1133 out + pos + 2, outsize + pos + 2, svg_p->dt,
1134 spmin + pos + 2, spmax + pos + 2);
1138 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1139 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
1140 out + pos + 3, outsize + pos + 3, svg_p->dt,
1141 spmin + pos + 3, spmax + pos + 3);
1143 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1144 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
1145 out + pos + 4, outsize + pos + 4, svg_p->dt,
1146 spmin + pos + 4, spmax + pos + 4);
1148 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1150 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1151 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv),
1152 out + pos + 5, outsize + pos + 5, svg_p->dt,
1153 spmin + pos + 5, spmax + pos + 5);
1155 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1156 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv),
1157 out + pos + 6, outsize + pos + 6, svg_p->dt,
1158 spmin + pos + 6, spmax + pos + 6);
1160 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1161 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv),
1162 out + pos + 7, outsize + pos + 7, svg_p->dt,
1163 spmin + pos + 7, spmax + pos + 7);
1165 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1166 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, g_itv),
1167 out + pos + 8, outsize + pos + 8, svg_p->dt,
1168 spmin + pos + 8, spmax + pos + 8);
1177 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1179 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1180 ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv)),
1181 out + pos + j, outsize + pos + j, svg_p->dt,
1182 spmin + pos + j, spmax + pos + j);
1186 if (action & F_END) {
1187 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1189 /* Should current CPU (including CPU "all") be displayed? */
1190 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1196 /* This is CPU "all" */
1197 strcpy(item_name, "all");
1200 sprintf(item_name, "%d", i - 1);
1203 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1204 draw_activity_graphs(a->g_nr, g_type,
1205 title, g_title1, item_name, group1,
1206 spmin + pos, spmax + pos, out + pos, outsize + pos,
1210 draw_activity_graphs(a->g_nr, g_type,
1211 title, g_title2, item_name, group2,
1212 spmin + pos, spmax + pos, out + pos, outsize + pos,
1217 /* Free remaining structures */
1218 free_graphs(out, outsize, spmin, spmax);
1223 ***************************************************************************
1224 * Display task creation and context switch statistics in SVG.
1227 * @a Activity structure with statistics.
1228 * @curr Index in array for current sample statistics.
1229 * @action Action expected from current function.
1230 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1231 * flag indicating that a restart record has been previously
1232 * found (.@restart) and time used for the X axis origin
1234 * @itv Interval of time in jiffies (only with F_MAIN action).
1235 * @record_hdr Pointer on record header of current stats sample.
1236 ***************************************************************************
1238 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1239 unsigned long long itv, struct record_header *record_hdr)
1242 *spc = (struct stats_pcsw *) a->buf[curr],
1243 *spp = (struct stats_pcsw *) a->buf[!curr];
1244 int group[] = {1, 1};
1245 int g_fields[] = {1, 0};
1246 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1247 char *title[] = {"Task creation", "Switching activity"};
1248 char *g_title[] = {"proc/s",
1250 static double *spmin, *spmax;
1252 static int *outsize;
1254 if (action & F_BEGIN) {
1256 * Allocate arrays that will contain the graphs data
1257 * and the min/max values.
1259 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1262 if (action & F_MAIN) {
1263 /* Check for min/max values */
1264 save_extrema(1, 1, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1265 itv, spmin, spmax, g_fields);
1267 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1268 S_VALUE(spp->processes, spc->processes, itv),
1269 out, outsize, svg_p->restart);
1271 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1272 S_VALUE(spp->context_switch, spc->context_switch, itv),
1273 out + 1, outsize + 1, svg_p->restart);
1276 if (action & F_END) {
1277 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1278 spmin, spmax, out, outsize, svg_p, record_hdr);
1280 /* Free remaining structures */
1281 free_graphs(out, outsize, spmin, spmax);
1286 ***************************************************************************
1287 * Display swap statistics in SVG.
1290 * @a Activity structure with statistics.
1291 * @curr Index in array for current sample statistics.
1292 * @action Action expected from current function.
1293 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1294 * flag indicating that a restart record has been previously
1295 * found (.@restart) and time used for the X axis origin
1297 * @itv Interval of time in jiffies (only with F_MAIN action).
1298 * @record_hdr Pointer on record header of current stats sample.
1299 ***************************************************************************
1301 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1302 unsigned long long itv, struct record_header *record_hdr)
1305 *ssc = (struct stats_swap *) a->buf[curr],
1306 *ssp = (struct stats_swap *) a->buf[!curr];
1308 int g_type[] = {SVG_LINE_GRAPH};
1309 char *title[] = {"Swap activity"};
1310 char *g_title[] = {"pswpin/s", "pswpout/s" };
1311 int g_fields[] = {0, 1};
1312 static double *spmin, *spmax;
1314 static int *outsize;
1316 if (action & F_BEGIN) {
1318 * Allocate arrays that will contain the graphs data
1319 * and the min/max values.
1321 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1324 if (action & F_MAIN) {
1325 /* Check for min/max values */
1326 save_extrema(0, 2, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1327 itv, spmin, spmax, g_fields);
1329 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1330 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1331 out, outsize, svg_p->restart);
1333 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1334 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1335 out + 1, outsize + 1, svg_p->restart);
1338 if (action & F_END) {
1339 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1340 spmin, spmax, out, outsize, svg_p, record_hdr);
1342 /* Free remaining structures */
1343 free_graphs(out, outsize, spmin, spmax);
1348 ***************************************************************************
1349 * Display paging statistics in SVG.
1352 * @a Activity structure with statistics.
1353 * @curr Index in array for current sample statistics.
1354 * @action Action expected from current function.
1355 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1356 * flag indicating that a restart record has been previously
1357 * found (.@restart) and time used for the X axis origin
1359 * @itv Interval of time in jiffies (only with F_MAIN action).
1360 * @record_hdr Pointer on record header of current stats sample.
1361 ***************************************************************************
1363 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1364 unsigned long long itv, struct record_header *record_hdr)
1367 *spc = (struct stats_paging *) a->buf[curr],
1368 *spp = (struct stats_paging *) a->buf[!curr];
1369 int group[] = {2, 2, 4};
1370 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1371 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1372 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1373 "fault/s", "majflt/s",
1374 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1375 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1376 static double *spmin, *spmax;
1378 static int *outsize;
1380 if (action & F_BEGIN) {
1382 * Allocate arrays that will contain the graphs data
1383 * and the min/max values.
1385 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1388 if (action & F_MAIN) {
1389 /* Check for min/max values */
1390 save_extrema(0, 8, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1391 itv, spmin, spmax, g_fields);
1393 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1394 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1395 out, outsize, svg_p->restart);
1397 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1398 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1399 out + 1, outsize + 1, svg_p->restart);
1401 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1402 S_VALUE(spp->pgfault, spc->pgfault, itv),
1403 out + 2, outsize + 2, svg_p->restart);
1405 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1406 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1407 out + 3, outsize + 3, svg_p->restart);
1409 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1410 S_VALUE(spp->pgfree, spc->pgfree, itv),
1411 out + 4, outsize + 4, svg_p->restart);
1413 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1414 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1415 out + 5, outsize + 5, svg_p->restart);
1417 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1418 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1419 out + 6, outsize + 6, svg_p->restart);
1421 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1422 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1423 out + 7, outsize + 7, svg_p->restart);
1426 if (action & F_END) {
1427 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1428 spmin, spmax, out, outsize, svg_p, record_hdr);
1430 /* Free remaining structures */
1431 free_graphs(out, outsize, spmin, spmax);
1436 ***************************************************************************
1437 * Display I/O and transfer rate statistics in SVG.
1440 * @a Activity structure with statistics.
1441 * @curr Index in array for current sample statistics.
1442 * @action Action expected from current function.
1443 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1444 * flag indicating that a restart record has been previously
1445 * found (.@restart) and time used for the X axis origin
1447 * @itv Interval of time in jiffies (only with F_MAIN action).
1448 * @record_hdr Pointer on record header of current stats sample.
1449 ***************************************************************************
1451 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1452 unsigned long long itv, struct record_header *record_hdr)
1455 *sic = (struct stats_io *) a->buf[curr],
1456 *sip = (struct stats_io *) a->buf[!curr];
1457 int group[] = {3, 2};
1458 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1459 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1460 char *g_title[] = {"tps", "rtps", "wtps",
1461 "bread/s", "bwrtn/s"};
1462 int g_fields[] = {0, 1, 2, 3, 4};
1463 static double *spmin, *spmax;
1465 static int *outsize;
1467 if (action & F_BEGIN) {
1469 * Allocate arrays that will contain the graphs data
1470 * and the min/max values.
1472 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1475 if (action & F_MAIN) {
1476 /* Check for min/max values */
1477 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1478 itv, spmin, spmax, g_fields);
1481 * If we get negative values, this is probably because
1482 * one or more devices/filesystems have been unmounted.
1483 * We display 0.0 in this case though we should rather tell
1484 * the user that the value cannot be calculated here.
1487 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1488 sic->dk_drive < sip->dk_drive ? 0.0 :
1489 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1490 out, outsize, svg_p->restart);
1492 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1493 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1494 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1495 out + 1, outsize + 1, svg_p->restart);
1497 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1498 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1499 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1500 out + 2, outsize + 2, svg_p->restart);
1502 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1503 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1504 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1505 out + 3, outsize + 3, svg_p->restart);
1507 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1508 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1509 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1510 out + 4, outsize + 4, svg_p->restart);
1513 if (action & F_END) {
1514 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1515 spmin, spmax, out, outsize, svg_p, record_hdr);
1517 /* Free remaining structures */
1518 free_graphs(out, outsize, spmin, spmax);
1523 ***************************************************************************
1524 * Display memory statistics in SVG.
1527 * @a Activity structure with statistics.
1528 * @curr Index in array for current sample statistics.
1529 * @action Action expected from current function.
1530 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1531 * flag indicating that a restart record has been previously
1532 * found (.@restart) and time used for the X axis origin
1534 * @itv Interval of time in jiffies (only with F_MAIN action).
1535 * @record_hdr Pointer on record header of current stats sample.
1536 ***************************************************************************
1538 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1539 unsigned long long itv, struct record_header *record_hdr)
1542 *smc = (struct stats_memory *) a->buf[curr];
1543 int group1[] = {3, 1, 3, 1, 3, 5};
1544 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1545 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1546 int group2[] = {3, 1, 1};
1547 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1548 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1549 "Memory utilization (3)", "Memory utilization (4)",
1550 "Memory utilization (5)", "Memory utilization (6)"};
1551 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1552 "Swap utilization (3)"};
1553 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1554 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1555 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1557 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1559 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1560 static double *spmin, *spmax;
1562 static int *outsize;
1566 if (action & F_BEGIN) {
1568 * Allocate arrays that will contain the graphs data
1569 * and the min/max values.
1571 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1574 if (action & F_MAIN) {
1575 /* Check for min/max values */
1576 save_extrema(0, 17, 0, (void *) a->buf[curr], NULL,
1577 itv, spmin, spmax, g_fields);
1578 /* Compute %memused min/max values */
1579 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1580 if (tval > *(spmax + 3)) {
1581 *(spmax + 3) = tval;
1583 if (tval < *(spmin + 3)) {
1584 *(spmin + 3) = tval;
1586 /* Compute %commit min/max values */
1587 tval = (smc->tlmkb + smc->tlskb) ?
1588 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1589 if (tval > *(spmax + 7)) {
1590 *(spmax + 7) = tval;
1592 if (tval < *(spmin + 7)) {
1593 *(spmin + 7) = tval;
1595 /* Compute %swpused min/max values */
1597 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1598 if (tval > *(spmax + 19)) {
1599 *(spmax + 19) = tval;
1601 if (tval < *(spmin + 19)) {
1602 *(spmin + 19) = tval;
1604 /* Compute %swpcad min/max values */
1605 tval = (smc->tlskb - smc->frskb) ?
1606 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1607 if (tval > *(spmax + 20)) {
1608 *(spmax + 20) = tval;
1610 if (tval < *(spmin + 20)) {
1611 *(spmin + 20) = tval;
1613 /* Compute memused min/max values in MB */
1614 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1615 if (tval > *(spmax + 2)) {
1616 *(spmax + 2) = tval;
1618 if (tval < *(spmin + 2)) {
1619 *(spmin + 2) = tval;
1621 /* Compute swpused min/max values in MB */
1622 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1623 if (tval > *(spmax + 17)) {
1624 *(spmax + 17) = tval;
1626 if (tval < *(spmin + 17)) {
1627 *(spmin + 17) = tval;
1631 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1632 ((double) smc->frmkb) / 1024,
1633 out, outsize, svg_p->restart);
1635 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1636 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1637 out + 2, outsize + 2, svg_p->restart);
1639 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1640 ((double) smc->availablekb) / 1024,
1641 out + 1, outsize + 1, svg_p->restart);
1643 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1644 ((double) smc->bufkb) / 1024,
1645 out + 4, outsize + 4, svg_p->restart);
1647 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1648 ((double) smc->camkb) / 1024,
1649 out + 5, outsize + 5, svg_p->restart);
1651 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1652 ((double) smc->frskb) / 1024,
1653 out + 16, outsize + 16, svg_p->restart);
1655 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1656 ((double) (smc->tlskb - smc->frskb)) / 1024,
1657 out + 17, outsize + 17, svg_p->restart);
1659 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1660 ((double) smc->caskb) / 1024,
1661 out + 18, outsize + 18, svg_p->restart);
1663 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1664 ((double) smc->comkb) / 1024,
1665 out + 6, outsize + 6, svg_p->restart);
1667 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1668 ((double) smc->activekb) / 1024,
1669 out + 8, outsize + 8, svg_p->restart);
1671 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1672 ((double) smc->inactkb) / 1024,
1673 out + 9, outsize + 9, svg_p->restart);
1675 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1676 ((double) smc->dirtykb) / 1024,
1677 out + 10, outsize + 10, svg_p->restart);
1679 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1680 ((double) smc->anonpgkb) / 1024,
1681 out + 11, outsize + 11, svg_p->restart);
1683 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1684 ((double) smc->slabkb) / 1024,
1685 out + 12, outsize + 12, svg_p->restart);
1687 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1688 ((double) smc->kstackkb) / 1024,
1689 out + 13, outsize + 13, svg_p->restart);
1691 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1692 ((double) smc->pgtblkb) / 1024,
1693 out + 14, outsize + 14, svg_p->restart);
1695 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1696 ((double) smc->vmusedkb) / 1024,
1697 out + 15, outsize + 15, svg_p->restart);
1699 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1702 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1703 out + 3, outsize + 3, svg_p->dt);
1705 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1707 (smc->tlmkb + smc->tlskb) ?
1708 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1709 out + 7, outsize + 7, svg_p->dt);
1711 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1714 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1715 out + 19, outsize + 19, svg_p->dt);
1717 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1719 (smc->tlskb - smc->frskb) ?
1720 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1721 out + 20, outsize + 20, svg_p->dt);
1724 if (action & F_END) {
1726 /* Conversion kB -> MB */
1727 for (i = 0; i < 17; i++) {
1728 *(spmin + g_fields[i]) /= 1024;
1729 *(spmax + g_fields[i]) /= 1024;
1732 if (DISPLAY_MEM_AMT(a->opt_flags)) {
1733 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1734 g_type1, title1, g_title1, NULL, group1,
1735 spmin, spmax, out, outsize, svg_p, record_hdr);
1738 if (DISPLAY_SWAP(a->opt_flags)) {
1739 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1740 spmin + 15, spmax + 15, out + 15, outsize + 15,
1744 /* Free remaining structures */
1745 free_graphs(out, outsize, spmin, spmax);
1750 ***************************************************************************
1751 * Display kernel tables statistics in SVG.
1754 * @a Activity structure with statistics.
1755 * @curr Index in array for current sample statistics.
1756 * @action Action expected from current function.
1757 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1758 * flag indicating that a restart record has been previously
1759 * found (.@restart) and time used for the X axis origin
1761 * @itv Interval of time in jiffies (only with F_MAIN action).
1762 * @record_hdr Pointer on record header of current stats sample.
1763 ***************************************************************************
1765 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1766 unsigned long long itv, struct record_header *record_hdr)
1768 struct stats_ktables
1769 *skc = (struct stats_ktables *) a->buf[curr];
1770 int group[] = {3, 1};
1771 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1772 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1773 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1775 int g_fields[] = {1, 2, 0, 3};
1776 static double *spmin, *spmax;
1778 static int *outsize;
1780 if (action & F_BEGIN) {
1782 * Allocate arrays that will contain the graphs data
1783 * and the min/max values.
1785 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1788 if (action & F_MAIN) {
1789 /* Check for min/max values */
1790 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
1791 itv, spmin, spmax, g_fields);
1793 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1794 (unsigned long) skc->dentry_stat,
1795 out, outsize, svg_p->restart);
1797 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1798 (unsigned long) skc->file_used,
1799 out + 1, outsize + 1, svg_p->restart);
1801 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1802 (unsigned long) skc->inode_used,
1803 out + 2, outsize + 2, svg_p->restart);
1805 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1806 (unsigned long) skc->pty_nr,
1807 out + 3, outsize + 3, svg_p->restart);
1810 if (action & F_END) {
1811 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1812 spmin, spmax, out, outsize, svg_p, record_hdr);
1814 /* Free remaining structures */
1815 free_graphs(out, outsize, spmin, spmax);
1820 ***************************************************************************
1821 * Display queue and load statistics in SVG.
1824 * @a Activity structure with statistics.
1825 * @curr Index in array for current sample statistics.
1826 * @action Action expected from current function.
1827 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1828 * flag indicating that a restart record has been previously
1829 * found (.@restart) and time used for the X axis origin
1831 * @itv Interval of time in jiffies (only with F_MAIN action).
1832 * @record_hdr Pointer on record header of current stats sample.
1833 ***************************************************************************
1835 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1836 unsigned long long itv, struct record_header *record_hdr)
1839 *sqc = (struct stats_queue *) a->buf[curr];
1840 int group[] = {2, 1, 3};
1841 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1842 char *title[] = {"Queue length", "Task list", "Load average"};
1843 char *g_title[] = {"~runq-sz", "~blocked",
1845 "ldavg-1", "ldavg-5", "ldavg-15"};
1846 int g_fields[] = {0, 1, 3, 4, 5, 2};
1847 static double *spmin, *spmax;
1849 static int *outsize;
1851 if (action & F_BEGIN) {
1853 * Allocate arrays that will contain the graphs data
1854 * and the min/max values.
1856 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1859 if (action & F_MAIN) {
1860 /* Check for min/max values */
1861 save_extrema(0, 2, 4, (void *) a->buf[curr], NULL,
1862 itv, spmin, spmax, g_fields);
1864 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1865 (unsigned long) sqc->nr_running,
1866 out, outsize, svg_p->restart);
1868 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1869 (unsigned long) sqc->procs_blocked,
1870 out + 1, outsize + 1, svg_p->restart);
1872 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1873 (unsigned long) sqc->nr_threads,
1874 out + 2, outsize + 2, svg_p->restart);
1876 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1877 (double) sqc->load_avg_1 / 100,
1878 out + 3, outsize + 3, svg_p->restart);
1880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1881 (double) sqc->load_avg_5 / 100,
1882 out + 4, outsize + 4, svg_p->restart);
1884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1885 (double) sqc->load_avg_15 / 100,
1886 out + 5, outsize + 5, svg_p->restart);
1889 if (action & F_END) {
1890 /* Fix min/max values for load average */
1891 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1892 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1893 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1895 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1896 spmin, spmax, out, outsize, svg_p, record_hdr);
1898 /* Free remaining structures */
1899 free_graphs(out, outsize, spmin, spmax);
1904 ***************************************************************************
1905 * Display disk statistics in SVG.
1908 * @a Activity structure with statistics.
1909 * @curr Index in array for current sample statistics.
1910 * @action Action expected from current function.
1911 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1912 * flag indicating that a restart record has been previously
1913 * found (.@restart) and time used for the X axis origin
1915 * @itv Interval of time in jiffies (only with F_MAIN action).
1916 * @record_hdr Pointer on record header of current stats sample.
1917 ***************************************************************************
1919 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1920 unsigned long long itv, struct record_header *record_hdr)
1922 struct stats_disk *sdc, *sdp;
1923 struct ext_disk_stats xds;
1924 int group[] = {1, 2, 2, 2, 1};
1925 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
1926 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
1927 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
1928 "Disk statistics (3)", "Disk statistics (4)",
1929 "Disk statistics (5)"};
1930 char *g_title[] = {"tps",
1931 "rd_sec/s", "wr_sec/s",
1932 "avgrq-sz", "avgqu-sz",
1935 int g_fields[] = {0, 1, 2};
1936 static double *spmin, *spmax;
1938 static int *outsize;
1939 char *item_name, *persist_dev_name;
1941 int i, j, k, pos, restart, *unregistered;
1943 if (action & F_BEGIN) {
1945 * Allocate arrays (#0..7) that will contain the graphs data
1946 * and the min/max values.
1947 * Also allocate one additional array (#8) for each disk device:
1948 * spmax + 8 will contain the device major number,
1949 * spmin + 8 will contain the device minor number,
1950 * outsize + 8 will contain a positive value (TRUE) if the device
1951 * has either still not been registered, or has been unregistered.
1953 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
1956 if (action & F_MAIN) {
1957 restart = svg_p->restart;
1959 * Mark previously registered devices as now
1960 * possibly unregistered for all graphs.
1962 for (k = 0; k < a->nr; k++) {
1963 unregistered = outsize + k * 9 + 8;
1964 if (*unregistered == FALSE) {
1965 *unregistered = MAYBE;
1969 /* For each device structure */
1970 for (i = 0; i < a->nr; i++) {
1971 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
1972 if (!(sdc->major + sdc->minor))
1973 /* Empty structure: Ignore it */
1976 /* Look for corresponding graph */
1977 for (k = 0; k < a->nr; k++) {
1978 if ((sdc->major == *(spmax + k * 9 + 8)) &&
1979 (sdc->minor == *(spmin + k * 9 + 8)))
1984 /* Graph not found: Look for first free entry */
1985 for (k = 0; k < a->nr; k++) {
1986 if (*(spmax + k * 9 + 8) == -DBL_MAX)
1990 /* No free graph entry: Graph for this item won't be drawn */
1994 unregistered = outsize + pos + 8;
1996 j = check_disk_reg(a, curr, !curr, i);
1997 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2000 * If current device was marked as previously unregistered,
2001 * then set restart variable to TRUE so that the graph will be
2002 * discontinuous, and mark it as now registered.
2004 if (*unregistered == TRUE) {
2007 *unregistered = FALSE;
2009 if (*(spmax + pos + 8) == -DBL_MAX) {
2010 /* Save device major and minor numbers (if not already done) */
2011 *(spmax + pos + 8) = sdc->major;
2012 *(spmin + pos + 8) = sdc->minor;
2015 /* Check for min/max values */
2016 save_extrema(1, 2, 0, (void *) sdc, (void *) sdp,
2017 itv, spmin + pos, spmax + pos, g_fields);
2019 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2020 if (xds.arqsz < *(spmin + pos + 3)) {
2021 *(spmin + pos + 3) = xds.arqsz;
2023 if (xds.arqsz > *(spmax + pos + 3)) {
2024 *(spmax + pos + 3) = xds.arqsz;
2026 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2027 if (aqusz < *(spmin + pos + 4)) {
2028 *(spmin + pos + 4) = aqusz;
2030 if (aqusz > *(spmax + pos + 4)) {
2031 *(spmax + pos + 4) = aqusz;
2033 if (xds.await < *(spmin + pos + 5)) {
2034 *(spmin + pos + 5) = xds.await;
2036 if (xds.await > *(spmax + pos + 5)) {
2037 *(spmax + pos + 5) = xds.await;
2039 if (xds.svctm < *(spmin + pos + 6)) {
2040 *(spmin + pos + 6) = xds.svctm;
2042 if (xds.svctm > *(spmax + pos + 6)) {
2043 *(spmax + pos + 6) = xds.svctm;
2045 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2046 *(spmin + pos + 7) = xds.util / 10.0;
2048 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2049 *(spmax + pos + 7) = xds.util / 10.0;
2053 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2054 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2055 out + pos, outsize + pos, restart);
2057 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2058 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv),
2059 out + pos + 1, outsize + pos + 1, restart);
2061 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2062 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv),
2063 out + pos + 2, outsize + pos + 2, restart);
2065 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2067 out + pos + 3, outsize + pos + 3, restart);
2069 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2071 out + pos + 4, outsize + pos + 4, restart);
2073 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2075 out + pos + 5, outsize + pos + 5, restart);
2077 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2079 out + pos + 6, outsize + pos + 6, restart);
2081 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2082 0.0, xds.util / 10.0,
2083 out + pos + 7, outsize + pos + 7, svg_p->dt);
2086 /* Mark devices not seen here as now unregistered */
2087 for (k = 0; k < a->nr; k++) {
2088 unregistered = outsize + k * 9 + 8;
2089 if (*unregistered != FALSE) {
2090 *unregistered = TRUE;
2095 if (action & F_END) {
2096 for (i = 0; i < a->nr; i++) {
2097 /* Check if there is something to display */
2103 persist_dev_name = NULL;
2105 if (DISPLAY_PERSIST_NAME_S(flags)) {
2106 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2110 if (persist_dev_name) {
2111 item_name = persist_dev_name;
2114 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2115 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2119 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2120 USE_PRETTY_OPTION(flags));
2124 draw_activity_graphs(a->g_nr, g_type,
2125 title, g_title, item_name, group,
2126 spmin + pos, spmax + pos, out + pos, outsize + pos,
2130 /* Free remaining structures */
2131 free_graphs(out, outsize, spmin, spmax);
2136 ***************************************************************************
2137 * Display network interfaces statistics in SVG.
2140 * @a Activity structure with statistics.
2141 * @curr Index in array for current sample statistics.
2142 * @action Action expected from current function.
2143 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2144 * flag indicating that a restart record has been previously
2145 * found (.@restart) and time used for the X axis origin
2147 * @itv Interval of time in jiffies (only with F_MAIN action).
2148 * @record_hdr Pointer on record header of current stats sample.
2149 ***************************************************************************
2151 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2152 unsigned long long itv, struct record_header *record_hdr)
2154 struct stats_net_dev *sndc, *sndp;
2155 int group[] = {2, 2, 3, 1};
2156 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2158 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2159 "Network statistics (3)", "Network statistics (4)"};
2160 char *g_title[] = {"rxpck/s", "txpck/s",
2162 "rxcmp/s", "txcmp/s", "rxmcst/s",
2164 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2165 static double *spmin, *spmax;
2167 static int *outsize;
2169 double rxkb, txkb, ifutil;
2170 int i, j, k, pos, restart, *unregistered;
2172 if (action & F_BEGIN) {
2174 * Allocate arrays (#0..7) that will contain the graphs data
2175 * and the min/max values.
2176 * Also allocate one additional array (#8) for each interface:
2177 * out + 8 will contain the interface name,
2178 * outsize + 8 will contain a positive value (TRUE) if the interface
2179 * has either still not been registered, or has been unregistered.
2181 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2184 if (action & F_MAIN) {
2185 restart = svg_p->restart;
2187 * Mark previously registered interfaces as now
2188 * possibly unregistered for all graphs.
2190 for (k = 0; k < a->nr; k++) {
2191 unregistered = outsize + k * 9 + 8;
2192 if (*unregistered == FALSE) {
2193 *unregistered = MAYBE;
2197 /* For each network interfaces structure */
2198 for (i = 0; i < a->nr; i++) {
2199 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2200 if (!strcmp(sndc->interface, ""))
2201 /* Empty structure: Ignore it */
2204 /* Look for corresponding graph */
2205 for (k = 0; k < a->nr; k++) {
2206 item_name = *(out + k * 9 + 8);
2207 if (!strcmp(sndc->interface, item_name))
2212 /* Graph not found: Look for first free entry */
2213 for (k = 0; k < a->nr; k++) {
2214 item_name = *(out + k * 9 + 8);
2215 if (!strcmp(item_name, ""))
2219 /* No free graph entry: Graph for this item won't be drawn */
2224 unregistered = outsize + pos + 8;
2226 j = check_net_dev_reg(a, curr, !curr, i);
2227 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2230 * If current interface was marked as previously unregistered,
2231 * then set restart variable to TRUE so that the graph will be
2232 * discontinuous, and mark it as now registered.
2234 if (*unregistered == TRUE) {
2237 *unregistered = FALSE;
2239 if (!item_name[0]) {
2240 /* Save network interface name (if not already done) */
2241 strncpy(item_name, sndc->interface, CHUNKSIZE);
2242 item_name[CHUNKSIZE - 1] = '\0';
2245 /* Check for min/max values */
2246 save_extrema(7, 0, 0, (void *) sndc, (void *) sndp,
2247 itv, spmin + pos, spmax + pos, g_fields);
2249 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2250 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2251 ifutil = compute_ifutil(sndc, rxkb, txkb);
2252 if (ifutil < *(spmin + pos + 7)) {
2253 *(spmin + pos + 7) = ifutil;
2255 if (ifutil > *(spmax + pos + 7)) {
2256 *(spmax + pos + 7) = ifutil;
2260 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2261 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2262 out + pos, outsize + pos, restart);
2264 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2265 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2266 out + pos + 1, outsize + pos + 1, restart);
2268 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2270 out + pos + 2, outsize + pos + 2, restart);
2272 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2274 out + pos + 3, outsize + pos + 3, restart);
2276 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2277 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2278 out + pos + 4, outsize + pos + 4, restart);
2280 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2281 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2282 out + pos + 5, outsize + pos + 5, restart);
2284 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2285 S_VALUE(sndp->multicast, sndc->multicast, itv),
2286 out + pos + 6, outsize + pos + 6, restart);
2288 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2290 out + pos + 7, outsize + pos + 7, svg_p->dt);
2293 /* Mark interfaces not seen here as now unregistered */
2294 for (k = 0; k < a->nr; k++) {
2295 unregistered = outsize + k * 9 + 8;
2296 if (*unregistered != FALSE) {
2297 *unregistered = TRUE;
2302 if (action & F_END) {
2303 for (i = 0; i < a->nr; i++) {
2305 * Check if there is something to display.
2306 * Don't test sndc->interface because maybe the network
2307 * interface has been registered later.
2313 /* Recalculate min and max values in kB, not in B */
2314 *(spmin + pos + 2) /= 1024;
2315 *(spmax + pos + 2) /= 1024;
2316 *(spmin + pos + 3) /= 1024;
2317 *(spmax + pos + 3) /= 1024;
2319 item_name = *(out + pos + 8);
2320 draw_activity_graphs(a->g_nr, g_type,
2321 title, g_title, item_name, group,
2322 spmin + pos, spmax + pos, out + pos, outsize + pos,
2326 /* Free remaining structures */
2327 free_graphs(out, outsize, spmin, spmax);
2332 ***************************************************************************
2333 * Display network interface errors statistics in SVG.
2336 * @a Activity structure with statistics.
2337 * @curr Index in array for current sample statistics.
2338 * @action Action expected from current function.
2339 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2340 * flag indicating that a restart record has been previously
2341 * found (.@restart) and time used for the X axis origin
2343 * @itv Interval of time in jiffies (only with F_MAIN action).
2344 * @record_hdr Pointer on record header of current stats sample.
2345 ***************************************************************************
2347 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2348 unsigned long long itv, struct record_header *record_hdr)
2350 struct stats_net_edev *snedc, *snedp;
2351 int group[] = {2, 2, 2, 3};
2352 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2354 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2355 "Network errors statistics (3)", "Network errors statistics (4)"};
2356 char *g_title[] = {"rxerr/s", "txerr/s",
2357 "rxdrop/s", "txdrop/s",
2358 "rxfifo/s", "txfifo/s",
2359 "coll/s", "txcarr/s", "rxfram/s"};
2360 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2361 static double *spmin, *spmax;
2363 static int *outsize;
2365 int i, j, k, pos, restart, *unregistered;
2367 if (action & F_BEGIN) {
2369 * Allocate arrays (#0..8) that will contain the graphs data
2370 * and the min/max values.
2371 * Also allocate one additional array (#9) for each interface:
2372 * out + 9 will contain the interface name,
2373 * outsize + 9 will contain a positive value (TRUE) if the interface
2374 * has either still not been registered, or has been unregistered.
2376 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
2379 if (action & F_MAIN) {
2380 restart = svg_p->restart;
2382 * Mark previously registered interfaces as now
2383 * possibly unregistered for all graphs.
2385 for (k = 0; k < a->nr; k++) {
2386 unregistered = outsize + k * 10 + 9;
2387 if (*unregistered == FALSE) {
2388 *unregistered = MAYBE;
2392 /* For each network interfaces structure */
2393 for (i = 0; i < a->nr; i++) {
2394 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2395 if (!strcmp(snedc->interface, ""))
2396 /* Empty structure: Ignore it */
2399 /* Look for corresponding graph */
2400 for (k = 0; k < a->nr; k++) {
2401 item_name = *(out + k * 10 + 9);
2402 if (!strcmp(snedc->interface, item_name))
2407 /* Graph not found: Look for first free entry */
2408 for (k = 0; k < a->nr; k++) {
2409 item_name = *(out + k * 10 + 9);
2410 if (!strcmp(item_name, ""))
2414 /* No free graph entry: Graph for this item won't be drawn */
2419 unregistered = outsize + pos + 9;
2421 j = check_net_edev_reg(a, curr, !curr, i);
2422 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2425 * If current interface was marked as previously unregistered,
2426 * then set restart variable to TRUE so that the graph will be
2427 * discontinuous, and mark it as now registered.
2429 if (*unregistered == TRUE) {
2432 *unregistered = FALSE;
2434 if (!item_name[0]) {
2435 /* Save network interface name (if not already done) */
2436 strncpy(item_name, snedc->interface, CHUNKSIZE);
2437 item_name[CHUNKSIZE - 1] = '\0';
2440 /* Check for min/max values */
2441 save_extrema(9, 0, 0, (void *) snedc, (void *) snedp,
2442 itv, spmin + pos, spmax + pos, g_fields);
2445 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2446 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2447 out + pos, outsize + pos, restart);
2449 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2450 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2451 out + pos + 1, outsize + pos + 1, restart);
2453 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2454 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2455 out + pos + 2, outsize + pos + 2, restart);
2457 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2458 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2459 out + pos + 3, outsize + pos + 3, restart);
2461 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2462 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2463 out + pos + 4, outsize + pos + 4, restart);
2465 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2466 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2467 out + pos + 5, outsize + pos + 5, restart);
2469 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2470 S_VALUE(snedp->collisions, snedc->collisions, itv),
2471 out + pos + 6, outsize + pos + 6, restart);
2473 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2474 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2475 out + pos + 7, outsize + pos + 7, restart);
2477 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2478 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2479 out + pos + 8, outsize + pos + 8, restart);
2482 /* Mark interfaces not seen here as now unregistered */
2483 for (k = 0; k < a->nr; k++) {
2484 unregistered = outsize + k * 10 + 9;
2485 if (*unregistered != FALSE) {
2486 *unregistered = TRUE;
2491 if (action & F_END) {
2492 for (i = 0; i < a->nr; i++) {
2494 * Check if there is something to display.
2495 * Don't test snedc->interface because maybe the network
2496 * interface has been registered later.
2502 item_name = *(out + pos + 9);
2503 draw_activity_graphs(a->g_nr, g_type,
2504 title, g_title, item_name, group,
2505 spmin + pos, spmax + pos, out + pos, outsize + pos,
2509 /* Free remaining structures */
2510 free_graphs(out, outsize, spmin, spmax);
2515 ***************************************************************************
2516 * Display NFS client statistics in SVG.
2519 * @a Activity structure with statistics.
2520 * @curr Index in array for current sample statistics.
2521 * @action Action expected from current function.
2522 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2523 * flag indicating that a restart record has been previously
2524 * found (.@restart) and time used for the X axis origin
2526 * @itv Interval of time in jiffies (only with F_MAIN action).
2527 * @record_hdr Pointer on record header of current stats sample.
2528 ***************************************************************************
2530 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2531 unsigned long long itv, struct record_header *record_hdr)
2533 struct stats_net_nfs
2534 *snnc = (struct stats_net_nfs *) a->buf[curr],
2535 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2536 int group[] = {2, 2, 2};
2537 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2538 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2539 "NFS client statistics (3)"};
2540 char *g_title[] = {"call/s", "retrans/s",
2541 "read/s", "write/s",
2542 "access/s", "getatt/s"};
2543 int g_fields[] = {0, 1, 2, 3, 4, 5};
2544 static double *spmin, *spmax;
2546 static int *outsize;
2548 if (action & F_BEGIN) {
2550 * Allocate arrays that will contain the graphs data
2551 * and the min/max values.
2553 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2556 if (action & F_MAIN) {
2557 /* Check for min/max values */
2558 save_extrema(0, 0, 6, (void *) a->buf[curr], (void *) a->buf[!curr],
2559 itv, spmin, spmax, g_fields);
2562 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2563 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2564 out, outsize, svg_p->restart);
2566 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2567 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2568 out + 1, outsize + 1, svg_p->restart);
2570 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2571 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2572 out + 2, outsize + 2, svg_p->restart);
2574 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2575 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2576 out + 3, outsize + 3, svg_p->restart);
2578 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2579 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2580 out + 4, outsize + 4, svg_p->restart);
2582 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2583 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2584 out + 5, outsize + 5, svg_p->restart);
2587 if (action & F_END) {
2588 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2589 spmin, spmax, out, outsize, svg_p, record_hdr);
2591 /* Free remaining structures */
2592 free_graphs(out, outsize, spmin, spmax);
2597 ***************************************************************************
2598 * Display NFS server statistics in SVG.
2601 * @a Activity structure with statistics.
2602 * @curr Index in array for current sample statistics.
2603 * @action Action expected from current function.
2604 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2605 * flag indicating that a restart record has been previously
2606 * found (.@restart) and time used for the X axis origin
2608 * @itv Interval of time in jiffies (only with F_MAIN action).
2609 * @record_hdr Pointer on record header of current stats sample.
2610 ***************************************************************************
2612 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2613 unsigned long long itv, struct record_header *record_hdr)
2615 struct stats_net_nfsd
2616 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2617 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2618 int group[] = {2, 3, 2, 2, 2};
2619 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2620 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2621 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2622 "NFS server statistics (3)", "NFS server statistics (4)",
2623 "NFS server statistics (5)"};
2624 char *g_title[] = {"scall/s", "badcall/s",
2625 "packet/s", "udp/s", "tcp/s",
2627 "sread/s", "swrite/s",
2628 "saccess/s", "sgetatt/s"};
2629 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2630 static double *spmin, *spmax;
2632 static int *outsize;
2634 if (action & F_BEGIN) {
2636 * Allocate arrays that will contain the graphs data
2637 * and the min/max values.
2639 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2642 if (action & F_MAIN) {
2643 /* Check for min/max values */
2644 save_extrema(0, 0, 11, (void *) a->buf[curr], (void *) a->buf[!curr],
2645 itv, spmin, spmax, g_fields);
2648 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2649 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2650 out, outsize, svg_p->restart);
2652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2653 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2654 out + 1, outsize + 1, svg_p->restart);
2656 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2657 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2658 out + 2, outsize + 2, svg_p->restart);
2660 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2661 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2662 out + 3, outsize + 3, svg_p->restart);
2664 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2665 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2666 out + 4, outsize + 4, svg_p->restart);
2668 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2669 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2670 out + 5, outsize + 5, svg_p->restart);
2672 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2673 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2674 out + 6, outsize + 6, svg_p->restart);
2676 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2677 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2678 out + 7, outsize + 7, svg_p->restart);
2680 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2681 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2682 out + 8, outsize + 8, svg_p->restart);
2684 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2685 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2686 out + 9, outsize + 9, svg_p->restart);
2688 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2689 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2690 out + 10, outsize + 10, svg_p->restart);
2693 if (action & F_END) {
2694 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2695 spmin, spmax, out, outsize, svg_p, record_hdr);
2697 /* Free remaining structures */
2698 free_graphs(out, outsize, spmin, spmax);
2703 ***************************************************************************
2704 * Display network socket statistics in SVG.
2707 * @a Activity structure with statistics.
2708 * @curr Index in array for current sample statistics.
2709 * @action Action expected from current function.
2710 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2711 * flag indicating that a restart record has been previously
2712 * found (.@restart) and time used for the X axis origin
2714 * @itv Interval of time in jiffies (only with F_MAIN action).
2715 * @record_hdr Pointer on record header of current stats sample.
2716 ***************************************************************************
2718 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2719 unsigned long long itv, struct record_header *record_hdr)
2721 struct stats_net_sock
2722 *snsc = (struct stats_net_sock *) a->buf[curr];
2723 int group[] = {1, 5};
2724 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2725 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2726 char *g_title[] = {"~totsck",
2727 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2728 int g_fields[] = {0, 1, 5, 2, 3, 4};
2729 static double *spmin, *spmax;
2731 static int *outsize;
2733 if (action & F_BEGIN) {
2735 * Allocate arrays that will contain the graphs data
2736 * and the min/max values.
2738 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2741 if (action & F_MAIN) {
2742 /* Check for min/max values */
2743 save_extrema(0, 0, 6, (void *) a->buf[curr], NULL,
2744 itv, spmin, spmax, g_fields);
2746 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2747 (unsigned long) snsc->sock_inuse,
2748 out, outsize, svg_p->restart);
2750 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2751 (unsigned long) snsc->tcp_inuse,
2752 out + 1, outsize + 1, svg_p->restart);
2754 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2755 (unsigned long) snsc->udp_inuse,
2756 out + 2, outsize + 2, svg_p->restart);
2758 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2759 (unsigned long) snsc->raw_inuse,
2760 out + 3, outsize + 3, svg_p->restart);
2762 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2763 (unsigned long) snsc->frag_inuse,
2764 out + 4, outsize + 4, svg_p->restart);
2766 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2767 (unsigned long) snsc->tcp_tw,
2768 out + 5, outsize + 5, svg_p->restart);
2771 if (action & F_END) {
2772 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2773 spmin, spmax, out, outsize, svg_p, record_hdr);
2775 /* Free remaining structures */
2776 free_graphs(out, outsize, spmin, spmax);
2781 ***************************************************************************
2782 * Display IPv4 network statistics in SVG.
2785 * @a Activity structure with statistics.
2786 * @curr Index in array for current sample statistics.
2787 * @action Action expected from current function.
2788 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2789 * flag indicating that a restart record has been previously
2790 * found (.@restart) and time used for the X axis origin
2792 * @itv Interval of time in jiffies (only with F_MAIN action).
2793 * @record_hdr Pointer on record header of current stats sample.
2794 ***************************************************************************
2796 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2797 unsigned long long itv, struct record_header *record_hdr)
2800 *snic = (struct stats_net_ip *) a->buf[curr],
2801 *snip = (struct stats_net_ip *) a->buf[!curr];
2802 int group[] = {4, 2, 2};
2803 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2804 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2805 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2806 "asmrq/s", "asmok/s",
2807 "fragok/s", "fragcrt/s"};
2808 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2809 static double *spmin, *spmax;
2811 static int *outsize;
2813 if (action & F_BEGIN) {
2815 * Allocate arrays that will contain the graphs data
2816 * and the min/max values.
2818 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2821 if (action & F_MAIN) {
2822 /* Check for min/max values */
2823 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2824 itv, spmin, spmax, g_fields);
2827 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2828 S_VALUE(snip->InReceives, snic->InReceives, itv),
2829 out, outsize, svg_p->restart);
2831 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2832 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2833 out + 1, outsize + 1, svg_p->restart);
2835 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2836 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2837 out + 2, outsize + 2, svg_p->restart);
2839 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2840 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2841 out + 3, outsize + 3, svg_p->restart);
2843 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2844 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2845 out + 4, outsize + 4, svg_p->restart);
2847 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2848 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2849 out + 5, outsize + 5, svg_p->restart);
2851 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2852 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2853 out + 6, outsize + 6, svg_p->restart);
2855 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2856 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2857 out + 7, outsize + 7, svg_p->restart);
2860 if (action & F_END) {
2861 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2862 spmin, spmax, out, outsize, svg_p, record_hdr);
2864 /* Free remaining structures */
2865 free_graphs(out, outsize, spmin, spmax);
2870 ***************************************************************************
2871 * Display IPv4 network errors statistics in SVG.
2874 * @a Activity structure with statistics.
2875 * @curr Index in array for current sample statistics.
2876 * @action Action expected from current function.
2877 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2878 * flag indicating that a restart record has been previously
2879 * found (.@restart) and time used for the X axis origin
2881 * @itv Interval of time in jiffies (only with F_MAIN action).
2882 * @record_hdr Pointer on record header of current stats sample.
2883 ***************************************************************************
2885 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2886 unsigned long long itv, struct record_header *record_hdr)
2888 struct stats_net_eip
2889 *sneic = (struct stats_net_eip *) a->buf[curr],
2890 *sneip = (struct stats_net_eip *) a->buf[!curr];
2891 int group[] = {3, 2, 3};
2892 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2893 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
2894 "IPv4 network errors statistics (3)"};
2895 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
2896 "idisc/s", "odisc/s",
2897 "onort/s", "asmf/s", "fragf/s"};
2898 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2899 static double *spmin, *spmax;
2901 static int *outsize;
2903 if (action & F_BEGIN) {
2905 * Allocate arrays that will contain the graphs data
2906 * and the min/max values.
2908 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2911 if (action & F_MAIN) {
2912 /* Check for min/max values */
2913 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2914 itv, spmin, spmax, g_fields);
2917 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2918 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
2919 out, outsize, svg_p->restart);
2921 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2922 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
2923 out + 1, outsize + 1, svg_p->restart);
2925 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2926 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
2927 out + 2, outsize + 2, svg_p->restart);
2929 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2930 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
2931 out + 3, outsize + 3, svg_p->restart);
2933 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2934 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
2935 out + 4, outsize + 4, svg_p->restart);
2937 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2938 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
2939 out + 5, outsize + 5, svg_p->restart);
2941 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2942 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
2943 out + 6, outsize + 6, svg_p->restart);
2945 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2946 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
2947 out + 7, outsize + 7, svg_p->restart);
2950 if (action & F_END) {
2951 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2952 spmin, spmax, out, outsize, svg_p, record_hdr);
2954 /* Free remaining structures */
2955 free_graphs(out, outsize, spmin, spmax);
2960 ***************************************************************************
2961 * Display ICMPv4 network statistics in SVG.
2964 * @a Activity structure with statistics.
2965 * @curr Index in array for current sample statistics.
2966 * @action Action expected from current function.
2967 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2968 * flag indicating that a restart record has been previously
2969 * found (.@restart) and time used for the X axis origin
2971 * @itv Interval of time in jiffies (only with F_MAIN action).
2972 * @record_hdr Pointer on record header of current stats sample.
2973 ***************************************************************************
2975 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2976 unsigned long long itv, struct record_header *record_hdr)
2978 struct stats_net_icmp
2979 *snic = (struct stats_net_icmp *) a->buf[curr],
2980 *snip = (struct stats_net_icmp *) a->buf[!curr];
2981 int group[] = {2, 4, 4, 4};
2982 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2984 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
2985 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
2986 char *g_title[] = {"imsg/s", "omsg/s",
2987 "iech/s", "iechr/s", "oech/s", "oechr/s",
2988 "itm/s", "itmr/s", "otm/s", "otmr/s",
2989 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
2990 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
2991 static double *spmin, *spmax;
2993 static int *outsize;
2995 if (action & F_BEGIN) {
2997 * Allocate arrays that will contain the graphs data
2998 * and the min/max values.
3000 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3003 if (action & F_MAIN) {
3004 /* Check for min/max values */
3005 save_extrema(0, 14, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3006 itv, spmin, spmax, g_fields);
3009 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3010 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3011 out, outsize, svg_p->restart);
3013 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3014 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3015 out + 1, outsize + 1, svg_p->restart);
3017 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3018 S_VALUE(snip->InEchos, snic->InEchos, itv),
3019 out + 2, outsize + 2, svg_p->restart);
3021 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3022 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3023 out + 3, outsize + 3, svg_p->restart);
3025 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3026 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3027 out + 4, outsize + 4, svg_p->restart);
3029 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3030 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3031 out + 5, outsize + 5, svg_p->restart);
3033 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3034 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3035 out + 6, outsize + 6, svg_p->restart);
3037 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3038 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3039 out + 7, outsize + 7, svg_p->restart);
3041 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3042 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3043 out + 8, outsize + 8, svg_p->restart);
3045 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3046 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3047 out + 9, outsize + 9, svg_p->restart);
3049 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3050 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3051 out + 10, outsize + 10, svg_p->restart);
3053 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3054 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3055 out + 11, outsize + 11, svg_p->restart);
3057 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3058 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3059 out + 12, outsize + 12, svg_p->restart);
3061 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3062 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3063 out + 13, outsize + 13, svg_p->restart);
3066 if (action & F_END) {
3067 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3068 spmin, spmax, out, outsize, svg_p, record_hdr);
3070 /* Free remaining structures */
3071 free_graphs(out, outsize, spmin, spmax);
3076 ***************************************************************************
3077 * Display ICMPv4 network errors statistics in SVG.
3080 * @a Activity structure with statistics.
3081 * @curr Index in array for current sample statistics.
3082 * @action Action expected from current function.
3083 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3084 * flag indicating that a restart record has been previously
3085 * found (.@restart) and time used for the X axis origin
3087 * @itv Interval of time in jiffies (only with F_MAIN action).
3088 * @record_hdr Pointer on record header of current stats sample.
3089 ***************************************************************************
3091 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3092 unsigned long long itv, struct record_header *record_hdr)
3094 struct stats_net_eicmp
3095 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3096 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3097 int group[] = {2, 2, 2, 2, 2, 2};
3098 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3099 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3100 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3101 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3102 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3103 char *g_title[] = {"ierr/s", "oerr/s",
3104 "idstunr/s", "odstunr/s",
3105 "itmex/s", "otmex/s",
3106 "iparmpb/s", "oparmpb/s",
3107 "isrcq/s", "osrcq/s",
3108 "iredir/s", "oredir/s"};
3109 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3110 static double *spmin, *spmax;
3112 static int *outsize;
3114 if (action & F_BEGIN) {
3116 * Allocate arrays that will contain the graphs data
3117 * and the min/max values.
3119 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3122 if (action & F_MAIN) {
3123 /* Check for min/max values */
3124 save_extrema(0, 12, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3125 itv, spmin, spmax, g_fields);
3128 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3129 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3130 out, outsize, svg_p->restart);
3132 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3133 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3134 out + 1, outsize + 1, svg_p->restart);
3136 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3137 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3138 out + 2, outsize + 2, svg_p->restart);
3140 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3141 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3142 out + 3, outsize + 3, svg_p->restart);
3144 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3145 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3146 out + 4, outsize + 4, svg_p->restart);
3148 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3149 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3150 out + 5, outsize + 5, svg_p->restart);
3152 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3153 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3154 out + 6, outsize + 6, svg_p->restart);
3156 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3157 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3158 out + 7, outsize + 7, svg_p->restart);
3160 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3161 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3162 out + 8, outsize + 8, svg_p->restart);
3164 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3165 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3166 out + 9, outsize + 9, svg_p->restart);
3168 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3169 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3170 out + 10, outsize + 10, svg_p->restart);
3172 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3173 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3174 out + 11, outsize + 11, svg_p->restart);
3177 if (action & F_END) {
3178 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3179 spmin, spmax, out, outsize, svg_p, record_hdr);
3181 /* Free remaining structures */
3182 free_graphs(out, outsize, spmin, spmax);
3187 ***************************************************************************
3188 * Display TCPv4 network statistics in SVG.
3191 * @a Activity structure with statistics.
3192 * @curr Index in array for current sample statistics.
3193 * @action Action expected from current function.
3194 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3195 * flag indicating that a restart record has been previously
3196 * found (.@restart) and time used for the X axis origin
3198 * @itv Interval of time in jiffies (only with F_MAIN action).
3199 * @record_hdr Pointer on record header of current stats sample.
3200 ***************************************************************************
3202 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3203 unsigned long long itv, struct record_header *record_hdr)
3205 struct stats_net_tcp
3206 *sntc = (struct stats_net_tcp *) a->buf[curr],
3207 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3208 int group[] = {2, 2};
3209 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3210 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3211 char *g_title[] = {"active/s", "passive/s",
3212 "iseg/s", "oseg/s"};
3213 int g_fields[] = {0, 1, 2, 3};
3214 static double *spmin, *spmax;
3216 static int *outsize;
3218 if (action & F_BEGIN) {
3220 * Allocate arrays that will contain the graphs data
3221 * and the min/max values.
3223 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3226 if (action & F_MAIN) {
3227 /* Check for min/max values */
3228 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3229 itv, spmin, spmax, g_fields);
3232 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3233 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3234 out, outsize, svg_p->restart);
3236 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3237 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3238 out + 1, outsize + 1, svg_p->restart);
3240 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3241 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3242 out + 2, outsize + 2, svg_p->restart);
3244 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3245 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3246 out + 3, outsize + 3, svg_p->restart);
3249 if (action & F_END) {
3250 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3251 spmin, spmax, out, outsize, svg_p, record_hdr);
3253 /* Free remaining structures */
3254 free_graphs(out, outsize, spmin, spmax);
3259 ***************************************************************************
3260 * Display TCPv4 network errors statistics in SVG.
3263 * @a Activity structure with statistics.
3264 * @curr Index in array for current sample statistics.
3265 * @action Action expected from current function.
3266 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3267 * flag indicating that a restart record has been previously
3268 * found (.@restart) and time used for the X axis origin
3270 * @itv Interval of time in jiffies (only with F_MAIN action).
3271 * @record_hdr Pointer on record header of current stats sample.
3272 ***************************************************************************
3274 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3275 unsigned long long itv, struct record_header *record_hdr)
3277 struct stats_net_etcp
3278 *snetc = (struct stats_net_etcp *) a->buf[curr],
3279 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3280 int group[] = {2, 3};
3281 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3282 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3283 char *g_title[] = {"atmptf/s", "estres/s",
3284 "retrans/s", "isegerr/s", "orsts/s"};
3285 int g_fields[] = {0, 1, 2, 3, 4};
3286 static double *spmin, *spmax;
3288 static int *outsize;
3290 if (action & F_BEGIN) {
3292 * Allocate arrays that will contain the graphs data
3293 * and the min/max values.
3295 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3298 if (action & F_MAIN) {
3299 /* Check for min/max values */
3300 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3301 itv, spmin, spmax, g_fields);
3304 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3305 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3306 out, outsize, svg_p->restart);
3308 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3309 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3310 out + 1, outsize + 1, svg_p->restart);
3312 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3313 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3314 out + 2, outsize + 2, svg_p->restart);
3316 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3317 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3318 out + 3, outsize + 3, svg_p->restart);
3320 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3321 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3322 out + 4, outsize + 4, svg_p->restart);
3325 if (action & F_END) {
3326 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3327 spmin, spmax, out, outsize, svg_p, record_hdr);
3329 /* Free remaining structures */
3330 free_graphs(out, outsize, spmin, spmax);
3335 ***************************************************************************
3336 * Display UDPv4 network statistics in SVG.
3339 * @a Activity structure with statistics.
3340 * @curr Index in array for current sample statistics.
3341 * @action Action expected from current function.
3342 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3343 * flag indicating that a restart record has been previously
3344 * found (.@restart) and time used for the X axis origin
3346 * @itv Interval of time in jiffies (only with F_MAIN action).
3347 * @record_hdr Pointer on record header of current stats sample.
3348 ***************************************************************************
3350 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3351 unsigned long long itv, struct record_header *record_hdr)
3353 struct stats_net_udp
3354 *snuc = (struct stats_net_udp *) a->buf[curr],
3355 *snup = (struct stats_net_udp *) a->buf[!curr];
3356 int group[] = {2, 2};
3357 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3358 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3359 char *g_title[] = {"idgm/s", "odgm/s",
3360 "noport/s", "idgmerr/s"};
3361 int g_fields[] = {0, 1, 2, 3};
3362 static double *spmin, *spmax;
3364 static int *outsize;
3366 if (action & F_BEGIN) {
3368 * Allocate arrays that will contain the graphs data
3369 * and the min/max values.
3371 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3374 if (action & F_MAIN) {
3375 /* Check for min/max values */
3376 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3377 itv, spmin, spmax, g_fields);
3380 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3381 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3382 out, outsize, svg_p->restart);
3384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3385 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3386 out + 1, outsize + 1, svg_p->restart);
3388 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3389 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3390 out + 2, outsize + 2, svg_p->restart);
3392 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3393 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3394 out + 3, outsize + 3, svg_p->restart);
3397 if (action & F_END) {
3398 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3399 spmin, spmax, out, outsize, svg_p, record_hdr);
3401 /* Free remaining structures */
3402 free_graphs(out, outsize, spmin, spmax);
3407 ***************************************************************************
3408 * Display IPV6 network socket statistics in SVG.
3411 * @a Activity structure with statistics.
3412 * @curr Index in array for current sample statistics.
3413 * @action Action expected from current function.
3414 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3415 * flag indicating that a restart record has been previously
3416 * found (.@restart) and time used for the X axis origin
3418 * @itv Interval of time in jiffies (only with F_MAIN action).
3419 * @record_hdr Pointer on record header of current stats sample.
3420 ***************************************************************************
3422 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3423 unsigned long long itv, struct record_header *record_hdr)
3425 struct stats_net_sock6
3426 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3428 int g_type[] = {SVG_LINE_GRAPH};
3429 char *title[] = {"IPv6 network sockets"};
3430 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3431 int g_fields[] = {0, 1, 2, 3};
3432 static double *spmin, *spmax;
3434 static int *outsize;
3436 if (action & F_BEGIN) {
3438 * Allocate arrays that will contain the graphs data
3439 * and the min/max values.
3441 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3444 if (action & F_MAIN) {
3445 /* Check for min/max values */
3446 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
3447 itv, spmin, spmax, g_fields);
3449 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3450 (unsigned long) snsc->tcp6_inuse,
3451 out, outsize, svg_p->restart);
3453 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3454 (unsigned long) snsc->udp6_inuse,
3455 out + 1, outsize + 1, svg_p->restart);
3457 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3458 (unsigned long) snsc->raw6_inuse,
3459 out + 2, outsize + 2, svg_p->restart);
3461 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3462 (unsigned long) snsc->frag6_inuse,
3463 out + 3, outsize + 3, svg_p->restart);
3466 if (action & F_END) {
3467 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3468 spmin, spmax, out, outsize, svg_p, record_hdr);
3470 /* Free remaining structures */
3471 free_graphs(out, outsize, spmin, spmax);
3476 ***************************************************************************
3477 * Display IPv6 network statistics in SVG.
3480 * @a Activity structure with statistics.
3481 * @curr Index in array for current sample statistics.
3482 * @action Action expected from current function.
3483 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3484 * flag indicating that a restart record has been previously
3485 * found (.@restart) and time used for the X axis origin
3487 * @itv Interval of time in jiffies (only with F_MAIN action).
3488 * @record_hdr Pointer on record header of current stats sample.
3489 ***************************************************************************
3491 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3492 unsigned long long itv, struct record_header *record_hdr)
3494 struct stats_net_ip6
3495 *snic = (struct stats_net_ip6 *) a->buf[curr],
3496 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3497 int group[] = {4, 2, 2, 2};
3498 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3500 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3501 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3502 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3503 "asmrq6/s", "asmok6/s",
3504 "imcpck6/s", "omcpck6/s",
3505 "fragok6/s", "fragcr6/s"};
3506 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3507 static double *spmin, *spmax;
3509 static int *outsize;
3511 if (action & F_BEGIN) {
3513 * Allocate arrays that will contain the graphs data
3514 * and the min/max values.
3516 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3519 if (action & F_MAIN) {
3520 /* Check for min/max values */
3521 save_extrema(10, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3522 itv, spmin, spmax, g_fields);
3525 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3526 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3527 out, outsize, svg_p->restart);
3529 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3530 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3531 out + 1, outsize + 1, svg_p->restart);
3533 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3534 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3535 out + 2, outsize + 2, svg_p->restart);
3537 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3538 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3539 out + 3, outsize + 3, svg_p->restart);
3541 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3542 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3543 out + 4, outsize + 4, svg_p->restart);
3545 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3546 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3547 out + 5, outsize + 5, svg_p->restart);
3549 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3550 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3551 out + 6, outsize + 6, svg_p->restart);
3553 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3554 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3555 out + 7, outsize + 7, svg_p->restart);
3557 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3558 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3559 out + 8, outsize + 8, svg_p->restart);
3561 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3562 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3563 out + 9, outsize + 9, svg_p->restart);
3566 if (action & F_END) {
3567 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3568 spmin, spmax, out, outsize, svg_p, record_hdr);
3570 /* Free remaining structures */
3571 free_graphs(out, outsize, spmin, spmax);
3576 ***************************************************************************
3577 * Display IPv6 network errors statistics in SVG.
3580 * @a Activity structure with statistics.
3581 * @curr Index in array for current sample statistics.
3582 * @action Action expected from current function.
3583 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3584 * flag indicating that a restart record has been previously
3585 * found (.@restart) and time used for the X axis origin
3587 * @itv Interval of time in jiffies (only with F_MAIN action).
3588 * @record_hdr Pointer on record header of current stats sample.
3589 ***************************************************************************
3591 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3592 unsigned long long itv, struct record_header *record_hdr)
3594 struct stats_net_eip6
3595 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3596 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3597 int group[] = {4, 2, 2, 3};
3598 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3600 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3601 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3602 "IPv6 network errors statistics (5)"};
3603 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3604 "idisc6/s", "odisc6/s",
3605 "inort6/s", "onort6/s",
3606 "asmf6/s", "fragf6/s", "itrpck6/s"};
3607 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3608 static double *spmin, *spmax;
3610 static int *outsize;
3612 if (action & F_BEGIN) {
3614 * Allocate arrays that will contain the graphs data
3615 * and the min/max values.
3617 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3620 if (action & F_MAIN) {
3621 /* Check for min/max values */
3622 save_extrema(11, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3623 itv, spmin, spmax, g_fields);
3626 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3627 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3628 out, outsize, svg_p->restart);
3630 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3631 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3632 out + 1, outsize + 1, svg_p->restart);
3634 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3635 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3636 out + 2, outsize + 2, svg_p->restart);
3638 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3639 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3640 out + 3, outsize + 3, svg_p->restart);
3642 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3643 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3644 out + 4, outsize + 4, svg_p->restart);
3646 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3647 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3648 out + 5, outsize + 5, svg_p->restart);
3650 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3651 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3652 out + 6, outsize + 6, svg_p->restart);
3654 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3655 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3656 out + 7, outsize + 7, svg_p->restart);
3658 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3659 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3660 out + 8, outsize + 8, svg_p->restart);
3662 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3663 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3664 out + 9, outsize + 9, svg_p->restart);
3666 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3667 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3668 out + 10, outsize + 10, svg_p->restart);
3671 if (action & F_END) {
3672 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3673 spmin, spmax, out, outsize, svg_p, record_hdr);
3675 /* Free remaining structures */
3676 free_graphs(out, outsize, spmin, spmax);
3681 ***************************************************************************
3682 * Display ICMPv6 network statistics in SVG.
3685 * @a Activity structure with statistics.
3686 * @curr Index in array for current sample statistics.
3687 * @action Action expected from current function.
3688 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3689 * flag indicating that a restart record has been previously
3690 * found (.@restart) and time used for the X axis origin
3692 * @itv Interval of time in jiffies (only with F_MAIN action).
3693 * @record_hdr Pointer on record header of current stats sample.
3694 ***************************************************************************
3696 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3697 unsigned long long itv, struct record_header *record_hdr)
3699 struct stats_net_icmp6
3700 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3701 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3702 int group[] = {2, 3, 5, 3, 4};
3703 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3704 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3705 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3706 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3707 "ICMPv6 network statistics (5)"};
3708 char *g_title[] = {"imsg6/s", "omsg6/s",
3709 "iech6/s", "iechr6/s", "oechr6/s",
3710 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3711 "irtsol6/s", "ortsol6/s", "irtad6/s",
3712 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3713 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3714 static double *spmin, *spmax;
3716 static int *outsize;
3718 if (action & F_BEGIN) {
3720 * Allocate arrays that will contain the graphs data
3721 * and the min/max values.
3723 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3726 if (action & F_MAIN) {
3727 /* Check for min/max values */
3728 save_extrema(0, 17, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3729 itv, spmin, spmax, g_fields);
3732 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3733 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3734 out, outsize, svg_p->restart);
3736 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3737 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3738 out + 1, outsize + 1, svg_p->restart);
3740 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3741 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3742 out + 2, outsize + 2, svg_p->restart);
3744 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3745 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3746 out + 3, outsize + 3, svg_p->restart);
3748 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3749 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3750 out + 4, outsize + 4, svg_p->restart);
3752 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3753 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3754 out + 5, outsize + 5, svg_p->restart);
3756 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3757 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3758 out + 6, outsize + 6, svg_p->restart);
3760 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3761 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3762 out + 7, outsize + 7, svg_p->restart);
3764 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3765 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3766 out + 8, outsize + 8, svg_p->restart);
3768 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3769 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3770 out + 9, outsize + 9, svg_p->restart);
3772 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3773 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3774 out + 10, outsize + 10, svg_p->restart);
3776 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3777 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3778 out + 11, outsize + 11, svg_p->restart);
3780 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3781 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3782 out + 12, outsize + 12, svg_p->restart);
3784 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3785 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3786 out + 13, outsize + 13, svg_p->restart);
3788 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3789 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3790 out + 14, outsize + 14, svg_p->restart);
3792 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3793 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3794 out + 15, outsize + 15, svg_p->restart);
3796 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3797 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3798 out + 16, outsize + 16, svg_p->restart);
3801 if (action & F_END) {
3802 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3803 spmin, spmax, out, outsize, svg_p, record_hdr);
3805 /* Free remaining structures */
3806 free_graphs(out, outsize, spmin, spmax);
3811 ***************************************************************************
3812 * Display ICMPv6 network errors statistics in SVG.
3815 * @a Activity structure with statistics.
3816 * @curr Index in array for current sample statistics.
3817 * @action Action expected from current function.
3818 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3819 * flag indicating that a restart record has been previously
3820 * found (.@restart) and time used for the X axis origin
3822 * @itv Interval of time in jiffies (only with F_MAIN action).
3823 * @record_hdr Pointer on record header of current stats sample.
3824 ***************************************************************************
3826 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3827 unsigned long long itv, struct record_header *record_hdr)
3829 struct stats_net_eicmp6
3830 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3831 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3832 int group[] = {1, 2, 2, 2, 2, 2};
3833 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3834 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3835 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3836 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3837 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3838 char *g_title[] = {"ierr6/s",
3839 "idtunr6/s", "odtunr6/s",
3840 "itmex6/s", "otmex6/s",
3841 "iprmpb6/s", "oprmpb6/s",
3842 "iredir6/s", "oredir6/s",
3843 "ipck2b6/s", "opck2b6/s"};
3844 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3845 static double *spmin, *spmax;
3847 static int *outsize;
3849 if (action & F_BEGIN) {
3851 * Allocate arrays that will contain the graphs data
3852 * and the min/max values.
3854 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3857 if (action & F_MAIN) {
3858 /* Check for min/max values */
3859 save_extrema(0, 11, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3860 itv, spmin, spmax, g_fields);
3863 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3864 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
3865 out, outsize, svg_p->restart);
3867 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3868 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
3869 out + 1, outsize + 1, svg_p->restart);
3871 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3872 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
3873 out + 2, outsize + 2, svg_p->restart);
3875 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3876 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
3877 out + 3, outsize + 3, svg_p->restart);
3879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3880 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
3881 out + 4, outsize + 4, svg_p->restart);
3883 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3884 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
3885 out + 5, outsize + 5, svg_p->restart);
3887 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3888 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
3889 out + 6, outsize + 6, svg_p->restart);
3891 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3892 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
3893 out + 7, outsize + 7, svg_p->restart);
3895 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3896 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
3897 out + 8, outsize + 8, svg_p->restart);
3899 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3900 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
3901 out + 9, outsize + 9, svg_p->restart);
3903 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3904 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
3905 out + 10, outsize + 10, svg_p->restart);
3908 if (action & F_END) {
3909 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3910 spmin, spmax, out, outsize, svg_p, record_hdr);
3912 /* Free remaining structures */
3913 free_graphs(out, outsize, spmin, spmax);
3918 ***************************************************************************
3919 * Display UDPv6 network statistics in SVG.
3922 * @a Activity structure with statistics.
3923 * @curr Index in array for current sample statistics.
3924 * @action Action expected from current function.
3925 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3926 * flag indicating that a restart record has been previously
3927 * found (.@restart) and time used for the X axis origin
3929 * @itv Interval of time in jiffies (only with F_MAIN action).
3930 * @record_hdr Pointer on record header of current stats sample.
3931 ***************************************************************************
3933 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3934 unsigned long long itv, struct record_header *record_hdr)
3936 struct stats_net_udp6
3937 *snuc = (struct stats_net_udp6 *) a->buf[curr],
3938 *snup = (struct stats_net_udp6 *) a->buf[!curr];
3939 int group[] = {2, 2};
3940 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3941 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
3942 char *g_title[] = {"idgm6/s", "odgm6/s",
3943 "noport6/s", "idgmer6/s"};
3944 int g_fields[] = {0, 1, 2, 3};
3945 static double *spmin, *spmax;
3947 static int *outsize;
3949 if (action & F_BEGIN) {
3951 * Allocate arrays that will contain the graphs data
3952 * and the min/max values.
3954 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3957 if (action & F_MAIN) {
3958 /* Check for min/max values */
3959 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3960 itv, spmin, spmax, g_fields);
3963 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3964 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
3965 out, outsize, svg_p->restart);
3967 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3968 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
3969 out + 1, outsize + 1, svg_p->restart);
3971 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3972 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
3973 out + 2, outsize + 2, svg_p->restart);
3975 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3976 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
3977 out + 3, outsize + 3, svg_p->restart);
3980 if (action & F_END) {
3981 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3982 spmin, spmax, out, outsize, svg_p, record_hdr);
3984 /* Free remaining structures */
3985 free_graphs(out, outsize, spmin, spmax);
3990 ***************************************************************************
3991 * Display CPU frequency statistics in SVG.
3994 * @a Activity structure with statistics.
3995 * @curr Index in array for current sample statistics.
3996 * @action Action expected from current function.
3997 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3998 * flag indicating that a restart record has been previously
3999 * found (.@restart) and time used for the X axis origin
4001 * @itv Interval of time in jiffies (unused here).
4002 * @record_hdr Pointer on record header of current stats sample.
4003 ***************************************************************************
4005 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4006 unsigned long long itv, struct record_header *record_hdr)
4008 struct stats_pwr_cpufreq *spc, *spp;
4010 int g_type[] = {SVG_LINE_GRAPH};
4011 char *title[] = {"CPU frequency"};
4012 char *g_title[] = {"MHz"};
4013 static double *spmin, *spmax;
4015 static int *outsize;
4019 if (action & F_BEGIN) {
4021 * Allocate arrays that will contain the graphs data
4022 * and the min/max values.
4024 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4027 if (action & F_MAIN) {
4029 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4031 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4032 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4034 /* Should current CPU (including CPU "all") be displayed? */
4035 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4040 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4041 ((double) spp->cpufreq) / 100,
4042 ((double) spc->cpufreq) / 100,
4043 out + i, outsize + i, svg_p->restart, svg_p->dt,
4044 spmin + i, spmax + i);
4048 if (action & F_END) {
4049 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4051 /* Should current CPU (including CPU "all") be displayed? */
4052 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4057 /* This is CPU "all" */
4058 strcpy(item_name, "all");
4061 sprintf(item_name, "%d", i - 1);
4064 draw_activity_graphs(a->g_nr, g_type,
4065 title, g_title, item_name, group,
4066 spmin + i, spmax + i, out + i, outsize + i,
4070 /* Free remaining structures */
4071 free_graphs(out, outsize, spmin, spmax);
4076 ***************************************************************************
4077 * Display fan statistics in SVG.
4080 * @a Activity structure with statistics.
4081 * @curr Index in array for current sample statistics.
4082 * @action Action expected from current function.
4083 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4084 * flag indicating that a restart record has been previously
4085 * found (.@restart) and time used for the X axis origin
4087 * @itv Interval of time in jiffies (unused here).
4088 * @record_hdr Pointer on record header of current stats sample.
4089 ***************************************************************************
4091 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4092 unsigned long long itv, struct record_header *record_hdr)
4094 struct stats_pwr_fan *spc, *spp;
4096 int g_type[] = {SVG_LINE_GRAPH};
4097 char *title[] = {"Fan speed"};
4098 char *g_title[] = {"~rpm"};
4099 static double *spmin, *spmax;
4101 static int *outsize;
4102 char item_name[MAX_SENSORS_DEV_LEN + 8];
4105 if (action & F_BEGIN) {
4107 * Allocate arrays that will contain the graphs data
4108 * and the min/max values.
4110 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4113 if (action & F_MAIN) {
4115 for (i = 0; i < a->nr; i++) {
4117 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4118 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4121 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4124 out + i, outsize + i, svg_p->restart, svg_p->dt,
4125 spmin + i, spmax + i);
4129 if (action & F_END) {
4130 for (i = 0; i < a->nr; i++) {
4132 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4134 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4135 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4137 draw_activity_graphs(a->g_nr, g_type,
4138 title, g_title, item_name, group,
4139 spmin + i, spmax + i, out + i, outsize + i,
4143 /* Free remaining structures */
4144 free_graphs(out, outsize, spmin, spmax);
4149 ***************************************************************************
4150 * Display temperature statistics in SVG.
4153 * @a Activity structure with statistics.
4154 * @curr Index in array for current sample statistics.
4155 * @action Action expected from current function.
4156 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4157 * flag indicating that a restart record has been previously
4158 * found (.@restart) and time used for the X axis origin
4160 * @itv Interval of time in jiffies (unused here).
4161 * @record_hdr Pointer on record header of current stats sample.
4162 ***************************************************************************
4164 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4165 unsigned long long itv, struct record_header *record_hdr)
4167 struct stats_pwr_temp *spc;
4168 int group[] = {1, 1};
4169 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4170 char *title[] = {"Device temperature (1)",
4171 "Device temperature (2)"};
4172 char *g_title[] = {"~degC",
4174 static double *spmin, *spmax;
4176 static int *outsize;
4177 char item_name[MAX_SENSORS_DEV_LEN + 8];
4181 if (action & F_BEGIN) {
4183 * Allocate arrays that will contain the graphs data
4184 * and the min/max values.
4186 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4189 if (action & F_MAIN) {
4190 /* For each temperature sensor */
4191 for (i = 0; i < a->nr; i++) {
4193 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4195 /* Look for min/max values */
4196 if (spc->temp < *(spmin + 2 * i)) {
4197 *(spmin + 2 * i) = spc->temp;
4199 if (spc->temp > *(spmax + 2 * i)) {
4200 *(spmax + 2 * i) = spc->temp;
4202 tval = (spc->temp_max - spc->temp_min) ?
4203 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4205 if (tval < *(spmin + 2 * i + 1)) {
4206 *(spmin + 2 * i + 1) = tval;
4208 if (tval > *(spmax + 2 * i + 1)) {
4209 *(spmax + 2 * i + 1) = tval;
4213 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4215 out + 2 * i, outsize + 2 * i, svg_p->restart);
4217 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4219 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4223 if (action & F_END) {
4224 for (i = 0; i < a->nr; i++) {
4226 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4228 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4229 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4231 draw_activity_graphs(a->g_nr, g_type,
4232 title, g_title, item_name, group,
4233 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4237 /* Free remaining structures */
4238 free_graphs(out, outsize, spmin, spmax);
4243 ***************************************************************************
4244 * Display voltage inputs statistics in SVG.
4247 * @a Activity structure with statistics.
4248 * @curr Index in array for current sample statistics.
4249 * @action Action expected from current function.
4250 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4251 * flag indicating that a restart record has been previously
4252 * found (.@restart) and time used for the X axis origin
4254 * @itv Interval of time in jiffies (only with F_MAIN action).
4255 * @record_hdr Pointer on record header of current stats sample.
4256 ***************************************************************************
4258 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4259 unsigned long long itv, struct record_header *record_hdr)
4261 struct stats_pwr_in *spc;
4262 int group[] = {1, 1};
4263 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4264 char *title[] = {"Voltage inputs (1)",
4265 "Voltage inputs (2)"};
4266 char *g_title[] = {"inV",
4268 static double *spmin, *spmax;
4270 static int *outsize;
4271 char item_name[MAX_SENSORS_DEV_LEN + 8];
4275 if (action & F_BEGIN) {
4277 * Allocate arrays that will contain the graphs data
4278 * and the min/max values.
4280 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4283 if (action & F_MAIN) {
4284 /* For each temperature sensor */
4285 for (i = 0; i < a->nr; i++) {
4287 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4289 /* Look for min/max values */
4290 if (spc->in < *(spmin + 2 * i)) {
4291 *(spmin + 2 * i) = spc->in;
4293 if (spc->in > *(spmax + 2 * i)) {
4294 *(spmax + 2 * i) = spc->in;
4296 tval = (spc->in_max - spc->in_min) ?
4297 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4299 if (tval < *(spmin + 2 * i + 1)) {
4300 *(spmin + 2 * i + 1) = tval;
4302 if (tval > *(spmax + 2 * i + 1)) {
4303 *(spmax + 2 * i + 1) = tval;
4307 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4309 out + 2 * i, outsize + 2 * i, svg_p->restart);
4311 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4313 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4317 if (action & F_END) {
4318 for (i = 0; i < a->nr; i++) {
4320 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4322 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4323 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4325 draw_activity_graphs(a->g_nr, g_type,
4326 title, g_title, item_name, group,
4327 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4331 /* Free remaining structures */
4332 free_graphs(out, outsize, spmin, spmax);
4337 ***************************************************************************
4338 * Display huge pages statistics in SVG.
4341 * @a Activity structure with statistics.
4342 * @curr Index in array for current sample statistics.
4343 * @action Action expected from current function.
4344 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4345 * flag indicating that a restart record has been previously
4346 * found (.@restart) and time used for the X axis origin
4348 * @itv Interval of time in jiffies (only with F_MAIN action).
4349 * @record_hdr Pointer on record header of current stats sample.
4350 ***************************************************************************
4352 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4353 unsigned long long itv, struct record_header *record_hdr)
4356 *smc = (struct stats_huge *) a->buf[curr];
4357 int group[] = {2, 1};
4358 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4359 char *title[] = {"Huge pages utilization (1)",
4360 "Huge pages utilization (2)"};
4361 char *g_title[] = {"~kbhugfree", "~kbhugused",
4363 int g_fields[] = {0};
4364 static double *spmin, *spmax;
4366 static int *outsize;
4369 if (action & F_BEGIN) {
4371 * Allocate arrays that will contain the graphs data
4372 * and the min/max values.
4374 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4377 if (action & F_MAIN) {
4378 /* Check for min/max values */
4379 save_extrema(0, 1, 0, (void *) a->buf[curr], NULL,
4380 itv, spmin, spmax, g_fields);
4382 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4383 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4385 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4386 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4388 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4389 if (tval < *(spmin + 2)) {
4390 *(spmin + 2) = tval;
4392 if (tval > *(spmax + 2)) {
4393 *(spmax + 2) = tval;
4397 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4398 (unsigned long) smc->frhkb,
4399 out, outsize, svg_p->restart);
4401 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4402 (unsigned long) smc->tlhkb - smc->frhkb,
4403 out + 1, outsize + 1, svg_p->restart);
4405 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4407 out + 2, outsize + 2, svg_p->dt);
4410 if (action & F_END) {
4411 draw_activity_graphs(a->g_nr, g_type,
4412 title, g_title, NULL, group,
4413 spmin, spmax, out, outsize, svg_p, record_hdr);
4415 /* Free remaining structures */
4416 free_graphs(out, outsize, spmin, spmax);
4421 ***************************************************************************
4422 * Display filesystem statistics in SVG.
4425 * @a Activity structure with statistics.
4426 * @curr Index in array for current sample statistics.
4427 * @action Action expected from current function.
4428 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4429 * flag indicating that a restart record has been previously
4430 * found (.@restart) and time used for the X axis origin
4432 * @itv Interval of time in jiffies (unused here).
4433 * @record_hdr Pointer on record header of current stats sample.
4434 ***************************************************************************
4436 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4437 unsigned long long itv, struct record_header *record_hdr)
4439 struct stats_filesystem *sfc, *sfp;
4440 int group[] = {2, 2, 2, 1};
4441 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4442 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4443 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4444 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4445 char *g_title[] = {"~MBfsfree", "~MBfsused",
4446 "%ufsused", "%fsused",
4447 "Ifree/1000", "Iused/1000",
4449 static double *spmin, *spmax;
4451 static int *outsize;
4454 int i, k, pos, restart;
4456 if (action & F_BEGIN) {
4458 * Allocate arrays (#0..6) that will contain the graphs data
4459 * and the min/max values.
4460 * Also allocate two additional arrays (#7..8) for each filesystem:
4461 * out + 7 will contain the filesystem name,
4462 * out + 8 will contain the mount point.
4464 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
4467 if (action & F_MAIN) {
4468 /* For each filesystem structure */
4469 for (i = 0; i < a->nr; i++) {
4470 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4473 /* Size of filesystem is zero: We are at the end of the list */
4476 /* Look for corresponding graph */
4477 for (k = 0; k < a->nr; k++) {
4478 item_name = *(out + k * 9 + 7);
4479 if (!strcmp(sfc->fs_name, item_name))
4485 /* Graph not found: Look for first free entry */
4486 for (k = 0; k < a->nr; k++) {
4487 item_name = *(out + k * 9 + 7);
4488 if (!strcmp(item_name, ""))
4492 /* No free graph entry: Graph for this item won't be drawn */
4498 if (!item_name[0]) {
4499 /* Save filesystem name and mount point (if not already done) */
4500 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4501 item_name[CHUNKSIZE - 1] = '\0';
4502 item_name = *(out + pos + 8);
4503 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4504 item_name[CHUNKSIZE - 1] = '\0';
4508 for (k = 0; k < a->nr; k++) {
4509 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4510 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4511 /* Filesystem found in previous sample */
4512 restart = svg_p->restart;
4516 /* Check for min/max values */
4518 /* Compute fsfree min/max values */
4519 tval = (double) sfc->f_bfree;
4520 if (tval > *(spmax + pos)) {
4521 *(spmax + pos) = tval;
4523 if (tval < *(spmin + pos)) {
4524 *(spmin + pos) = tval;
4526 /* Compute fsused min/max values */
4527 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4528 if (tval > *(spmax + pos + 1)) {
4529 *(spmax + pos + 1) = tval;
4531 if (tval < *(spmin + pos + 1)) {
4532 *(spmin + pos + 1) = tval;
4534 /* Compute %ufsused min/max values */
4535 tval = sfc->f_blocks ?
4536 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4537 if (tval > *(spmax + pos + 2)) {
4538 *(spmax + pos + 2) = tval;
4540 if (tval < *(spmin + pos + 2)) {
4541 *(spmin + pos + 2) = tval;
4543 /* Compute %fsused min/max values */
4544 tval = sfc->f_blocks ?
4545 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4546 if (tval > *(spmax + pos + 3)) {
4547 *(spmax + pos + 3) = tval;
4549 if (tval < *(spmin + pos + 3)) {
4550 *(spmin + pos + 3) = tval;
4552 /* Compute Ifree min/max values */
4553 tval = (double) sfc->f_ffree;
4554 if (tval > *(spmax + pos + 4)) {
4555 *(spmax + pos + 4) = tval;
4557 if (tval < *(spmin + pos + 4)) {
4558 *(spmin + pos + 4) = tval;
4560 /* Compute Iused min/max values */
4561 tval = (double) (sfc->f_files - sfc->f_ffree);
4562 if (tval > *(spmax + pos + 5)) {
4563 *(spmax + pos + 5) = tval;
4565 if (tval < *(spmin + pos + 5)) {
4566 *(spmin + pos + 5) = tval;
4568 /* Compute %Iused min/max values */
4569 tval = sfc->f_files ?
4570 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4571 if (tval > *(spmax + pos + 6)) {
4572 *(spmax + pos + 6) = tval;
4574 if (tval < *(spmin + pos + 6)) {
4575 *(spmin + pos + 6) = tval;
4579 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4580 (double) sfc->f_bfree / 1024 / 1024,
4581 out + pos, outsize + pos, restart);
4583 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4584 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4585 out + pos + 1, outsize + pos + 1, restart);
4587 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4590 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4591 out + pos + 2, outsize + pos + 2, svg_p->dt);
4593 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4596 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4597 out + pos + 3, outsize + pos + 3, svg_p->dt);
4599 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4600 ((double) sfc->f_ffree) / 1000,
4601 out + pos + 4, outsize + pos + 4, restart);
4603 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4604 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4605 out + pos + 5, outsize + pos + 5, restart);
4607 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4610 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4611 out + pos + 6, outsize + pos + 6, svg_p->dt);
4615 if (action & F_END) {
4617 for (i = 0; i < a->nr; i++) {
4619 /* Check if there is something to display */
4624 /* Conversion B -> MB and inodes/1000 */
4625 for (k = 0; k < 2; k++) {
4626 *(spmin + pos + k) /= (1024 * 1024);
4627 *(spmax + pos + k) /= (1024 * 1024);
4628 *(spmin + pos + 4 + k) /= 1000;
4629 *(spmax + pos + 4 + k) /= 1000;
4632 if (DISPLAY_MOUNT(a->opt_flags)) {
4633 item_name = *(out + pos + 8);
4636 item_name = *(out + pos + 7);
4639 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4640 spmin + pos, spmax + pos, out + pos, outsize + pos,
4644 /* Free remaining structures */
4645 free_graphs(out, outsize, spmin, spmax);
4650 ***************************************************************************
4651 * Display Fibre Channel HBA statistics in SVG.
4654 * @a Activity structure with statistics.
4655 * @curr Index in array for current sample statistics.
4656 * @action Action expected from current function.
4657 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4658 * flag indicating that a restart record has been previously
4659 * found (.@restart) and time used for the X axis origin
4661 * @itv Interval of time in jiffies (only with F_MAIN action).
4662 * @record_hdr Pointer on record header of current stats sample.
4663 ***************************************************************************
4665 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4666 unsigned long long itv, struct record_header *record_hdr)
4668 struct stats_fchost *sfcc, *sfcp;
4669 int group[] = {2, 2};
4670 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4671 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4672 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4673 "fch_rxw/s", "fch_txw/s"};
4674 int g_fields[] = {0, 1, 2, 3};
4675 static double *spmin, *spmax;
4677 static int *outsize;
4681 if (action & F_BEGIN) {
4683 * Allocate arrays (#0..3) that will contain the graphs data
4684 * and the min/max values.
4685 * Also allocate one additional array (#4) that will contain
4688 out = allocate_graph_lines(4 * a->nr, &outsize, &spmin, &spmax);
4691 if (action & F_MAIN) {
4692 /* For each FC HBA */
4693 for (i = 0; i < a->nr; i++) {
4695 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4696 if (!sfcc->fchost_name[0])
4697 /* We are at the end of the list */
4700 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
4703 item_name = *(out + pos + 4);
4704 if (!item_name[0]) {
4705 /* Save FC HBA name */
4706 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4707 item_name[CHUNKSIZE - 1] = '\0';
4710 /* Look for min/max values */
4711 save_extrema(0, 4, 0, (void *) sfcc, (void *) sfcp,
4712 itv, spmin + pos, spmax + pos, g_fields);
4715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4716 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4717 out + pos, outsize + pos, svg_p->restart);
4719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4720 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4721 out + pos + 1, outsize + pos + 1, svg_p->restart);
4723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4724 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4725 out + pos + 2, outsize + pos + 2, svg_p->restart);
4727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4728 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4729 out + pos + 3, outsize + pos + 3, svg_p->restart);
4733 if (action & F_END) {
4734 for (i = 0; i < a->nr; i++) {
4736 /* Check if there is something to display */
4741 item_name = *(out + pos + 4);
4742 draw_activity_graphs(a->g_nr, g_type,
4743 title, g_title, item_name, group,
4744 spmin + pos, spmax + pos, out + pos, outsize + pos,
4748 /* Free remaining structures */
4749 free_graphs(out, outsize, spmin, spmax);
4754 ***************************************************************************
4755 * Display softnet statistics in SVG.
4758 * @a Activity structure with statistics.
4759 * @curr Index in array for current sample statistics.
4760 * @action Action expected from current function.
4761 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4762 * flag indicating that a restart record has been previously
4763 * found (.@restart) and time used for the X axis origin
4765 * @itv Interval of time in jiffies (only with F_MAIN action).
4766 * @record_hdr Pointer on record header of current stats sample.
4767 ***************************************************************************
4769 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4770 unsigned long long itv, struct record_header *record_hdr)
4772 struct stats_softnet *ssnc, *ssnp;
4773 int group[] = {2, 3};
4774 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4775 char *title[] = {"Software-based network processing statistics (1)",
4776 "Software-based network processing statistics (2)"};
4777 char *g_title[] = {"total/s", "dropd/s",
4778 "squeezd/s", "rx_rps/s", "flw_lim/s"};
4779 int g_fields[] = {0, 1, 2, 3, 4};
4780 static double *spmin, *spmax;
4782 static int *outsize;
4786 if (action & F_BEGIN) {
4788 * Allocate arrays that will contain the graphs data
4789 * and the min/max values.
4791 out = allocate_graph_lines(5 * a->nr, &outsize, &spmin, &spmax);
4794 if (action & F_MAIN) {
4796 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4798 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
4799 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
4801 /* Should current CPU (including CPU "all") be displayed? */
4802 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4808 /* Check for min/max values */
4809 save_extrema(0, 0, 5, (void *) ssnc, (void *) ssnp,
4810 itv, spmin + pos, spmax + pos, g_fields);
4813 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4814 S_VALUE(ssnp->processed, ssnc->processed, itv),
4815 out + pos, outsize + pos, svg_p->restart);
4817 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4818 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
4819 out + pos + 1, outsize + pos + 1, svg_p->restart);
4821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4822 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
4823 out + pos + 2, outsize + pos + 2, svg_p->restart);
4825 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4826 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
4827 out + pos + 3, outsize + pos + 3, svg_p->restart);
4829 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4830 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
4831 out + pos + 4, outsize + pos + 4, svg_p->restart);
4835 if (action & F_END) {
4836 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4838 /* Should current CPU (including CPU "all") be displayed? */
4839 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4846 /* This is CPU "all" */
4847 strcpy(item_name, "all");
4850 sprintf(item_name, "%d", i - 1);
4853 draw_activity_graphs(a->g_nr, g_type,
4854 title, g_title, item_name, group,
4855 spmin + pos, spmax + pos, out + pos, outsize + pos,
4859 /* Free remaining structures */
4860 free_graphs(out, outsize, spmin, spmax);