2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016 by Sebastien GODARD (sysstat <at> orange.fr)
5 ***************************************************************************
6 * This program is free software; you can redistribute it and/or modify it *
7 * under the terms of the GNU General Public License as published by the *
8 * Free Software Foundation; either version 2 of the License, or (at your *
9 * option) any later version. *
11 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * You should have received a copy of the GNU General Public License along *
17 * with this program; if not, write to the Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *
19 ***************************************************************************
31 #include "svg_stats.h"
36 #define _(string) gettext(string)
38 #define _(string) (string)
41 extern unsigned int flags;
42 extern unsigned int dm_major;
44 unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
45 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
46 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
47 0xcc3300, 0x50040f, 0xffffbf, 0x193d55};
48 #define SVG_COLORS_IDX_MASK 0x0f
51 ***************************************************************************
52 * Compare the values of a statistics sample with the max and min values
53 * already found in previous samples for this same activity. If some new
54 * min or max values are found, then save them.
55 * Assume values cannot be negative.
56 * The structure containing the statistics sample is composed of @llu_nr
57 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
58 * followed by @u_nr unsigned int fields.
61 * @llu_nr Number of unsigned long long fields composing the structure.
62 * @lu_nr Number of unsigned long fields composing the structure.
63 * @u_nr Number of unsigned int fields composing the structure.
64 * @cs Pointer on current sample statistics structure.
65 * @ps Pointer on previous sample statistics structure (may be NULL).
66 * @itv Interval of time in jiffies.
67 * @spmin Array containing min values already found for this activity.
68 * @spmax Array containing max values already found for this activity.
69 * @g_fields Index in spmin/spmax arrays where extrema values for each
70 * activity metric will be saved. As a consequence spmin/spmax
71 * arrays mau contain values in a different order than that of
72 * the fields in the statistics structure.
75 * @spmin Array containg the possible new min values for current activity.
76 * @spmax Array containg the possible new max values for current activity.
77 ***************************************************************************
79 void save_extrema(int llu_nr, int lu_nr, int u_nr, void *cs, void *ps,
80 unsigned long long itv, double *spmin, double *spmax, int g_fields[])
82 unsigned long long *lluc, *llup;
83 unsigned long *luc, *lup;
84 unsigned int *uc, *up;
88 /* Compare unsigned long long fields */
89 lluc = (unsigned long long *) cs;
90 llup = (unsigned long long *) ps;
91 for (i = 0; i < llu_nr; i++, m++) {
93 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
97 * If no pointer on previous sample has been given
98 * then the value is not a per-second one.
100 val = (double) *lluc;
102 if (val < *(spmin + g_fields[m])) {
103 *(spmin + g_fields[m]) = val;
105 if (val > *(spmax + g_fields[m])) {
106 *(spmax + g_fields[m]) = val;
108 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
110 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
114 /* Compare unsigned long fields */
115 luc = (unsigned long *) lluc;
116 lup = (unsigned long *) llup;
117 for (i = 0; i < lu_nr; i++, m++) {
119 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
124 if (val < *(spmin + g_fields[m])) {
125 *(spmin + g_fields[m]) = val;
127 if (val > *(spmax + g_fields[m])) {
128 *(spmax + g_fields[m]) = val;
130 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
132 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
136 /* Compare unsigned int fields */
137 uc = (unsigned int *) luc;
138 up = (unsigned int *) lup;
139 for (i = 0; i < u_nr; i++, m++) {
141 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
146 if (val < *(spmin + g_fields[m])) {
147 *(spmin + g_fields[m]) = val;
149 if (val > *(spmax + g_fields[m])) {
150 *(spmax + g_fields[m]) = val;
152 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
154 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
160 ***************************************************************************
161 * Find the min and max values of all the graphs that will be drawn in the
162 * same view. The graphs have their own min and max values in
163 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
166 * @pos Position in array for the first graph extrema value.
167 * @n Number of graphs to scan.
168 * @spmin Array containing min values for graphs.
169 * @spmax Array containing max values for graphs.
172 * @gmin Global min value found.
173 * @gmax Global max value found.
174 ***************************************************************************
176 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
177 double *gmin, double *gmax)
181 *gmin = *(spmin + pos);
182 *gmax = *(spmax + pos);
184 for (i = 1; i < n; i++) {
185 if (*(spmin + pos + i) < *gmin) {
186 *gmin = *(spmin + pos + i);
188 if (*(spmax + pos + i) > *gmax) {
189 *gmax = *(spmax + pos + i);
195 ***************************************************************************
196 * Allocate arrays used to save graphs data, min and max values.
197 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
198 * array is returned. This is equivalent to "char data[][n]" where each
199 * element is of indeterminate size and will contain the graph data (eg.
200 * << path d="M12,14 L13,16..." ... >>.
201 * The size of element data[i] is given by outsize[i].
202 * Also allocate an array to save min values (equivalent to "double spmin[n]")
203 * and an array for max values (equivalent to "double spmax[n]").
206 * @n Number of graphs to draw for current activity.
209 * @outsize Array that will contain the sizes of each element in array
210 * of chars. Equivalent to "int outsize[n]" with
211 * outsize[n] = sizeof(data[][n]).
212 * @spmin Array that will contain min values for current activity.
213 * @spmax Array that will contain max values for current activity.
216 * Pointer on array of arrays of chars that will contain the graphs data.
218 * NB: @min and @max arrays contain values in the same order as the fields
219 * in the statistics structure.
220 ***************************************************************************
222 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
229 * Allocate an array of pointers. Each of these pointers will
230 * be an array of chars.
232 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
236 /* Allocate array that will contain the size of each array of chars */
237 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
241 /* Allocate array that will contain the min value of each graph */
242 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
246 /* Allocate array that will contain the max value of each graph */
247 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
251 /* Allocate arrays of chars that will contain graphs data */
252 for (i = 0; i < n; i++) {
253 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
258 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
259 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
260 *(*spmin + i) = DBL_MAX; /* Init min and max values */
261 *(*spmax + i) = -DBL_MAX;
268 ***************************************************************************
269 * Save SVG code for current graph.
272 * @data SVG code to append to current graph definition.
273 * @out Pointer on array of chars for current graph definition.
274 * @outsize Size of array of chars for current graph definition.
277 * @out Pointer on array of chars for current graph definition that
278 * has been updated with the addition of current sample data.
279 * @outsize Array that containing the (possibly new) sizes of each
280 * element in array of chars.
281 ***************************************************************************
283 void save_svg_data(char *data, char **out, int *outsize)
289 /* Determine space left in array */
290 len = *outsize - strlen(out_p) - 1;
291 if (strlen(data) >= len) {
293 * If current array of chars doesn't have enough space left
294 * then reallocate it with CHUNKSIZE more bytes.
296 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
298 *outsize += CHUNKSIZE;
301 strncat(out_p, data, len);
305 ***************************************************************************
306 * Update line graph definition by appending current X,Y coordinates.
309 * @timetag Timestamp in seconds since the epoch for current sample
310 * stats. Will be used as X coordinate.
311 * @value Value of current sample metric. Will be used as Y coordinate.
312 * @out Pointer on array of chars for current graph definition.
313 * @outsize Size of array of chars for current graph definition.
314 * @restart Set to TRUE if a RESTART record has been read since the last
318 * @out Pointer on array of chars for current graph definition that
319 * has been updated with the addition of current sample data.
320 * @outsize Array that containing the (possibly new) sizes of each
321 * element in array of chars.
322 ***************************************************************************
324 void lnappend(unsigned long timetag, double value, char **out, int *outsize, int restart)
328 /* Prepare additional graph definition data */
329 snprintf(data, 128, " %c%lu,%.2f", restart ? 'M' : 'L', timetag, value);
332 save_svg_data(data, out, outsize);
336 ***************************************************************************
337 * Update line graph definition by appending current X,Y coordinates. Use
338 * (unsigned long) integer values here.
341 * @timetag Timestamp in seconds since the epoch for current sample
342 * stats. Will be used as X coordinate.
343 * @value Value of current sample metric. Will be used as Y coordinate.
344 * @out Pointer on array of chars for current graph definition.
345 * @outsize Size of array of chars for current graph definition.
346 * @restart Set to TRUE if a RESTART record has been read since the last
350 * @out Pointer on array of chars for current graph definition that
351 * has been updated with the addition of current sample data.
352 * @outsize Array that containing the (possibly new) sizes of each
353 * element in array of chars.
354 ***************************************************************************
356 void lniappend(unsigned long timetag, unsigned long value, char **out, int *outsize,
361 /* Prepare additional graph definition data */
362 snprintf(data, 128, " %c%lu,%lu", restart ? 'M' : 'L', timetag, value);
365 save_svg_data(data, out, outsize);
369 ***************************************************************************
370 * Update bar graph definition by adding a new rectangle.
373 * @timetag Timestamp in seconds since the epoch for current sample
374 * stats. Will be used as X coordinate.
375 * @value Value of current sample metric. Will be used as rectangle
377 * @offset Offset for Y coordinate.
378 * @out Pointer on array of chars for current graph definition.
379 * @outsize Size of array of chars for current graph definition.
380 * @dt Interval of time in seconds between current and previous
384 * @out Pointer on array of chars for current graph definition that
385 * has been updated with the addition of current sample data.
386 * @outsize Array that containing the (possibly new) sizes of each
387 * element in array of chars.
388 ***************************************************************************
390 void brappend(unsigned long timetag, double offset, double value, char **out, int *outsize,
395 /* Prepare additional graph definition data */
396 if ((value == 0.0) || (dt == 0))
397 /* Dont draw a flat rectangle! */
400 snprintf(data, 128, "<rect x=\"%lu\" y=\"%.2f\" height=\"%.2f\" width=\"%lu\"/>",
401 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
404 save_svg_data(data, out, outsize);
409 ***************************************************************************
410 * Update CPU graph and min/max values for each metric.
413 * @timetag Timestamp in seconds since the epoch for current sample
414 * stats. Will be used as X coordinate.
415 * @offset Offset for Y coordinate.
416 * @value Value of current CPU metric. Will be used as rectangle
418 * @out Pointer on array of chars for current graph definition.
419 * @outsize Size of array of chars for current graph definition.
420 * @dt Interval of time in seconds between current and previous
422 * @spmin Min value already found for this CPU metric.
423 * @spmax Max value already found for this CPU metric.
426 * @offset New offset value, to use to draw next rectangle
427 * @out Pointer on array of chars for current graph definition that
428 * has been updated with the addition of current sample data.
429 * @outsize Array that containing the (possibly new) sizes of each
430 * element in array of chars.
431 ***************************************************************************
433 void cpuappend(unsigned long timetag, double *offset, double value, char **out, int *outsize,
434 unsigned long dt, double *spmin, double *spmax)
436 /* Save min and max values */
437 if (value < *spmin) {
440 if (value > *spmax) {
443 /* Prepare additional graph definition data */
444 brappend(timetag, *offset, value, out, outsize, dt);
450 ***************************************************************************
451 * Update rectangular graph and min/max values.
454 * @timetag Timestamp in seconds since the epoch for current sample
455 * stats. Will be used as X coordinate.
456 * @p_value Metric value for previous sample
457 * @value Metric value for current sample.
458 * @out Pointer on array of chars for current graph definition.
459 * @outsize Size of array of chars for current graph definition.
460 * @restart Set to TRUE if a RESTART record has been read since the last
462 * @dt Interval of time in seconds between current and previous
464 * @spmin Min value already found for this metric.
465 * @spmax Max value already found for this metric.
468 * @out Pointer on array of chars for current graph definition that
469 * has been updated with the addition of current sample data.
470 * @outsize Array that containing the (possibly new) sizes of each
471 * element in array of chars.
472 * @spmin Min value for this metric.
473 * @spmax Max value for this metric.
474 ***************************************************************************
476 void recappend(unsigned long timetag, double p_value, double value, char **out, int *outsize,
477 int restart, unsigned long dt, double *spmin, double *spmax)
479 char data[128], data1[128], data2[128];
481 /* Save min and max values */
482 if (value < *spmin) {
485 if (value > *spmax) {
488 /* Prepare additional graph definition data */
490 snprintf(data1, 128, " M%lu,%.2f", timetag - dt, p_value);
493 if (p_value != value) {
494 snprintf(data2, 128, " L%lu,%.2f", timetag, value);
497 snprintf(data, 128, "%s L%lu,%.2f%s", restart ? data1 : "", timetag, p_value,
498 p_value != value ? data2 : "");
501 save_svg_data(data, out, outsize);
505 ***************************************************************************
506 * Calculate 10 raised to the power of n.
509 * @n Power number to use.
512 * 10 raised to the power of n.
513 ***************************************************************************
515 unsigned int pwr10(int n)
520 for (i = 0; i < n; i++) {
528 ***************************************************************************
529 * Autoscale graphs of a given view.
532 * @asf_nr (Maximum) number of autoscale factors.
533 * @group Number of graphs in current view.
534 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
535 * @pos Position in array for the first graph in view.
536 * @gmax Global max value for all graphs in view.
537 * @spmax Array containing max values for graphs.
540 * @asfactor Autoscale factors (one for each graph).
541 ***************************************************************************
543 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
544 double gmax, double *spmax)
549 for (j = 0; j < asf_nr; j++) {
550 /* Init autoscale factors */
554 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
556 for (j = 0; (j < group) && (j < asf_nr); j++) {
557 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
560 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
561 if (strlen(val) > 0) {
562 asfactor[j] = pwr10(strlen(val) - 1);
569 ***************************************************************************
570 * Display background grid (horizontal lines) and corresponding graduations.
573 * @ypos Gap between two horizontal lines.
574 * @yfactor Scaling factor on Y axis.
575 * @lmax Max value for current view.
576 * @dp Number of decimal places for graduations.
577 ***************************************************************************
579 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
585 /* Display horizontal lines (except on X axis) */
587 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
588 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
589 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
593 * Display graduations.
594 * Use same rounded value for graduation numbers as for grid lines
595 * to make sure they are properly aligned.
597 sprintf(stmp, "%.2f", ypos * j);
598 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
599 "text-anchor: end\">%.*f.</text>\n",
600 (long) (atof(stmp) * yfactor), dp, ypos * j);
603 while (ypos * j <= lmax);
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 if (DISPLAY_IDLE(flags)) {
1188 /* Include additional %idle field */
1193 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1195 /* Should current CPU (including CPU "all") be displayed? */
1196 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1202 /* This is CPU "all" */
1203 strcpy(item_name, "all");
1206 sprintf(item_name, "%d", i - 1);
1209 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1210 draw_activity_graphs(a->g_nr, g_type,
1211 title, g_title1, item_name, group1,
1212 spmin + pos, spmax + pos, out + pos, outsize + pos,
1216 draw_activity_graphs(a->g_nr, g_type,
1217 title, g_title2, item_name, group2,
1218 spmin + pos, spmax + pos, out + pos, outsize + pos,
1223 /* Free remaining structures */
1224 free_graphs(out, outsize, spmin, spmax);
1229 ***************************************************************************
1230 * Display task creation and context switch statistics in SVG.
1233 * @a Activity structure with statistics.
1234 * @curr Index in array for current sample statistics.
1235 * @action Action expected from current function.
1236 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1237 * flag indicating that a restart record has been previously
1238 * found (.@restart) and time used for the X axis origin
1240 * @itv Interval of time in jiffies (only with F_MAIN action).
1241 * @record_hdr Pointer on record header of current stats sample.
1242 ***************************************************************************
1244 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1245 unsigned long long itv, struct record_header *record_hdr)
1248 *spc = (struct stats_pcsw *) a->buf[curr],
1249 *spp = (struct stats_pcsw *) a->buf[!curr];
1250 int group[] = {1, 1};
1251 int g_fields[] = {1, 0};
1252 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1253 char *title[] = {"Task creation", "Switching activity"};
1254 char *g_title[] = {"proc/s",
1256 static double *spmin, *spmax;
1258 static int *outsize;
1260 if (action & F_BEGIN) {
1262 * Allocate arrays that will contain the graphs data
1263 * and the min/max values.
1265 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1268 if (action & F_MAIN) {
1269 /* Check for min/max values */
1270 save_extrema(1, 1, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1271 itv, spmin, spmax, g_fields);
1273 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1274 S_VALUE(spp->processes, spc->processes, itv),
1275 out, outsize, svg_p->restart);
1277 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1278 S_VALUE(spp->context_switch, spc->context_switch, itv),
1279 out + 1, outsize + 1, svg_p->restart);
1282 if (action & F_END) {
1283 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1284 spmin, spmax, out, outsize, svg_p, record_hdr);
1286 /* Free remaining structures */
1287 free_graphs(out, outsize, spmin, spmax);
1292 ***************************************************************************
1293 * Display swap statistics in SVG.
1296 * @a Activity structure with statistics.
1297 * @curr Index in array for current sample statistics.
1298 * @action Action expected from current function.
1299 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1300 * flag indicating that a restart record has been previously
1301 * found (.@restart) and time used for the X axis origin
1303 * @itv Interval of time in jiffies (only with F_MAIN action).
1304 * @record_hdr Pointer on record header of current stats sample.
1305 ***************************************************************************
1307 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1308 unsigned long long itv, struct record_header *record_hdr)
1311 *ssc = (struct stats_swap *) a->buf[curr],
1312 *ssp = (struct stats_swap *) a->buf[!curr];
1314 int g_type[] = {SVG_LINE_GRAPH};
1315 char *title[] = {"Swap activity"};
1316 char *g_title[] = {"pswpin/s", "pswpout/s" };
1317 int g_fields[] = {0, 1};
1318 static double *spmin, *spmax;
1320 static int *outsize;
1322 if (action & F_BEGIN) {
1324 * Allocate arrays that will contain the graphs data
1325 * and the min/max values.
1327 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1330 if (action & F_MAIN) {
1331 /* Check for min/max values */
1332 save_extrema(0, 2, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1333 itv, spmin, spmax, g_fields);
1335 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1336 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1337 out, outsize, svg_p->restart);
1339 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1340 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1341 out + 1, outsize + 1, svg_p->restart);
1344 if (action & F_END) {
1345 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1346 spmin, spmax, out, outsize, svg_p, record_hdr);
1348 /* Free remaining structures */
1349 free_graphs(out, outsize, spmin, spmax);
1354 ***************************************************************************
1355 * Display paging statistics in SVG.
1358 * @a Activity structure with statistics.
1359 * @curr Index in array for current sample statistics.
1360 * @action Action expected from current function.
1361 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1362 * flag indicating that a restart record has been previously
1363 * found (.@restart) and time used for the X axis origin
1365 * @itv Interval of time in jiffies (only with F_MAIN action).
1366 * @record_hdr Pointer on record header of current stats sample.
1367 ***************************************************************************
1369 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1370 unsigned long long itv, struct record_header *record_hdr)
1373 *spc = (struct stats_paging *) a->buf[curr],
1374 *spp = (struct stats_paging *) a->buf[!curr];
1375 int group[] = {2, 2, 4};
1376 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1377 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1378 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1379 "fault/s", "majflt/s",
1380 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1381 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1382 static double *spmin, *spmax;
1384 static int *outsize;
1386 if (action & F_BEGIN) {
1388 * Allocate arrays that will contain the graphs data
1389 * and the min/max values.
1391 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1394 if (action & F_MAIN) {
1395 /* Check for min/max values */
1396 save_extrema(0, 8, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1397 itv, spmin, spmax, g_fields);
1399 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1400 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1401 out, outsize, svg_p->restart);
1403 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1404 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1405 out + 1, outsize + 1, svg_p->restart);
1407 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1408 S_VALUE(spp->pgfault, spc->pgfault, itv),
1409 out + 2, outsize + 2, svg_p->restart);
1411 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1412 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1413 out + 3, outsize + 3, svg_p->restart);
1415 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1416 S_VALUE(spp->pgfree, spc->pgfree, itv),
1417 out + 4, outsize + 4, svg_p->restart);
1419 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1420 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1421 out + 5, outsize + 5, svg_p->restart);
1423 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1424 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1425 out + 6, outsize + 6, svg_p->restart);
1427 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1428 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1429 out + 7, outsize + 7, svg_p->restart);
1432 if (action & F_END) {
1433 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1434 spmin, spmax, out, outsize, svg_p, record_hdr);
1436 /* Free remaining structures */
1437 free_graphs(out, outsize, spmin, spmax);
1442 ***************************************************************************
1443 * Display I/O and transfer rate statistics in SVG.
1446 * @a Activity structure with statistics.
1447 * @curr Index in array for current sample statistics.
1448 * @action Action expected from current function.
1449 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1450 * flag indicating that a restart record has been previously
1451 * found (.@restart) and time used for the X axis origin
1453 * @itv Interval of time in jiffies (only with F_MAIN action).
1454 * @record_hdr Pointer on record header of current stats sample.
1455 ***************************************************************************
1457 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1458 unsigned long long itv, struct record_header *record_hdr)
1461 *sic = (struct stats_io *) a->buf[curr],
1462 *sip = (struct stats_io *) a->buf[!curr];
1463 int group[] = {3, 2};
1464 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1465 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1466 char *g_title[] = {"tps", "rtps", "wtps",
1467 "bread/s", "bwrtn/s"};
1468 int g_fields[] = {0, 1, 2, 3, 4};
1469 static double *spmin, *spmax;
1471 static int *outsize;
1473 if (action & F_BEGIN) {
1475 * Allocate arrays that will contain the graphs data
1476 * and the min/max values.
1478 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1481 if (action & F_MAIN) {
1482 /* Check for min/max values */
1483 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
1484 itv, spmin, spmax, g_fields);
1487 * If we get negative values, this is probably because
1488 * one or more devices/filesystems have been unmounted.
1489 * We display 0.0 in this case though we should rather tell
1490 * the user that the value cannot be calculated here.
1493 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1494 sic->dk_drive < sip->dk_drive ? 0.0 :
1495 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1496 out, outsize, svg_p->restart);
1498 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1499 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1500 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1501 out + 1, outsize + 1, svg_p->restart);
1503 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1504 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1505 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1506 out + 2, outsize + 2, svg_p->restart);
1508 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1509 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1510 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1511 out + 3, outsize + 3, svg_p->restart);
1513 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1514 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1515 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1516 out + 4, outsize + 4, svg_p->restart);
1519 if (action & F_END) {
1520 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1521 spmin, spmax, out, outsize, svg_p, record_hdr);
1523 /* Free remaining structures */
1524 free_graphs(out, outsize, spmin, spmax);
1529 ***************************************************************************
1530 * Display memory statistics in SVG.
1533 * @a Activity structure with statistics.
1534 * @curr Index in array for current sample statistics.
1535 * @action Action expected from current function.
1536 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1537 * flag indicating that a restart record has been previously
1538 * found (.@restart) and time used for the X axis origin
1540 * @itv Interval of time in jiffies (only with F_MAIN action).
1541 * @record_hdr Pointer on record header of current stats sample.
1542 ***************************************************************************
1544 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1545 unsigned long long itv, struct record_header *record_hdr)
1548 *smc = (struct stats_memory *) a->buf[curr];
1549 int group1[] = {3, 1, 3, 1, 3, 5};
1550 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1551 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1552 int group2[] = {3, 1, 1};
1553 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1554 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1555 "Memory utilization (3)", "Memory utilization (4)",
1556 "Memory utilization (5)", "Memory utilization (6)"};
1557 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1558 "Swap utilization (3)"};
1559 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1560 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1561 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1563 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1565 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1566 static double *spmin, *spmax;
1568 static int *outsize;
1572 if (action & F_BEGIN) {
1574 * Allocate arrays that will contain the graphs data
1575 * and the min/max values.
1577 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1580 if (action & F_MAIN) {
1581 /* Check for min/max values */
1582 save_extrema(0, 17, 0, (void *) a->buf[curr], NULL,
1583 itv, spmin, spmax, g_fields);
1584 /* Compute %memused min/max values */
1585 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1586 if (tval > *(spmax + 3)) {
1587 *(spmax + 3) = tval;
1589 if (tval < *(spmin + 3)) {
1590 *(spmin + 3) = tval;
1592 /* Compute %commit min/max values */
1593 tval = (smc->tlmkb + smc->tlskb) ?
1594 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1595 if (tval > *(spmax + 7)) {
1596 *(spmax + 7) = tval;
1598 if (tval < *(spmin + 7)) {
1599 *(spmin + 7) = tval;
1601 /* Compute %swpused min/max values */
1603 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1604 if (tval > *(spmax + 19)) {
1605 *(spmax + 19) = tval;
1607 if (tval < *(spmin + 19)) {
1608 *(spmin + 19) = tval;
1610 /* Compute %swpcad min/max values */
1611 tval = (smc->tlskb - smc->frskb) ?
1612 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1613 if (tval > *(spmax + 20)) {
1614 *(spmax + 20) = tval;
1616 if (tval < *(spmin + 20)) {
1617 *(spmin + 20) = tval;
1619 /* Compute memused min/max values in MB */
1620 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1621 if (tval > *(spmax + 2)) {
1622 *(spmax + 2) = tval;
1624 if (tval < *(spmin + 2)) {
1625 *(spmin + 2) = tval;
1627 /* Compute swpused min/max values in MB */
1628 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1629 if (tval > *(spmax + 17)) {
1630 *(spmax + 17) = tval;
1632 if (tval < *(spmin + 17)) {
1633 *(spmin + 17) = tval;
1637 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1638 ((double) smc->frmkb) / 1024,
1639 out, outsize, svg_p->restart);
1641 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1642 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1643 out + 2, outsize + 2, svg_p->restart);
1645 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1646 ((double) smc->availablekb) / 1024,
1647 out + 1, outsize + 1, svg_p->restart);
1649 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1650 ((double) smc->bufkb) / 1024,
1651 out + 4, outsize + 4, svg_p->restart);
1653 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1654 ((double) smc->camkb) / 1024,
1655 out + 5, outsize + 5, svg_p->restart);
1657 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1658 ((double) smc->frskb) / 1024,
1659 out + 16, outsize + 16, svg_p->restart);
1661 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1662 ((double) (smc->tlskb - smc->frskb)) / 1024,
1663 out + 17, outsize + 17, svg_p->restart);
1665 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1666 ((double) smc->caskb) / 1024,
1667 out + 18, outsize + 18, svg_p->restart);
1669 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1670 ((double) smc->comkb) / 1024,
1671 out + 6, outsize + 6, svg_p->restart);
1673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1674 ((double) smc->activekb) / 1024,
1675 out + 8, outsize + 8, svg_p->restart);
1677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1678 ((double) smc->inactkb) / 1024,
1679 out + 9, outsize + 9, svg_p->restart);
1681 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1682 ((double) smc->dirtykb) / 1024,
1683 out + 10, outsize + 10, svg_p->restart);
1685 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1686 ((double) smc->anonpgkb) / 1024,
1687 out + 11, outsize + 11, svg_p->restart);
1689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1690 ((double) smc->slabkb) / 1024,
1691 out + 12, outsize + 12, svg_p->restart);
1693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1694 ((double) smc->kstackkb) / 1024,
1695 out + 13, outsize + 13, svg_p->restart);
1697 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1698 ((double) smc->pgtblkb) / 1024,
1699 out + 14, outsize + 14, svg_p->restart);
1701 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1702 ((double) smc->vmusedkb) / 1024,
1703 out + 15, outsize + 15, svg_p->restart);
1705 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1708 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1709 out + 3, outsize + 3, svg_p->dt);
1711 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1713 (smc->tlmkb + smc->tlskb) ?
1714 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1715 out + 7, outsize + 7, svg_p->dt);
1717 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1720 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1721 out + 19, outsize + 19, svg_p->dt);
1723 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1725 (smc->tlskb - smc->frskb) ?
1726 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1727 out + 20, outsize + 20, svg_p->dt);
1730 if (action & F_END) {
1732 /* Conversion kB -> MB */
1733 for (i = 0; i < 17; i++) {
1734 *(spmin + g_fields[i]) /= 1024;
1735 *(spmax + g_fields[i]) /= 1024;
1738 if (DISPLAY_MEM_AMT(a->opt_flags)) {
1739 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1740 g_type1, title1, g_title1, NULL, group1,
1741 spmin, spmax, out, outsize, svg_p, record_hdr);
1744 if (DISPLAY_SWAP(a->opt_flags)) {
1745 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1746 spmin + 15, spmax + 15, out + 15, outsize + 15,
1750 /* Free remaining structures */
1751 free_graphs(out, outsize, spmin, spmax);
1756 ***************************************************************************
1757 * Display kernel tables statistics in SVG.
1760 * @a Activity structure with statistics.
1761 * @curr Index in array for current sample statistics.
1762 * @action Action expected from current function.
1763 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1764 * flag indicating that a restart record has been previously
1765 * found (.@restart) and time used for the X axis origin
1767 * @itv Interval of time in jiffies (only with F_MAIN action).
1768 * @record_hdr Pointer on record header of current stats sample.
1769 ***************************************************************************
1771 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1772 unsigned long long itv, struct record_header *record_hdr)
1774 struct stats_ktables
1775 *skc = (struct stats_ktables *) a->buf[curr];
1776 int group[] = {3, 1};
1777 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1778 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1779 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1781 int g_fields[] = {1, 2, 0, 3};
1782 static double *spmin, *spmax;
1784 static int *outsize;
1786 if (action & F_BEGIN) {
1788 * Allocate arrays that will contain the graphs data
1789 * and the min/max values.
1791 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1794 if (action & F_MAIN) {
1795 /* Check for min/max values */
1796 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
1797 itv, spmin, spmax, g_fields);
1799 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1800 (unsigned long) skc->dentry_stat,
1801 out, outsize, svg_p->restart);
1803 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1804 (unsigned long) skc->file_used,
1805 out + 1, outsize + 1, svg_p->restart);
1807 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1808 (unsigned long) skc->inode_used,
1809 out + 2, outsize + 2, svg_p->restart);
1811 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1812 (unsigned long) skc->pty_nr,
1813 out + 3, outsize + 3, svg_p->restart);
1816 if (action & F_END) {
1817 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1818 spmin, spmax, out, outsize, svg_p, record_hdr);
1820 /* Free remaining structures */
1821 free_graphs(out, outsize, spmin, spmax);
1826 ***************************************************************************
1827 * Display queue and load statistics in SVG.
1830 * @a Activity structure with statistics.
1831 * @curr Index in array for current sample statistics.
1832 * @action Action expected from current function.
1833 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1834 * flag indicating that a restart record has been previously
1835 * found (.@restart) and time used for the X axis origin
1837 * @itv Interval of time in jiffies (only with F_MAIN action).
1838 * @record_hdr Pointer on record header of current stats sample.
1839 ***************************************************************************
1841 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1842 unsigned long long itv, struct record_header *record_hdr)
1845 *sqc = (struct stats_queue *) a->buf[curr];
1846 int group[] = {2, 1, 3};
1847 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1848 char *title[] = {"Queue length", "Task list", "Load average"};
1849 char *g_title[] = {"~runq-sz", "~blocked",
1851 "ldavg-1", "ldavg-5", "ldavg-15"};
1852 int g_fields[] = {0, 1, 3, 4, 5, 2};
1853 static double *spmin, *spmax;
1855 static int *outsize;
1857 if (action & F_BEGIN) {
1859 * Allocate arrays that will contain the graphs data
1860 * and the min/max values.
1862 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1865 if (action & F_MAIN) {
1866 /* Check for min/max values */
1867 save_extrema(0, 2, 4, (void *) a->buf[curr], NULL,
1868 itv, spmin, spmax, g_fields);
1870 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1871 (unsigned long) sqc->nr_running,
1872 out, outsize, svg_p->restart);
1874 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1875 (unsigned long) sqc->procs_blocked,
1876 out + 1, outsize + 1, svg_p->restart);
1878 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1879 (unsigned long) sqc->nr_threads,
1880 out + 2, outsize + 2, svg_p->restart);
1882 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1883 (double) sqc->load_avg_1 / 100,
1884 out + 3, outsize + 3, svg_p->restart);
1886 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1887 (double) sqc->load_avg_5 / 100,
1888 out + 4, outsize + 4, svg_p->restart);
1890 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1891 (double) sqc->load_avg_15 / 100,
1892 out + 5, outsize + 5, svg_p->restart);
1895 if (action & F_END) {
1896 /* Fix min/max values for load average */
1897 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1898 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1899 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1901 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1902 spmin, spmax, out, outsize, svg_p, record_hdr);
1904 /* Free remaining structures */
1905 free_graphs(out, outsize, spmin, spmax);
1910 ***************************************************************************
1911 * Display disk statistics in SVG.
1914 * @a Activity structure with statistics.
1915 * @curr Index in array for current sample statistics.
1916 * @action Action expected from current function.
1917 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1918 * flag indicating that a restart record has been previously
1919 * found (.@restart) and time used for the X axis origin
1921 * @itv Interval of time in jiffies (only with F_MAIN action).
1922 * @record_hdr Pointer on record header of current stats sample.
1923 ***************************************************************************
1925 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1926 unsigned long long itv, struct record_header *record_hdr)
1928 struct stats_disk *sdc, *sdp, sdpzero;
1929 struct ext_disk_stats xds;
1930 int group[] = {1, 2, 2, 2, 1};
1931 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
1932 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
1933 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
1934 "Disk statistics (3)", "Disk statistics (4)",
1935 "Disk statistics (5)"};
1936 char *g_title[] = {"tps",
1937 "rd_sec/s", "wr_sec/s",
1938 "avgrq-sz", "avgqu-sz",
1941 int g_fields[] = {0, 1, 2};
1942 static double *spmin, *spmax;
1944 static int *outsize;
1945 char *item_name, *persist_dev_name;
1947 int i, j, k, pos, restart, *unregistered;
1949 if (action & F_BEGIN) {
1951 * Allocate arrays (#0..7) that will contain the graphs data
1952 * and the min/max values.
1953 * Also allocate one additional array (#8) for each disk device:
1954 * spmax + 8 will contain the device major number,
1955 * spmin + 8 will contain the device minor number,
1956 * outsize + 8 will contain a positive value (TRUE) if the device
1957 * has either still not been registered, or has been unregistered.
1959 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
1962 if (action & F_MAIN) {
1963 memset(&sdpzero, 0, STATS_DISK_SIZE);
1964 restart = svg_p->restart;
1966 * Mark previously registered devices as now
1967 * possibly unregistered for all graphs.
1969 for (k = 0; k < a->nr; k++) {
1970 unregistered = outsize + k * 9 + 8;
1971 if (*unregistered == FALSE) {
1972 *unregistered = MAYBE;
1976 /* For each device structure */
1977 for (i = 0; i < a->nr; i++) {
1978 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
1979 if (!(sdc->major + sdc->minor))
1980 /* Empty structure: Ignore it */
1983 /* Look for corresponding graph */
1984 for (k = 0; k < a->nr; k++) {
1985 if ((sdc->major == *(spmax + k * 9 + 8)) &&
1986 (sdc->minor == *(spmin + k * 9 + 8)))
1991 /* Graph not found: Look for first free entry */
1992 for (k = 0; k < a->nr; k++) {
1993 if (*(spmax + k * 9 + 8) == -DBL_MAX)
1997 /* No free graph entry: Graph for this item won't be drawn */
2001 unregistered = outsize + pos + 8;
2003 j = check_disk_reg(a, curr, !curr, i);
2005 /* This is a newly registered interface. Previous stats are zero */
2009 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2013 * If current device was marked as previously unregistered,
2014 * then set restart variable to TRUE so that the graph will be
2015 * discontinuous, and mark it as now registered.
2017 if (*unregistered == TRUE) {
2020 *unregistered = FALSE;
2022 if (*(spmax + pos + 8) == -DBL_MAX) {
2023 /* Save device major and minor numbers (if not already done) */
2024 *(spmax + pos + 8) = sdc->major;
2025 *(spmin + pos + 8) = sdc->minor;
2028 /* Check for min/max values */
2029 save_extrema(1, 2, 0, (void *) sdc, (void *) sdp,
2030 itv, spmin + pos, spmax + pos, g_fields);
2032 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2033 if (xds.arqsz < *(spmin + pos + 3)) {
2034 *(spmin + pos + 3) = xds.arqsz;
2036 if (xds.arqsz > *(spmax + pos + 3)) {
2037 *(spmax + pos + 3) = xds.arqsz;
2039 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2040 if (aqusz < *(spmin + pos + 4)) {
2041 *(spmin + pos + 4) = aqusz;
2043 if (aqusz > *(spmax + pos + 4)) {
2044 *(spmax + pos + 4) = aqusz;
2046 if (xds.await < *(spmin + pos + 5)) {
2047 *(spmin + pos + 5) = xds.await;
2049 if (xds.await > *(spmax + pos + 5)) {
2050 *(spmax + pos + 5) = xds.await;
2052 if (xds.svctm < *(spmin + pos + 6)) {
2053 *(spmin + pos + 6) = xds.svctm;
2055 if (xds.svctm > *(spmax + pos + 6)) {
2056 *(spmax + pos + 6) = xds.svctm;
2058 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2059 *(spmin + pos + 7) = xds.util / 10.0;
2061 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2062 *(spmax + pos + 7) = xds.util / 10.0;
2066 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2067 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2068 out + pos, outsize + pos, restart);
2070 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2071 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv),
2072 out + pos + 1, outsize + pos + 1, restart);
2074 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2075 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv),
2076 out + pos + 2, outsize + pos + 2, restart);
2078 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2080 out + pos + 3, outsize + pos + 3, restart);
2082 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2084 out + pos + 4, outsize + pos + 4, restart);
2086 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2088 out + pos + 5, outsize + pos + 5, restart);
2090 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2092 out + pos + 6, outsize + pos + 6, restart);
2094 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2095 0.0, xds.util / 10.0,
2096 out + pos + 7, outsize + pos + 7, svg_p->dt);
2099 /* Mark devices not seen here as now unregistered */
2100 for (k = 0; k < a->nr; k++) {
2101 unregistered = outsize + k * 9 + 8;
2102 if (*unregistered != FALSE) {
2103 *unregistered = TRUE;
2108 if (action & F_END) {
2109 for (i = 0; i < a->nr; i++) {
2110 /* Check if there is something to display */
2116 persist_dev_name = NULL;
2118 if (DISPLAY_PERSIST_NAME_S(flags)) {
2119 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2123 if (persist_dev_name) {
2124 item_name = persist_dev_name;
2127 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2128 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2132 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2133 USE_PRETTY_OPTION(flags));
2137 draw_activity_graphs(a->g_nr, g_type,
2138 title, g_title, item_name, group,
2139 spmin + pos, spmax + pos, out + pos, outsize + pos,
2143 /* Free remaining structures */
2144 free_graphs(out, outsize, spmin, spmax);
2149 ***************************************************************************
2150 * Display network interfaces statistics in SVG.
2153 * @a Activity structure with statistics.
2154 * @curr Index in array for current sample statistics.
2155 * @action Action expected from current function.
2156 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2157 * flag indicating that a restart record has been previously
2158 * found (.@restart) and time used for the X axis origin
2160 * @itv Interval of time in jiffies (only with F_MAIN action).
2161 * @record_hdr Pointer on record header of current stats sample.
2162 ***************************************************************************
2164 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2165 unsigned long long itv, struct record_header *record_hdr)
2167 struct stats_net_dev *sndc, *sndp, sndzero;
2168 int group[] = {2, 2, 3, 1};
2169 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2171 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2172 "Network statistics (3)", "Network statistics (4)"};
2173 char *g_title[] = {"rxpck/s", "txpck/s",
2175 "rxcmp/s", "txcmp/s", "rxmcst/s",
2177 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2178 static double *spmin, *spmax;
2180 static int *outsize;
2182 double rxkb, txkb, ifutil;
2183 int i, j, k, pos, restart, *unregistered;
2185 if (action & F_BEGIN) {
2187 * Allocate arrays (#0..7) that will contain the graphs data
2188 * and the min/max values.
2189 * Also allocate one additional array (#8) for each interface:
2190 * out + 8 will contain the interface name,
2191 * outsize + 8 will contain a positive value (TRUE) if the interface
2192 * has either still not been registered, or has been unregistered.
2194 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2197 if (action & F_MAIN) {
2198 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2199 restart = svg_p->restart;
2201 * Mark previously registered interfaces as now
2202 * possibly unregistered for all graphs.
2204 for (k = 0; k < a->nr; k++) {
2205 unregistered = outsize + k * 9 + 8;
2206 if (*unregistered == FALSE) {
2207 *unregistered = MAYBE;
2211 /* For each network interfaces structure */
2212 for (i = 0; i < a->nr; i++) {
2213 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2214 if (!strcmp(sndc->interface, ""))
2215 /* Empty structure: This is the end of the list */
2218 /* Look for corresponding graph */
2219 for (k = 0; k < a->nr; k++) {
2220 item_name = *(out + k * 9 + 8);
2221 if (!strcmp(sndc->interface, item_name))
2226 /* Graph not found: Look for first free entry */
2227 for (k = 0; k < a->nr; k++) {
2228 item_name = *(out + k * 9 + 8);
2229 if (!strcmp(item_name, ""))
2233 /* No free graph entry: Graph for this item won't be drawn */
2238 unregistered = outsize + pos + 8;
2240 j = check_net_dev_reg(a, curr, !curr, i);
2242 /* This is a newly registered interface. Previous stats are zero */
2246 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2250 * If current interface was marked as previously unregistered,
2251 * then set restart variable to TRUE so that the graph will be
2252 * discontinuous, and mark it as now registered.
2254 if (*unregistered == TRUE) {
2257 *unregistered = FALSE;
2259 if (!item_name[0]) {
2260 /* Save network interface name (if not already done) */
2261 strncpy(item_name, sndc->interface, CHUNKSIZE);
2262 item_name[CHUNKSIZE - 1] = '\0';
2265 /* Check for min/max values */
2266 save_extrema(7, 0, 0, (void *) sndc, (void *) sndp,
2267 itv, spmin + pos, spmax + pos, g_fields);
2269 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2270 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2271 ifutil = compute_ifutil(sndc, rxkb, txkb);
2272 if (ifutil < *(spmin + pos + 7)) {
2273 *(spmin + pos + 7) = ifutil;
2275 if (ifutil > *(spmax + pos + 7)) {
2276 *(spmax + pos + 7) = ifutil;
2280 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2281 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2282 out + pos, outsize + pos, restart);
2284 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2285 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2286 out + pos + 1, outsize + pos + 1, restart);
2288 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2290 out + pos + 2, outsize + pos + 2, restart);
2292 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2294 out + pos + 3, outsize + pos + 3, restart);
2296 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2297 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2298 out + pos + 4, outsize + pos + 4, restart);
2300 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2301 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2302 out + pos + 5, outsize + pos + 5, restart);
2304 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2305 S_VALUE(sndp->multicast, sndc->multicast, itv),
2306 out + pos + 6, outsize + pos + 6, restart);
2308 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2310 out + pos + 7, outsize + pos + 7, svg_p->dt);
2313 /* Mark interfaces not seen here as now unregistered */
2314 for (k = 0; k < a->nr; k++) {
2315 unregistered = outsize + k * 9 + 8;
2316 if (*unregistered != FALSE) {
2317 *unregistered = TRUE;
2322 if (action & F_END) {
2323 for (i = 0; i < a->nr; i++) {
2325 * Check if there is something to display.
2326 * Don't test sndc->interface because maybe the network
2327 * interface has been registered later.
2333 /* Recalculate min and max values in kB, not in B */
2334 *(spmin + pos + 2) /= 1024;
2335 *(spmax + pos + 2) /= 1024;
2336 *(spmin + pos + 3) /= 1024;
2337 *(spmax + pos + 3) /= 1024;
2339 item_name = *(out + pos + 8);
2340 draw_activity_graphs(a->g_nr, g_type,
2341 title, g_title, item_name, group,
2342 spmin + pos, spmax + pos, out + pos, outsize + pos,
2346 /* Free remaining structures */
2347 free_graphs(out, outsize, spmin, spmax);
2352 ***************************************************************************
2353 * Display network interface errors statistics in SVG.
2356 * @a Activity structure with statistics.
2357 * @curr Index in array for current sample statistics.
2358 * @action Action expected from current function.
2359 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2360 * flag indicating that a restart record has been previously
2361 * found (.@restart) and time used for the X axis origin
2363 * @itv Interval of time in jiffies (only with F_MAIN action).
2364 * @record_hdr Pointer on record header of current stats sample.
2365 ***************************************************************************
2367 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2368 unsigned long long itv, struct record_header *record_hdr)
2370 struct stats_net_edev *snedc, *snedp, snedzero;
2371 int group[] = {2, 2, 2, 3};
2372 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2374 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2375 "Network errors statistics (3)", "Network errors statistics (4)"};
2376 char *g_title[] = {"rxerr/s", "txerr/s",
2377 "rxdrop/s", "txdrop/s",
2378 "rxfifo/s", "txfifo/s",
2379 "coll/s", "txcarr/s", "rxfram/s"};
2380 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2381 static double *spmin, *spmax;
2383 static int *outsize;
2385 int i, j, k, pos, restart, *unregistered;
2387 if (action & F_BEGIN) {
2389 * Allocate arrays (#0..8) that will contain the graphs data
2390 * and the min/max values.
2391 * Also allocate one additional array (#9) for each interface:
2392 * out + 9 will contain the interface name,
2393 * outsize + 9 will contain a positive value (TRUE) if the interface
2394 * has either still not been registered, or has been unregistered.
2396 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
2399 if (action & F_MAIN) {
2400 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2401 restart = svg_p->restart;
2403 * Mark previously registered interfaces as now
2404 * possibly unregistered for all graphs.
2406 for (k = 0; k < a->nr; k++) {
2407 unregistered = outsize + k * 10 + 9;
2408 if (*unregistered == FALSE) {
2409 *unregistered = MAYBE;
2413 /* For each network interfaces structure */
2414 for (i = 0; i < a->nr; i++) {
2415 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2416 if (!strcmp(snedc->interface, ""))
2417 /* Empty structure: This is the end of the list */
2420 /* Look for corresponding graph */
2421 for (k = 0; k < a->nr; k++) {
2422 item_name = *(out + k * 10 + 9);
2423 if (!strcmp(snedc->interface, item_name))
2428 /* Graph not found: Look for first free entry */
2429 for (k = 0; k < a->nr; k++) {
2430 item_name = *(out + k * 10 + 9);
2431 if (!strcmp(item_name, ""))
2435 /* No free graph entry: Graph for this item won't be drawn */
2440 unregistered = outsize + pos + 9;
2442 j = check_net_edev_reg(a, curr, !curr, i);
2444 /* This is a newly registered interface. Previous stats are zero */
2448 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2452 * If current interface was marked as previously unregistered,
2453 * then set restart variable to TRUE so that the graph will be
2454 * discontinuous, and mark it as now registered.
2456 if (*unregistered == TRUE) {
2459 *unregistered = FALSE;
2461 if (!item_name[0]) {
2462 /* Save network interface name (if not already done) */
2463 strncpy(item_name, snedc->interface, CHUNKSIZE);
2464 item_name[CHUNKSIZE - 1] = '\0';
2467 /* Check for min/max values */
2468 save_extrema(9, 0, 0, (void *) snedc, (void *) snedp,
2469 itv, spmin + pos, spmax + pos, g_fields);
2472 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2473 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2474 out + pos, outsize + pos, restart);
2476 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2477 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2478 out + pos + 1, outsize + pos + 1, restart);
2480 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2481 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2482 out + pos + 2, outsize + pos + 2, restart);
2484 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2485 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2486 out + pos + 3, outsize + pos + 3, restart);
2488 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2489 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2490 out + pos + 4, outsize + pos + 4, restart);
2492 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2493 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2494 out + pos + 5, outsize + pos + 5, restart);
2496 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2497 S_VALUE(snedp->collisions, snedc->collisions, itv),
2498 out + pos + 6, outsize + pos + 6, restart);
2500 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2501 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2502 out + pos + 7, outsize + pos + 7, restart);
2504 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2505 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2506 out + pos + 8, outsize + pos + 8, restart);
2509 /* Mark interfaces not seen here as now unregistered */
2510 for (k = 0; k < a->nr; k++) {
2511 unregistered = outsize + k * 10 + 9;
2512 if (*unregistered != FALSE) {
2513 *unregistered = TRUE;
2518 if (action & F_END) {
2519 for (i = 0; i < a->nr; i++) {
2521 * Check if there is something to display.
2522 * Don't test snedc->interface because maybe the network
2523 * interface has been registered later.
2529 item_name = *(out + pos + 9);
2530 draw_activity_graphs(a->g_nr, g_type,
2531 title, g_title, item_name, group,
2532 spmin + pos, spmax + pos, out + pos, outsize + pos,
2536 /* Free remaining structures */
2537 free_graphs(out, outsize, spmin, spmax);
2542 ***************************************************************************
2543 * Display NFS client statistics in SVG.
2546 * @a Activity structure with statistics.
2547 * @curr Index in array for current sample statistics.
2548 * @action Action expected from current function.
2549 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2550 * flag indicating that a restart record has been previously
2551 * found (.@restart) and time used for the X axis origin
2553 * @itv Interval of time in jiffies (only with F_MAIN action).
2554 * @record_hdr Pointer on record header of current stats sample.
2555 ***************************************************************************
2557 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2558 unsigned long long itv, struct record_header *record_hdr)
2560 struct stats_net_nfs
2561 *snnc = (struct stats_net_nfs *) a->buf[curr],
2562 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2563 int group[] = {2, 2, 2};
2564 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2565 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2566 "NFS client statistics (3)"};
2567 char *g_title[] = {"call/s", "retrans/s",
2568 "read/s", "write/s",
2569 "access/s", "getatt/s"};
2570 int g_fields[] = {0, 1, 2, 3, 4, 5};
2571 static double *spmin, *spmax;
2573 static int *outsize;
2575 if (action & F_BEGIN) {
2577 * Allocate arrays that will contain the graphs data
2578 * and the min/max values.
2580 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2583 if (action & F_MAIN) {
2584 /* Check for min/max values */
2585 save_extrema(0, 0, 6, (void *) a->buf[curr], (void *) a->buf[!curr],
2586 itv, spmin, spmax, g_fields);
2589 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2590 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2591 out, outsize, svg_p->restart);
2593 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2594 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2595 out + 1, outsize + 1, svg_p->restart);
2597 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2598 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2599 out + 2, outsize + 2, svg_p->restart);
2601 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2602 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2603 out + 3, outsize + 3, svg_p->restart);
2605 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2606 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2607 out + 4, outsize + 4, svg_p->restart);
2609 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2610 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2611 out + 5, outsize + 5, svg_p->restart);
2614 if (action & F_END) {
2615 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2616 spmin, spmax, out, outsize, svg_p, record_hdr);
2618 /* Free remaining structures */
2619 free_graphs(out, outsize, spmin, spmax);
2624 ***************************************************************************
2625 * Display NFS server statistics in SVG.
2628 * @a Activity structure with statistics.
2629 * @curr Index in array for current sample statistics.
2630 * @action Action expected from current function.
2631 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2632 * flag indicating that a restart record has been previously
2633 * found (.@restart) and time used for the X axis origin
2635 * @itv Interval of time in jiffies (only with F_MAIN action).
2636 * @record_hdr Pointer on record header of current stats sample.
2637 ***************************************************************************
2639 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2640 unsigned long long itv, struct record_header *record_hdr)
2642 struct stats_net_nfsd
2643 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2644 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2645 int group[] = {2, 3, 2, 2, 2};
2646 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2647 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2648 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2649 "NFS server statistics (3)", "NFS server statistics (4)",
2650 "NFS server statistics (5)"};
2651 char *g_title[] = {"scall/s", "badcall/s",
2652 "packet/s", "udp/s", "tcp/s",
2654 "sread/s", "swrite/s",
2655 "saccess/s", "sgetatt/s"};
2656 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2657 static double *spmin, *spmax;
2659 static int *outsize;
2661 if (action & F_BEGIN) {
2663 * Allocate arrays that will contain the graphs data
2664 * and the min/max values.
2666 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2669 if (action & F_MAIN) {
2670 /* Check for min/max values */
2671 save_extrema(0, 0, 11, (void *) a->buf[curr], (void *) a->buf[!curr],
2672 itv, spmin, spmax, g_fields);
2675 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2676 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2677 out, outsize, svg_p->restart);
2679 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2680 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2681 out + 1, outsize + 1, svg_p->restart);
2683 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2684 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2685 out + 2, outsize + 2, svg_p->restart);
2687 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2688 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2689 out + 3, outsize + 3, svg_p->restart);
2691 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2692 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2693 out + 4, outsize + 4, svg_p->restart);
2695 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2696 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2697 out + 5, outsize + 5, svg_p->restart);
2699 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2700 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2701 out + 6, outsize + 6, svg_p->restart);
2703 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2704 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2705 out + 7, outsize + 7, svg_p->restart);
2707 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2708 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2709 out + 8, outsize + 8, svg_p->restart);
2711 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2712 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2713 out + 9, outsize + 9, svg_p->restart);
2715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2716 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2717 out + 10, outsize + 10, svg_p->restart);
2720 if (action & F_END) {
2721 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2722 spmin, spmax, out, outsize, svg_p, record_hdr);
2724 /* Free remaining structures */
2725 free_graphs(out, outsize, spmin, spmax);
2730 ***************************************************************************
2731 * Display network socket statistics in SVG.
2734 * @a Activity structure with statistics.
2735 * @curr Index in array for current sample statistics.
2736 * @action Action expected from current function.
2737 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2738 * flag indicating that a restart record has been previously
2739 * found (.@restart) and time used for the X axis origin
2741 * @itv Interval of time in jiffies (only with F_MAIN action).
2742 * @record_hdr Pointer on record header of current stats sample.
2743 ***************************************************************************
2745 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2746 unsigned long long itv, struct record_header *record_hdr)
2748 struct stats_net_sock
2749 *snsc = (struct stats_net_sock *) a->buf[curr];
2750 int group[] = {1, 5};
2751 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2752 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2753 char *g_title[] = {"~totsck",
2754 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2755 int g_fields[] = {0, 1, 5, 2, 3, 4};
2756 static double *spmin, *spmax;
2758 static int *outsize;
2760 if (action & F_BEGIN) {
2762 * Allocate arrays that will contain the graphs data
2763 * and the min/max values.
2765 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2768 if (action & F_MAIN) {
2769 /* Check for min/max values */
2770 save_extrema(0, 0, 6, (void *) a->buf[curr], NULL,
2771 itv, spmin, spmax, g_fields);
2773 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2774 (unsigned long) snsc->sock_inuse,
2775 out, outsize, svg_p->restart);
2777 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2778 (unsigned long) snsc->tcp_inuse,
2779 out + 1, outsize + 1, svg_p->restart);
2781 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2782 (unsigned long) snsc->udp_inuse,
2783 out + 2, outsize + 2, svg_p->restart);
2785 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2786 (unsigned long) snsc->raw_inuse,
2787 out + 3, outsize + 3, svg_p->restart);
2789 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2790 (unsigned long) snsc->frag_inuse,
2791 out + 4, outsize + 4, svg_p->restart);
2793 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2794 (unsigned long) snsc->tcp_tw,
2795 out + 5, outsize + 5, svg_p->restart);
2798 if (action & F_END) {
2799 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2800 spmin, spmax, out, outsize, svg_p, record_hdr);
2802 /* Free remaining structures */
2803 free_graphs(out, outsize, spmin, spmax);
2808 ***************************************************************************
2809 * Display IPv4 network statistics in SVG.
2812 * @a Activity structure with statistics.
2813 * @curr Index in array for current sample statistics.
2814 * @action Action expected from current function.
2815 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2816 * flag indicating that a restart record has been previously
2817 * found (.@restart) and time used for the X axis origin
2819 * @itv Interval of time in jiffies (only with F_MAIN action).
2820 * @record_hdr Pointer on record header of current stats sample.
2821 ***************************************************************************
2823 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2824 unsigned long long itv, struct record_header *record_hdr)
2827 *snic = (struct stats_net_ip *) a->buf[curr],
2828 *snip = (struct stats_net_ip *) a->buf[!curr];
2829 int group[] = {4, 2, 2};
2830 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2831 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2832 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2833 "asmrq/s", "asmok/s",
2834 "fragok/s", "fragcrt/s"};
2835 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2836 static double *spmin, *spmax;
2838 static int *outsize;
2840 if (action & F_BEGIN) {
2842 * Allocate arrays that will contain the graphs data
2843 * and the min/max values.
2845 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2848 if (action & F_MAIN) {
2849 /* Check for min/max values */
2850 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2851 itv, spmin, spmax, g_fields);
2854 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2855 S_VALUE(snip->InReceives, snic->InReceives, itv),
2856 out, outsize, svg_p->restart);
2858 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2859 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2860 out + 1, outsize + 1, svg_p->restart);
2862 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2863 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2864 out + 2, outsize + 2, svg_p->restart);
2866 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2867 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2868 out + 3, outsize + 3, svg_p->restart);
2870 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2871 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2872 out + 4, outsize + 4, svg_p->restart);
2874 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2875 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2876 out + 5, outsize + 5, svg_p->restart);
2878 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2879 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2880 out + 6, outsize + 6, svg_p->restart);
2882 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2883 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2884 out + 7, outsize + 7, svg_p->restart);
2887 if (action & F_END) {
2888 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2889 spmin, spmax, out, outsize, svg_p, record_hdr);
2891 /* Free remaining structures */
2892 free_graphs(out, outsize, spmin, spmax);
2897 ***************************************************************************
2898 * Display IPv4 network errors statistics in SVG.
2901 * @a Activity structure with statistics.
2902 * @curr Index in array for current sample statistics.
2903 * @action Action expected from current function.
2904 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2905 * flag indicating that a restart record has been previously
2906 * found (.@restart) and time used for the X axis origin
2908 * @itv Interval of time in jiffies (only with F_MAIN action).
2909 * @record_hdr Pointer on record header of current stats sample.
2910 ***************************************************************************
2912 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2913 unsigned long long itv, struct record_header *record_hdr)
2915 struct stats_net_eip
2916 *sneic = (struct stats_net_eip *) a->buf[curr],
2917 *sneip = (struct stats_net_eip *) a->buf[!curr];
2918 int group[] = {3, 2, 3};
2919 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2920 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
2921 "IPv4 network errors statistics (3)"};
2922 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
2923 "idisc/s", "odisc/s",
2924 "onort/s", "asmf/s", "fragf/s"};
2925 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2926 static double *spmin, *spmax;
2928 static int *outsize;
2930 if (action & F_BEGIN) {
2932 * Allocate arrays that will contain the graphs data
2933 * and the min/max values.
2935 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2938 if (action & F_MAIN) {
2939 /* Check for min/max values */
2940 save_extrema(8, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
2941 itv, spmin, spmax, g_fields);
2944 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2945 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
2946 out, outsize, svg_p->restart);
2948 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2949 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
2950 out + 1, outsize + 1, svg_p->restart);
2952 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2953 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
2954 out + 2, outsize + 2, svg_p->restart);
2956 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2957 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
2958 out + 3, outsize + 3, svg_p->restart);
2960 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2961 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
2962 out + 4, outsize + 4, svg_p->restart);
2964 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2965 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
2966 out + 5, outsize + 5, svg_p->restart);
2968 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2969 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
2970 out + 6, outsize + 6, svg_p->restart);
2972 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2973 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
2974 out + 7, outsize + 7, svg_p->restart);
2977 if (action & F_END) {
2978 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2979 spmin, spmax, out, outsize, svg_p, record_hdr);
2981 /* Free remaining structures */
2982 free_graphs(out, outsize, spmin, spmax);
2987 ***************************************************************************
2988 * Display ICMPv4 network statistics in SVG.
2991 * @a Activity structure with statistics.
2992 * @curr Index in array for current sample statistics.
2993 * @action Action expected from current function.
2994 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2995 * flag indicating that a restart record has been previously
2996 * found (.@restart) and time used for the X axis origin
2998 * @itv Interval of time in jiffies (only with F_MAIN action).
2999 * @record_hdr Pointer on record header of current stats sample.
3000 ***************************************************************************
3002 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3003 unsigned long long itv, struct record_header *record_hdr)
3005 struct stats_net_icmp
3006 *snic = (struct stats_net_icmp *) a->buf[curr],
3007 *snip = (struct stats_net_icmp *) a->buf[!curr];
3008 int group[] = {2, 4, 4, 4};
3009 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3011 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3012 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3013 char *g_title[] = {"imsg/s", "omsg/s",
3014 "iech/s", "iechr/s", "oech/s", "oechr/s",
3015 "itm/s", "itmr/s", "otm/s", "otmr/s",
3016 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3017 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3018 static double *spmin, *spmax;
3020 static int *outsize;
3022 if (action & F_BEGIN) {
3024 * Allocate arrays that will contain the graphs data
3025 * and the min/max values.
3027 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3030 if (action & F_MAIN) {
3031 /* Check for min/max values */
3032 save_extrema(0, 14, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3033 itv, spmin, spmax, g_fields);
3036 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3037 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3038 out, outsize, svg_p->restart);
3040 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3041 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3042 out + 1, outsize + 1, svg_p->restart);
3044 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3045 S_VALUE(snip->InEchos, snic->InEchos, itv),
3046 out + 2, outsize + 2, svg_p->restart);
3048 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3049 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3050 out + 3, outsize + 3, svg_p->restart);
3052 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3053 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3054 out + 4, outsize + 4, svg_p->restart);
3056 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3057 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3058 out + 5, outsize + 5, svg_p->restart);
3060 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3061 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3062 out + 6, outsize + 6, svg_p->restart);
3064 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3065 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3066 out + 7, outsize + 7, svg_p->restart);
3068 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3069 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3070 out + 8, outsize + 8, svg_p->restart);
3072 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3073 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3074 out + 9, outsize + 9, svg_p->restart);
3076 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3077 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3078 out + 10, outsize + 10, svg_p->restart);
3080 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3081 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3082 out + 11, outsize + 11, svg_p->restart);
3084 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3085 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3086 out + 12, outsize + 12, svg_p->restart);
3088 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3089 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3090 out + 13, outsize + 13, svg_p->restart);
3093 if (action & F_END) {
3094 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3095 spmin, spmax, out, outsize, svg_p, record_hdr);
3097 /* Free remaining structures */
3098 free_graphs(out, outsize, spmin, spmax);
3103 ***************************************************************************
3104 * Display ICMPv4 network errors statistics in SVG.
3107 * @a Activity structure with statistics.
3108 * @curr Index in array for current sample statistics.
3109 * @action Action expected from current function.
3110 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3111 * flag indicating that a restart record has been previously
3112 * found (.@restart) and time used for the X axis origin
3114 * @itv Interval of time in jiffies (only with F_MAIN action).
3115 * @record_hdr Pointer on record header of current stats sample.
3116 ***************************************************************************
3118 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3119 unsigned long long itv, struct record_header *record_hdr)
3121 struct stats_net_eicmp
3122 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3123 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3124 int group[] = {2, 2, 2, 2, 2, 2};
3125 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3126 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3127 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3128 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3129 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3130 char *g_title[] = {"ierr/s", "oerr/s",
3131 "idstunr/s", "odstunr/s",
3132 "itmex/s", "otmex/s",
3133 "iparmpb/s", "oparmpb/s",
3134 "isrcq/s", "osrcq/s",
3135 "iredir/s", "oredir/s"};
3136 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3137 static double *spmin, *spmax;
3139 static int *outsize;
3141 if (action & F_BEGIN) {
3143 * Allocate arrays that will contain the graphs data
3144 * and the min/max values.
3146 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3149 if (action & F_MAIN) {
3150 /* Check for min/max values */
3151 save_extrema(0, 12, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3152 itv, spmin, spmax, g_fields);
3155 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3156 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3157 out, outsize, svg_p->restart);
3159 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3160 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3161 out + 1, outsize + 1, svg_p->restart);
3163 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3164 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3165 out + 2, outsize + 2, svg_p->restart);
3167 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3168 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3169 out + 3, outsize + 3, svg_p->restart);
3171 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3172 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3173 out + 4, outsize + 4, svg_p->restart);
3175 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3176 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3177 out + 5, outsize + 5, svg_p->restart);
3179 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3180 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3181 out + 6, outsize + 6, svg_p->restart);
3183 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3184 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3185 out + 7, outsize + 7, svg_p->restart);
3187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3188 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3189 out + 8, outsize + 8, svg_p->restart);
3191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3192 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3193 out + 9, outsize + 9, svg_p->restart);
3195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3196 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3197 out + 10, outsize + 10, svg_p->restart);
3199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3200 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3201 out + 11, outsize + 11, svg_p->restart);
3204 if (action & F_END) {
3205 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3206 spmin, spmax, out, outsize, svg_p, record_hdr);
3208 /* Free remaining structures */
3209 free_graphs(out, outsize, spmin, spmax);
3214 ***************************************************************************
3215 * Display TCPv4 network statistics in SVG.
3218 * @a Activity structure with statistics.
3219 * @curr Index in array for current sample statistics.
3220 * @action Action expected from current function.
3221 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3222 * flag indicating that a restart record has been previously
3223 * found (.@restart) and time used for the X axis origin
3225 * @itv Interval of time in jiffies (only with F_MAIN action).
3226 * @record_hdr Pointer on record header of current stats sample.
3227 ***************************************************************************
3229 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3230 unsigned long long itv, struct record_header *record_hdr)
3232 struct stats_net_tcp
3233 *sntc = (struct stats_net_tcp *) a->buf[curr],
3234 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3235 int group[] = {2, 2};
3236 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3237 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3238 char *g_title[] = {"active/s", "passive/s",
3239 "iseg/s", "oseg/s"};
3240 int g_fields[] = {0, 1, 2, 3};
3241 static double *spmin, *spmax;
3243 static int *outsize;
3245 if (action & F_BEGIN) {
3247 * Allocate arrays that will contain the graphs data
3248 * and the min/max values.
3250 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3253 if (action & F_MAIN) {
3254 /* Check for min/max values */
3255 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3256 itv, spmin, spmax, g_fields);
3259 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3260 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3261 out, outsize, svg_p->restart);
3263 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3264 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3265 out + 1, outsize + 1, svg_p->restart);
3267 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3268 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3269 out + 2, outsize + 2, svg_p->restart);
3271 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3272 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3273 out + 3, outsize + 3, svg_p->restart);
3276 if (action & F_END) {
3277 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3278 spmin, spmax, out, outsize, svg_p, record_hdr);
3280 /* Free remaining structures */
3281 free_graphs(out, outsize, spmin, spmax);
3286 ***************************************************************************
3287 * Display TCPv4 network errors statistics in SVG.
3290 * @a Activity structure with statistics.
3291 * @curr Index in array for current sample statistics.
3292 * @action Action expected from current function.
3293 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3294 * flag indicating that a restart record has been previously
3295 * found (.@restart) and time used for the X axis origin
3297 * @itv Interval of time in jiffies (only with F_MAIN action).
3298 * @record_hdr Pointer on record header of current stats sample.
3299 ***************************************************************************
3301 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3302 unsigned long long itv, struct record_header *record_hdr)
3304 struct stats_net_etcp
3305 *snetc = (struct stats_net_etcp *) a->buf[curr],
3306 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3307 int group[] = {2, 3};
3308 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3309 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3310 char *g_title[] = {"atmptf/s", "estres/s",
3311 "retrans/s", "isegerr/s", "orsts/s"};
3312 int g_fields[] = {0, 1, 2, 3, 4};
3313 static double *spmin, *spmax;
3315 static int *outsize;
3317 if (action & F_BEGIN) {
3319 * Allocate arrays that will contain the graphs data
3320 * and the min/max values.
3322 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3325 if (action & F_MAIN) {
3326 /* Check for min/max values */
3327 save_extrema(0, 5, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3328 itv, spmin, spmax, g_fields);
3331 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3332 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3333 out, outsize, svg_p->restart);
3335 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3336 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3337 out + 1, outsize + 1, svg_p->restart);
3339 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3340 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3341 out + 2, outsize + 2, svg_p->restart);
3343 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3344 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3345 out + 3, outsize + 3, svg_p->restart);
3347 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3348 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3349 out + 4, outsize + 4, svg_p->restart);
3352 if (action & F_END) {
3353 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3354 spmin, spmax, out, outsize, svg_p, record_hdr);
3356 /* Free remaining structures */
3357 free_graphs(out, outsize, spmin, spmax);
3362 ***************************************************************************
3363 * Display UDPv4 network statistics in SVG.
3366 * @a Activity structure with statistics.
3367 * @curr Index in array for current sample statistics.
3368 * @action Action expected from current function.
3369 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3370 * flag indicating that a restart record has been previously
3371 * found (.@restart) and time used for the X axis origin
3373 * @itv Interval of time in jiffies (only with F_MAIN action).
3374 * @record_hdr Pointer on record header of current stats sample.
3375 ***************************************************************************
3377 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3378 unsigned long long itv, struct record_header *record_hdr)
3380 struct stats_net_udp
3381 *snuc = (struct stats_net_udp *) a->buf[curr],
3382 *snup = (struct stats_net_udp *) a->buf[!curr];
3383 int group[] = {2, 2};
3384 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3385 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3386 char *g_title[] = {"idgm/s", "odgm/s",
3387 "noport/s", "idgmerr/s"};
3388 int g_fields[] = {0, 1, 2, 3};
3389 static double *spmin, *spmax;
3391 static int *outsize;
3393 if (action & F_BEGIN) {
3395 * Allocate arrays that will contain the graphs data
3396 * and the min/max values.
3398 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3401 if (action & F_MAIN) {
3402 /* Check for min/max values */
3403 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3404 itv, spmin, spmax, g_fields);
3407 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3408 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3409 out, outsize, svg_p->restart);
3411 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3412 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3413 out + 1, outsize + 1, svg_p->restart);
3415 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3416 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3417 out + 2, outsize + 2, svg_p->restart);
3419 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3420 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3421 out + 3, outsize + 3, svg_p->restart);
3424 if (action & F_END) {
3425 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3426 spmin, spmax, out, outsize, svg_p, record_hdr);
3428 /* Free remaining structures */
3429 free_graphs(out, outsize, spmin, spmax);
3434 ***************************************************************************
3435 * Display IPV6 network socket statistics in SVG.
3438 * @a Activity structure with statistics.
3439 * @curr Index in array for current sample statistics.
3440 * @action Action expected from current function.
3441 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3442 * flag indicating that a restart record has been previously
3443 * found (.@restart) and time used for the X axis origin
3445 * @itv Interval of time in jiffies (only with F_MAIN action).
3446 * @record_hdr Pointer on record header of current stats sample.
3447 ***************************************************************************
3449 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3450 unsigned long long itv, struct record_header *record_hdr)
3452 struct stats_net_sock6
3453 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3455 int g_type[] = {SVG_LINE_GRAPH};
3456 char *title[] = {"IPv6 network sockets"};
3457 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3458 int g_fields[] = {0, 1, 2, 3};
3459 static double *spmin, *spmax;
3461 static int *outsize;
3463 if (action & F_BEGIN) {
3465 * Allocate arrays that will contain the graphs data
3466 * and the min/max values.
3468 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3471 if (action & F_MAIN) {
3472 /* Check for min/max values */
3473 save_extrema(0, 0, 4, (void *) a->buf[curr], NULL,
3474 itv, spmin, spmax, g_fields);
3476 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3477 (unsigned long) snsc->tcp6_inuse,
3478 out, outsize, svg_p->restart);
3480 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3481 (unsigned long) snsc->udp6_inuse,
3482 out + 1, outsize + 1, svg_p->restart);
3484 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3485 (unsigned long) snsc->raw6_inuse,
3486 out + 2, outsize + 2, svg_p->restart);
3488 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3489 (unsigned long) snsc->frag6_inuse,
3490 out + 3, outsize + 3, svg_p->restart);
3493 if (action & F_END) {
3494 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3495 spmin, spmax, out, outsize, svg_p, record_hdr);
3497 /* Free remaining structures */
3498 free_graphs(out, outsize, spmin, spmax);
3503 ***************************************************************************
3504 * Display IPv6 network statistics in SVG.
3507 * @a Activity structure with statistics.
3508 * @curr Index in array for current sample statistics.
3509 * @action Action expected from current function.
3510 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3511 * flag indicating that a restart record has been previously
3512 * found (.@restart) and time used for the X axis origin
3514 * @itv Interval of time in jiffies (only with F_MAIN action).
3515 * @record_hdr Pointer on record header of current stats sample.
3516 ***************************************************************************
3518 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3519 unsigned long long itv, struct record_header *record_hdr)
3521 struct stats_net_ip6
3522 *snic = (struct stats_net_ip6 *) a->buf[curr],
3523 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3524 int group[] = {4, 2, 2, 2};
3525 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3527 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3528 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3529 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3530 "asmrq6/s", "asmok6/s",
3531 "imcpck6/s", "omcpck6/s",
3532 "fragok6/s", "fragcr6/s"};
3533 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3534 static double *spmin, *spmax;
3536 static int *outsize;
3538 if (action & F_BEGIN) {
3540 * Allocate arrays that will contain the graphs data
3541 * and the min/max values.
3543 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3546 if (action & F_MAIN) {
3547 /* Check for min/max values */
3548 save_extrema(10, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3549 itv, spmin, spmax, g_fields);
3552 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3553 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3554 out, outsize, svg_p->restart);
3556 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3557 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3558 out + 1, outsize + 1, svg_p->restart);
3560 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3561 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3562 out + 2, outsize + 2, svg_p->restart);
3564 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3565 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3566 out + 3, outsize + 3, svg_p->restart);
3568 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3569 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3570 out + 4, outsize + 4, svg_p->restart);
3572 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3573 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3574 out + 5, outsize + 5, svg_p->restart);
3576 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3577 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3578 out + 6, outsize + 6, svg_p->restart);
3580 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3581 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3582 out + 7, outsize + 7, svg_p->restart);
3584 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3585 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3586 out + 8, outsize + 8, svg_p->restart);
3588 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3589 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3590 out + 9, outsize + 9, svg_p->restart);
3593 if (action & F_END) {
3594 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3595 spmin, spmax, out, outsize, svg_p, record_hdr);
3597 /* Free remaining structures */
3598 free_graphs(out, outsize, spmin, spmax);
3603 ***************************************************************************
3604 * Display IPv6 network errors statistics in SVG.
3607 * @a Activity structure with statistics.
3608 * @curr Index in array for current sample statistics.
3609 * @action Action expected from current function.
3610 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3611 * flag indicating that a restart record has been previously
3612 * found (.@restart) and time used for the X axis origin
3614 * @itv Interval of time in jiffies (only with F_MAIN action).
3615 * @record_hdr Pointer on record header of current stats sample.
3616 ***************************************************************************
3618 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3619 unsigned long long itv, struct record_header *record_hdr)
3621 struct stats_net_eip6
3622 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3623 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3624 int group[] = {4, 2, 2, 3};
3625 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3627 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3628 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3629 "IPv6 network errors statistics (5)"};
3630 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3631 "idisc6/s", "odisc6/s",
3632 "inort6/s", "onort6/s",
3633 "asmf6/s", "fragf6/s", "itrpck6/s"};
3634 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3635 static double *spmin, *spmax;
3637 static int *outsize;
3639 if (action & F_BEGIN) {
3641 * Allocate arrays that will contain the graphs data
3642 * and the min/max values.
3644 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3647 if (action & F_MAIN) {
3648 /* Check for min/max values */
3649 save_extrema(11, 0, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3650 itv, spmin, spmax, g_fields);
3653 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3654 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3655 out, outsize, svg_p->restart);
3657 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3658 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3659 out + 1, outsize + 1, svg_p->restart);
3661 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3662 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3663 out + 2, outsize + 2, svg_p->restart);
3665 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3666 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3667 out + 3, outsize + 3, svg_p->restart);
3669 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3670 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3671 out + 4, outsize + 4, svg_p->restart);
3673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3674 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3675 out + 5, outsize + 5, svg_p->restart);
3677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3678 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3679 out + 6, outsize + 6, svg_p->restart);
3681 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3682 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3683 out + 7, outsize + 7, svg_p->restart);
3685 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3686 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3687 out + 8, outsize + 8, svg_p->restart);
3689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3690 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3691 out + 9, outsize + 9, svg_p->restart);
3693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3694 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3695 out + 10, outsize + 10, svg_p->restart);
3698 if (action & F_END) {
3699 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3700 spmin, spmax, out, outsize, svg_p, record_hdr);
3702 /* Free remaining structures */
3703 free_graphs(out, outsize, spmin, spmax);
3708 ***************************************************************************
3709 * Display ICMPv6 network statistics in SVG.
3712 * @a Activity structure with statistics.
3713 * @curr Index in array for current sample statistics.
3714 * @action Action expected from current function.
3715 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3716 * flag indicating that a restart record has been previously
3717 * found (.@restart) and time used for the X axis origin
3719 * @itv Interval of time in jiffies (only with F_MAIN action).
3720 * @record_hdr Pointer on record header of current stats sample.
3721 ***************************************************************************
3723 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3724 unsigned long long itv, struct record_header *record_hdr)
3726 struct stats_net_icmp6
3727 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3728 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3729 int group[] = {2, 3, 5, 3, 4};
3730 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3731 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3732 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3733 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3734 "ICMPv6 network statistics (5)"};
3735 char *g_title[] = {"imsg6/s", "omsg6/s",
3736 "iech6/s", "iechr6/s", "oechr6/s",
3737 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3738 "irtsol6/s", "ortsol6/s", "irtad6/s",
3739 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3740 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3741 static double *spmin, *spmax;
3743 static int *outsize;
3745 if (action & F_BEGIN) {
3747 * Allocate arrays that will contain the graphs data
3748 * and the min/max values.
3750 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3753 if (action & F_MAIN) {
3754 /* Check for min/max values */
3755 save_extrema(0, 17, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3756 itv, spmin, spmax, g_fields);
3759 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3760 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3761 out, outsize, svg_p->restart);
3763 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3764 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3765 out + 1, outsize + 1, svg_p->restart);
3767 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3768 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3769 out + 2, outsize + 2, svg_p->restart);
3771 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3772 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3773 out + 3, outsize + 3, svg_p->restart);
3775 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3776 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3777 out + 4, outsize + 4, svg_p->restart);
3779 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3780 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3781 out + 5, outsize + 5, svg_p->restart);
3783 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3784 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3785 out + 6, outsize + 6, svg_p->restart);
3787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3788 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3789 out + 7, outsize + 7, svg_p->restart);
3791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3792 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3793 out + 8, outsize + 8, svg_p->restart);
3795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3796 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3797 out + 9, outsize + 9, svg_p->restart);
3799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3800 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3801 out + 10, outsize + 10, svg_p->restart);
3803 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3804 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3805 out + 11, outsize + 11, svg_p->restart);
3807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3808 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3809 out + 12, outsize + 12, svg_p->restart);
3811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3812 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3813 out + 13, outsize + 13, svg_p->restart);
3815 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3816 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3817 out + 14, outsize + 14, svg_p->restart);
3819 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3820 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3821 out + 15, outsize + 15, svg_p->restart);
3823 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3824 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3825 out + 16, outsize + 16, svg_p->restart);
3828 if (action & F_END) {
3829 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3830 spmin, spmax, out, outsize, svg_p, record_hdr);
3832 /* Free remaining structures */
3833 free_graphs(out, outsize, spmin, spmax);
3838 ***************************************************************************
3839 * Display ICMPv6 network errors statistics in SVG.
3842 * @a Activity structure with statistics.
3843 * @curr Index in array for current sample statistics.
3844 * @action Action expected from current function.
3845 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3846 * flag indicating that a restart record has been previously
3847 * found (.@restart) and time used for the X axis origin
3849 * @itv Interval of time in jiffies (only with F_MAIN action).
3850 * @record_hdr Pointer on record header of current stats sample.
3851 ***************************************************************************
3853 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3854 unsigned long long itv, struct record_header *record_hdr)
3856 struct stats_net_eicmp6
3857 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3858 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3859 int group[] = {1, 2, 2, 2, 2, 2};
3860 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3861 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3862 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3863 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3864 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3865 char *g_title[] = {"ierr6/s",
3866 "idtunr6/s", "odtunr6/s",
3867 "itmex6/s", "otmex6/s",
3868 "iprmpb6/s", "oprmpb6/s",
3869 "iredir6/s", "oredir6/s",
3870 "ipck2b6/s", "opck2b6/s"};
3871 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3872 static double *spmin, *spmax;
3874 static int *outsize;
3876 if (action & F_BEGIN) {
3878 * Allocate arrays that will contain the graphs data
3879 * and the min/max values.
3881 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3884 if (action & F_MAIN) {
3885 /* Check for min/max values */
3886 save_extrema(0, 11, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3887 itv, spmin, spmax, g_fields);
3890 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3891 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
3892 out, outsize, svg_p->restart);
3894 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3895 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
3896 out + 1, outsize + 1, svg_p->restart);
3898 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3899 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
3900 out + 2, outsize + 2, svg_p->restart);
3902 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3903 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
3904 out + 3, outsize + 3, svg_p->restart);
3906 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3907 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
3908 out + 4, outsize + 4, svg_p->restart);
3910 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3911 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
3912 out + 5, outsize + 5, svg_p->restart);
3914 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3915 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
3916 out + 6, outsize + 6, svg_p->restart);
3918 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3919 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
3920 out + 7, outsize + 7, svg_p->restart);
3922 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3923 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
3924 out + 8, outsize + 8, svg_p->restart);
3926 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3927 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
3928 out + 9, outsize + 9, svg_p->restart);
3930 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3931 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
3932 out + 10, outsize + 10, svg_p->restart);
3935 if (action & F_END) {
3936 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3937 spmin, spmax, out, outsize, svg_p, record_hdr);
3939 /* Free remaining structures */
3940 free_graphs(out, outsize, spmin, spmax);
3945 ***************************************************************************
3946 * Display UDPv6 network statistics in SVG.
3949 * @a Activity structure with statistics.
3950 * @curr Index in array for current sample statistics.
3951 * @action Action expected from current function.
3952 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3953 * flag indicating that a restart record has been previously
3954 * found (.@restart) and time used for the X axis origin
3956 * @itv Interval of time in jiffies (only with F_MAIN action).
3957 * @record_hdr Pointer on record header of current stats sample.
3958 ***************************************************************************
3960 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3961 unsigned long long itv, struct record_header *record_hdr)
3963 struct stats_net_udp6
3964 *snuc = (struct stats_net_udp6 *) a->buf[curr],
3965 *snup = (struct stats_net_udp6 *) a->buf[!curr];
3966 int group[] = {2, 2};
3967 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3968 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
3969 char *g_title[] = {"idgm6/s", "odgm6/s",
3970 "noport6/s", "idgmer6/s"};
3971 int g_fields[] = {0, 1, 2, 3};
3972 static double *spmin, *spmax;
3974 static int *outsize;
3976 if (action & F_BEGIN) {
3978 * Allocate arrays that will contain the graphs data
3979 * and the min/max values.
3981 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3984 if (action & F_MAIN) {
3985 /* Check for min/max values */
3986 save_extrema(0, 4, 0, (void *) a->buf[curr], (void *) a->buf[!curr],
3987 itv, spmin, spmax, g_fields);
3990 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3991 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
3992 out, outsize, svg_p->restart);
3994 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3995 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
3996 out + 1, outsize + 1, svg_p->restart);
3998 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3999 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4000 out + 2, outsize + 2, svg_p->restart);
4002 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4003 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4004 out + 3, outsize + 3, svg_p->restart);
4007 if (action & F_END) {
4008 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4009 spmin, spmax, out, outsize, svg_p, record_hdr);
4011 /* Free remaining structures */
4012 free_graphs(out, outsize, spmin, spmax);
4017 ***************************************************************************
4018 * Display CPU frequency statistics in SVG.
4021 * @a Activity structure with statistics.
4022 * @curr Index in array for current sample statistics.
4023 * @action Action expected from current function.
4024 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4025 * flag indicating that a restart record has been previously
4026 * found (.@restart) and time used for the X axis origin
4028 * @itv Interval of time in jiffies (unused here).
4029 * @record_hdr Pointer on record header of current stats sample.
4030 ***************************************************************************
4032 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4033 unsigned long long itv, struct record_header *record_hdr)
4035 struct stats_pwr_cpufreq *spc, *spp;
4037 int g_type[] = {SVG_LINE_GRAPH};
4038 char *title[] = {"CPU frequency"};
4039 char *g_title[] = {"MHz"};
4040 static double *spmin, *spmax;
4042 static int *outsize;
4046 if (action & F_BEGIN) {
4048 * Allocate arrays that will contain the graphs data
4049 * and the min/max values.
4051 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4054 if (action & F_MAIN) {
4056 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4058 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4059 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4061 /* Should current CPU (including CPU "all") be displayed? */
4062 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4067 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4068 ((double) spp->cpufreq) / 100,
4069 ((double) spc->cpufreq) / 100,
4070 out + i, outsize + i, svg_p->restart, svg_p->dt,
4071 spmin + i, spmax + i);
4075 if (action & F_END) {
4076 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4078 /* Should current CPU (including CPU "all") be displayed? */
4079 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4084 /* This is CPU "all" */
4085 strcpy(item_name, "all");
4088 sprintf(item_name, "%d", i - 1);
4091 draw_activity_graphs(a->g_nr, g_type,
4092 title, g_title, item_name, group,
4093 spmin + i, spmax + i, out + i, outsize + i,
4097 /* Free remaining structures */
4098 free_graphs(out, outsize, spmin, spmax);
4103 ***************************************************************************
4104 * Display fan statistics in SVG.
4107 * @a Activity structure with statistics.
4108 * @curr Index in array for current sample statistics.
4109 * @action Action expected from current function.
4110 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4111 * flag indicating that a restart record has been previously
4112 * found (.@restart) and time used for the X axis origin
4114 * @itv Interval of time in jiffies (unused here).
4115 * @record_hdr Pointer on record header of current stats sample.
4116 ***************************************************************************
4118 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4119 unsigned long long itv, struct record_header *record_hdr)
4121 struct stats_pwr_fan *spc, *spp;
4123 int g_type[] = {SVG_LINE_GRAPH};
4124 char *title[] = {"Fan speed"};
4125 char *g_title[] = {"~rpm"};
4126 static double *spmin, *spmax;
4128 static int *outsize;
4129 char item_name[MAX_SENSORS_DEV_LEN + 8];
4132 if (action & F_BEGIN) {
4134 * Allocate arrays that will contain the graphs data
4135 * and the min/max values.
4137 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4140 if (action & F_MAIN) {
4142 for (i = 0; i < a->nr; i++) {
4144 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4145 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4148 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4151 out + i, outsize + i, svg_p->restart, svg_p->dt,
4152 spmin + i, spmax + i);
4156 if (action & F_END) {
4157 for (i = 0; i < a->nr; i++) {
4159 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4161 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4162 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4164 draw_activity_graphs(a->g_nr, g_type,
4165 title, g_title, item_name, group,
4166 spmin + i, spmax + i, out + i, outsize + i,
4170 /* Free remaining structures */
4171 free_graphs(out, outsize, spmin, spmax);
4176 ***************************************************************************
4177 * Display temperature statistics in SVG.
4180 * @a Activity structure with statistics.
4181 * @curr Index in array for current sample statistics.
4182 * @action Action expected from current function.
4183 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4184 * flag indicating that a restart record has been previously
4185 * found (.@restart) and time used for the X axis origin
4187 * @itv Interval of time in jiffies (unused here).
4188 * @record_hdr Pointer on record header of current stats sample.
4189 ***************************************************************************
4191 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4192 unsigned long long itv, struct record_header *record_hdr)
4194 struct stats_pwr_temp *spc;
4195 int group[] = {1, 1};
4196 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4197 char *title[] = {"Device temperature (1)",
4198 "Device temperature (2)"};
4199 char *g_title[] = {"~degC",
4201 static double *spmin, *spmax;
4203 static int *outsize;
4204 char item_name[MAX_SENSORS_DEV_LEN + 8];
4208 if (action & F_BEGIN) {
4210 * Allocate arrays that will contain the graphs data
4211 * and the min/max values.
4213 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4216 if (action & F_MAIN) {
4217 /* For each temperature sensor */
4218 for (i = 0; i < a->nr; i++) {
4220 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4222 /* Look for min/max values */
4223 if (spc->temp < *(spmin + 2 * i)) {
4224 *(spmin + 2 * i) = spc->temp;
4226 if (spc->temp > *(spmax + 2 * i)) {
4227 *(spmax + 2 * i) = spc->temp;
4229 tval = (spc->temp_max - spc->temp_min) ?
4230 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4232 if (tval < *(spmin + 2 * i + 1)) {
4233 *(spmin + 2 * i + 1) = tval;
4235 if (tval > *(spmax + 2 * i + 1)) {
4236 *(spmax + 2 * i + 1) = tval;
4240 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4242 out + 2 * i, outsize + 2 * i, svg_p->restart);
4244 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4246 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4250 if (action & F_END) {
4251 for (i = 0; i < a->nr; i++) {
4253 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4255 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4256 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4258 draw_activity_graphs(a->g_nr, g_type,
4259 title, g_title, item_name, group,
4260 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4264 /* Free remaining structures */
4265 free_graphs(out, outsize, spmin, spmax);
4270 ***************************************************************************
4271 * Display voltage inputs statistics in SVG.
4274 * @a Activity structure with statistics.
4275 * @curr Index in array for current sample statistics.
4276 * @action Action expected from current function.
4277 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4278 * flag indicating that a restart record has been previously
4279 * found (.@restart) and time used for the X axis origin
4281 * @itv Interval of time in jiffies (only with F_MAIN action).
4282 * @record_hdr Pointer on record header of current stats sample.
4283 ***************************************************************************
4285 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4286 unsigned long long itv, struct record_header *record_hdr)
4288 struct stats_pwr_in *spc;
4289 int group[] = {1, 1};
4290 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4291 char *title[] = {"Voltage inputs (1)",
4292 "Voltage inputs (2)"};
4293 char *g_title[] = {"inV",
4295 static double *spmin, *spmax;
4297 static int *outsize;
4298 char item_name[MAX_SENSORS_DEV_LEN + 8];
4302 if (action & F_BEGIN) {
4304 * Allocate arrays that will contain the graphs data
4305 * and the min/max values.
4307 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4310 if (action & F_MAIN) {
4311 /* For each temperature sensor */
4312 for (i = 0; i < a->nr; i++) {
4314 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4316 /* Look for min/max values */
4317 if (spc->in < *(spmin + 2 * i)) {
4318 *(spmin + 2 * i) = spc->in;
4320 if (spc->in > *(spmax + 2 * i)) {
4321 *(spmax + 2 * i) = spc->in;
4323 tval = (spc->in_max - spc->in_min) ?
4324 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4326 if (tval < *(spmin + 2 * i + 1)) {
4327 *(spmin + 2 * i + 1) = tval;
4329 if (tval > *(spmax + 2 * i + 1)) {
4330 *(spmax + 2 * i + 1) = tval;
4334 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4336 out + 2 * i, outsize + 2 * i, svg_p->restart);
4338 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4340 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4344 if (action & F_END) {
4345 for (i = 0; i < a->nr; i++) {
4347 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4349 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4350 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4352 draw_activity_graphs(a->g_nr, g_type,
4353 title, g_title, item_name, group,
4354 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4358 /* Free remaining structures */
4359 free_graphs(out, outsize, spmin, spmax);
4364 ***************************************************************************
4365 * Display huge pages statistics in SVG.
4368 * @a Activity structure with statistics.
4369 * @curr Index in array for current sample statistics.
4370 * @action Action expected from current function.
4371 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4372 * flag indicating that a restart record has been previously
4373 * found (.@restart) and time used for the X axis origin
4375 * @itv Interval of time in jiffies (only with F_MAIN action).
4376 * @record_hdr Pointer on record header of current stats sample.
4377 ***************************************************************************
4379 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4380 unsigned long long itv, struct record_header *record_hdr)
4383 *smc = (struct stats_huge *) a->buf[curr];
4384 int group[] = {2, 1};
4385 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4386 char *title[] = {"Huge pages utilization (1)",
4387 "Huge pages utilization (2)"};
4388 char *g_title[] = {"~kbhugfree", "~kbhugused",
4390 int g_fields[] = {0};
4391 static double *spmin, *spmax;
4393 static int *outsize;
4396 if (action & F_BEGIN) {
4398 * Allocate arrays that will contain the graphs data
4399 * and the min/max values.
4401 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4404 if (action & F_MAIN) {
4405 /* Check for min/max values */
4406 save_extrema(0, 1, 0, (void *) a->buf[curr], NULL,
4407 itv, spmin, spmax, g_fields);
4409 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4410 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4412 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4413 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4415 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4416 if (tval < *(spmin + 2)) {
4417 *(spmin + 2) = tval;
4419 if (tval > *(spmax + 2)) {
4420 *(spmax + 2) = tval;
4424 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4425 (unsigned long) smc->frhkb,
4426 out, outsize, svg_p->restart);
4428 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4429 (unsigned long) smc->tlhkb - smc->frhkb,
4430 out + 1, outsize + 1, svg_p->restart);
4432 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4434 out + 2, outsize + 2, svg_p->dt);
4437 if (action & F_END) {
4438 draw_activity_graphs(a->g_nr, g_type,
4439 title, g_title, NULL, group,
4440 spmin, spmax, out, outsize, svg_p, record_hdr);
4442 /* Free remaining structures */
4443 free_graphs(out, outsize, spmin, spmax);
4448 ***************************************************************************
4449 * Display filesystem statistics in SVG.
4452 * @a Activity structure with statistics.
4453 * @curr Index in array for current sample statistics.
4454 * @action Action expected from current function.
4455 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4456 * flag indicating that a restart record has been previously
4457 * found (.@restart) and time used for the X axis origin
4459 * @itv Interval of time in jiffies (unused here).
4460 * @record_hdr Pointer on record header of current stats sample.
4461 ***************************************************************************
4463 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4464 unsigned long long itv, struct record_header *record_hdr)
4466 struct stats_filesystem *sfc, *sfp;
4467 int group[] = {2, 2, 2, 1};
4468 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4469 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4470 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4471 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4472 char *g_title[] = {"~MBfsfree", "~MBfsused",
4473 "%ufsused", "%fsused",
4474 "Ifree/1000", "Iused/1000",
4476 static double *spmin, *spmax;
4478 static int *outsize;
4481 int i, k, pos, restart;
4483 if (action & F_BEGIN) {
4485 * Allocate arrays (#0..6) that will contain the graphs data
4486 * and the min/max values.
4487 * Also allocate two additional arrays (#7..8) for each filesystem:
4488 * out + 7 will contain the filesystem name,
4489 * out + 8 will contain the mount point.
4491 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
4494 if (action & F_MAIN) {
4495 /* For each filesystem structure */
4496 for (i = 0; i < a->nr; i++) {
4497 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4500 /* Size of filesystem is zero: We are at the end of the list */
4503 /* Look for corresponding graph */
4504 for (k = 0; k < a->nr; k++) {
4505 item_name = *(out + k * 9 + 7);
4506 if (!strcmp(sfc->fs_name, item_name))
4512 /* Graph not found: Look for first free entry */
4513 for (k = 0; k < a->nr; k++) {
4514 item_name = *(out + k * 9 + 7);
4515 if (!strcmp(item_name, ""))
4519 /* No free graph entry: Graph for this item won't be drawn */
4525 if (!item_name[0]) {
4526 /* Save filesystem name and mount point (if not already done) */
4527 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4528 item_name[CHUNKSIZE - 1] = '\0';
4529 item_name = *(out + pos + 8);
4530 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4531 item_name[CHUNKSIZE - 1] = '\0';
4535 for (k = 0; k < a->nr; k++) {
4536 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4537 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4538 /* Filesystem found in previous sample */
4539 restart = svg_p->restart;
4543 /* Check for min/max values */
4545 /* Compute fsfree min/max values */
4546 tval = (double) sfc->f_bfree;
4547 if (tval > *(spmax + pos)) {
4548 *(spmax + pos) = tval;
4550 if (tval < *(spmin + pos)) {
4551 *(spmin + pos) = tval;
4553 /* Compute fsused min/max values */
4554 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4555 if (tval > *(spmax + pos + 1)) {
4556 *(spmax + pos + 1) = tval;
4558 if (tval < *(spmin + pos + 1)) {
4559 *(spmin + pos + 1) = tval;
4561 /* Compute %ufsused min/max values */
4562 tval = sfc->f_blocks ?
4563 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4564 if (tval > *(spmax + pos + 2)) {
4565 *(spmax + pos + 2) = tval;
4567 if (tval < *(spmin + pos + 2)) {
4568 *(spmin + pos + 2) = tval;
4570 /* Compute %fsused min/max values */
4571 tval = sfc->f_blocks ?
4572 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4573 if (tval > *(spmax + pos + 3)) {
4574 *(spmax + pos + 3) = tval;
4576 if (tval < *(spmin + pos + 3)) {
4577 *(spmin + pos + 3) = tval;
4579 /* Compute Ifree min/max values */
4580 tval = (double) sfc->f_ffree;
4581 if (tval > *(spmax + pos + 4)) {
4582 *(spmax + pos + 4) = tval;
4584 if (tval < *(spmin + pos + 4)) {
4585 *(spmin + pos + 4) = tval;
4587 /* Compute Iused min/max values */
4588 tval = (double) (sfc->f_files - sfc->f_ffree);
4589 if (tval > *(spmax + pos + 5)) {
4590 *(spmax + pos + 5) = tval;
4592 if (tval < *(spmin + pos + 5)) {
4593 *(spmin + pos + 5) = tval;
4595 /* Compute %Iused min/max values */
4596 tval = sfc->f_files ?
4597 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4598 if (tval > *(spmax + pos + 6)) {
4599 *(spmax + pos + 6) = tval;
4601 if (tval < *(spmin + pos + 6)) {
4602 *(spmin + pos + 6) = tval;
4606 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4607 (double) sfc->f_bfree / 1024 / 1024,
4608 out + pos, outsize + pos, restart);
4610 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4611 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4612 out + pos + 1, outsize + pos + 1, restart);
4614 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4617 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4618 out + pos + 2, outsize + pos + 2, svg_p->dt);
4620 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4623 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4624 out + pos + 3, outsize + pos + 3, svg_p->dt);
4626 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4627 ((double) sfc->f_ffree) / 1000,
4628 out + pos + 4, outsize + pos + 4, restart);
4630 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4631 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4632 out + pos + 5, outsize + pos + 5, restart);
4634 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4637 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4638 out + pos + 6, outsize + pos + 6, svg_p->dt);
4642 if (action & F_END) {
4644 for (i = 0; i < a->nr; i++) {
4646 /* Check if there is something to display */
4651 /* Conversion B -> MB and inodes/1000 */
4652 for (k = 0; k < 2; k++) {
4653 *(spmin + pos + k) /= (1024 * 1024);
4654 *(spmax + pos + k) /= (1024 * 1024);
4655 *(spmin + pos + 4 + k) /= 1000;
4656 *(spmax + pos + 4 + k) /= 1000;
4659 if (DISPLAY_MOUNT(a->opt_flags)) {
4660 item_name = *(out + pos + 8);
4663 item_name = *(out + pos + 7);
4666 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4667 spmin + pos, spmax + pos, out + pos, outsize + pos,
4671 /* Free remaining structures */
4672 free_graphs(out, outsize, spmin, spmax);
4677 ***************************************************************************
4678 * Display Fibre Channel HBA statistics in SVG.
4681 * @a Activity structure with statistics.
4682 * @curr Index in array for current sample statistics.
4683 * @action Action expected from current function.
4684 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4685 * flag indicating that a restart record has been previously
4686 * found (.@restart) and time used for the X axis origin
4688 * @itv Interval of time in jiffies (only with F_MAIN action).
4689 * @record_hdr Pointer on record header of current stats sample.
4690 ***************************************************************************
4692 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4693 unsigned long long itv, struct record_header *record_hdr)
4695 struct stats_fchost *sfcc, *sfcp;
4696 int group[] = {2, 2};
4697 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4698 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4699 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4700 "fch_rxw/s", "fch_txw/s"};
4701 int g_fields[] = {0, 1, 2, 3};
4702 static double *spmin, *spmax;
4704 static int *outsize;
4708 if (action & F_BEGIN) {
4710 * Allocate arrays (#0..3) that will contain the graphs data
4711 * and the min/max values.
4712 * Also allocate one additional array (#4) that will contain
4715 out = allocate_graph_lines(4 * a->nr, &outsize, &spmin, &spmax);
4718 if (action & F_MAIN) {
4719 /* For each FC HBA */
4720 for (i = 0; i < a->nr; i++) {
4722 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4723 if (!sfcc->fchost_name[0])
4724 /* We are at the end of the list */
4727 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
4730 item_name = *(out + pos + 4);
4731 if (!item_name[0]) {
4732 /* Save FC HBA name */
4733 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4734 item_name[CHUNKSIZE - 1] = '\0';
4737 /* Look for min/max values */
4738 save_extrema(0, 4, 0, (void *) sfcc, (void *) sfcp,
4739 itv, spmin + pos, spmax + pos, g_fields);
4742 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4743 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4744 out + pos, outsize + pos, svg_p->restart);
4746 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4747 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4748 out + pos + 1, outsize + pos + 1, svg_p->restart);
4750 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4751 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4752 out + pos + 2, outsize + pos + 2, svg_p->restart);
4754 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4755 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4756 out + pos + 3, outsize + pos + 3, svg_p->restart);
4760 if (action & F_END) {
4761 for (i = 0; i < a->nr; i++) {
4763 /* Check if there is something to display */
4768 item_name = *(out + pos + 4);
4769 draw_activity_graphs(a->g_nr, g_type,
4770 title, g_title, item_name, group,
4771 spmin + pos, spmax + pos, out + pos, outsize + pos,
4775 /* Free remaining structures */
4776 free_graphs(out, outsize, spmin, spmax);
4781 ***************************************************************************
4782 * Display softnet statistics in SVG.
4785 * @a Activity structure with statistics.
4786 * @curr Index in array for current sample statistics.
4787 * @action Action expected from current function.
4788 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4789 * flag indicating that a restart record has been previously
4790 * found (.@restart) and time used for the X axis origin
4792 * @itv Interval of time in jiffies (only with F_MAIN action).
4793 * @record_hdr Pointer on record header of current stats sample.
4794 ***************************************************************************
4796 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4797 unsigned long long itv, struct record_header *record_hdr)
4799 struct stats_softnet *ssnc, *ssnp;
4800 int group[] = {2, 3};
4801 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4802 char *title[] = {"Software-based network processing statistics (1)",
4803 "Software-based network processing statistics (2)"};
4804 char *g_title[] = {"total/s", "dropd/s",
4805 "squeezd/s", "rx_rps/s", "flw_lim/s"};
4806 int g_fields[] = {0, 1, 2, 3, 4};
4807 static double *spmin, *spmax;
4809 static int *outsize;
4813 if (action & F_BEGIN) {
4815 * Allocate arrays that will contain the graphs data
4816 * and the min/max values.
4818 out = allocate_graph_lines(5 * a->nr, &outsize, &spmin, &spmax);
4821 if (action & F_MAIN) {
4823 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4825 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
4826 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
4828 /* Should current CPU (including CPU "all") be displayed? */
4829 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4835 /* Check for min/max values */
4836 save_extrema(0, 0, 5, (void *) ssnc, (void *) ssnp,
4837 itv, spmin + pos, spmax + pos, g_fields);
4840 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4841 S_VALUE(ssnp->processed, ssnc->processed, itv),
4842 out + pos, outsize + pos, svg_p->restart);
4844 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4845 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
4846 out + pos + 1, outsize + pos + 1, svg_p->restart);
4848 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4849 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
4850 out + pos + 2, outsize + pos + 2, svg_p->restart);
4852 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4853 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
4854 out + pos + 3, outsize + pos + 3, svg_p->restart);
4856 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4857 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
4858 out + pos + 4, outsize + pos + 4, svg_p->restart);
4862 if (action & F_END) {
4863 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4865 /* Should current CPU (including CPU "all") be displayed? */
4866 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4873 /* This is CPU "all" */
4874 strcpy(item_name, "all");
4877 sprintf(item_name, "%d", i - 1);
4880 draw_activity_graphs(a->g_nr, g_type,
4881 title, g_title, item_name, group,
4882 spmin + pos, spmax + pos, out + pos, outsize + pos,
4886 /* Free remaining structures */
4887 free_graphs(out, outsize, spmin, spmax);