2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016-2017 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 * @types_nr Number of fields whose type is "long long", "long" and "int"
62 * composing the structure.
63 * @cs Pointer on current sample statistics structure.
64 * @ps Pointer on previous sample statistics structure (may be NULL).
65 * @itv Interval of time in jiffies.
66 * @spmin Array containing min values already found for this activity.
67 * @spmax Array containing max values already found for this activity.
68 * @g_fields Index in spmin/spmax arrays where extrema values for each
69 * activity metric will be saved. As a consequence spmin/spmax
70 * arrays may contain values in a different order than that of
71 * the fields in the statistics structure.
74 * @spmin Array containg the possible new min values for current activity.
75 * @spmax Array containg the possible new max values for current activity.
76 ***************************************************************************
78 void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
79 double *spmin, double *spmax, int g_fields[])
81 unsigned long long *lluc, *llup;
82 unsigned long *luc, *lup;
83 unsigned int *uc, *up;
87 /* Compare unsigned long long fields */
88 lluc = (unsigned long long *) cs;
89 llup = (unsigned long long *) ps;
90 for (i = 0; i < types_nr[0]; i++, m++) {
92 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
96 * If no pointer on previous sample has been given
97 * then the value is not a per-second one.
101 if (val < *(spmin + g_fields[m])) {
102 *(spmin + g_fields[m]) = val;
104 if (val > *(spmax + g_fields[m])) {
105 *(spmax + g_fields[m]) = val;
107 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
109 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
113 /* Compare unsigned long fields */
114 luc = (unsigned long *) lluc;
115 lup = (unsigned long *) llup;
116 for (i = 0; i < types_nr[1]; i++, m++) {
118 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
123 if (val < *(spmin + g_fields[m])) {
124 *(spmin + g_fields[m]) = val;
126 if (val > *(spmax + g_fields[m])) {
127 *(spmax + g_fields[m]) = val;
129 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
131 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
135 /* Compare unsigned int fields */
136 uc = (unsigned int *) luc;
137 up = (unsigned int *) lup;
138 for (i = 0; i < types_nr[2]; i++, m++) {
140 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
145 if (val < *(spmin + g_fields[m])) {
146 *(spmin + g_fields[m]) = val;
148 if (val > *(spmax + g_fields[m])) {
149 *(spmax + g_fields[m]) = val;
151 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
153 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
159 ***************************************************************************
160 * Find the min and max values of all the graphs that will be drawn in the
161 * same view. The graphs have their own min and max values in
162 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
165 * @pos Position in array for the first graph extrema value.
166 * @n Number of graphs to scan.
167 * @spmin Array containing min values for graphs.
168 * @spmax Array containing max values for graphs.
171 * @gmin Global min value found.
172 * @gmax Global max value found.
173 ***************************************************************************
175 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
176 double *gmin, double *gmax)
180 *gmin = *(spmin + pos);
181 *gmax = *(spmax + pos);
183 for (i = 1; i < n; i++) {
184 if (*(spmin + pos + i) < *gmin) {
185 *gmin = *(spmin + pos + i);
187 if (*(spmax + pos + i) > *gmax) {
188 *gmax = *(spmax + pos + i);
194 ***************************************************************************
195 * Allocate arrays used to save graphs data, min and max values.
196 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
197 * array is returned. This is equivalent to "char data[][n]" where each
198 * element is of indeterminate size and will contain the graph data (eg.
199 * << path d="M12,14 L13,16..." ... >>.
200 * The size of element data[i] is given by outsize[i].
201 * Also allocate an array to save min values (equivalent to "double spmin[n]")
202 * and an array for max values (equivalent to "double spmax[n]").
205 * @n Number of graphs to draw for current activity.
208 * @outsize Array that will contain the sizes of each element in array
209 * of chars. Equivalent to "int outsize[n]" with
210 * outsize[n] = sizeof(data[][n]).
211 * @spmin Array that will contain min values for current activity.
212 * @spmax Array that will contain max values for current activity.
215 * Pointer on array of arrays of chars that will contain the graphs data.
217 * NB: @min and @max arrays contain values in the same order as the fields
218 * in the statistics structure.
219 ***************************************************************************
221 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
228 * Allocate an array of pointers. Each of these pointers will
229 * be an array of chars.
231 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
235 /* Allocate array that will contain the size of each array of chars */
236 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
240 /* Allocate array that will contain the min value of each graph */
241 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
245 /* Allocate array that will contain the max value of each graph */
246 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
250 /* Allocate arrays of chars that will contain graphs data */
251 for (i = 0; i < n; i++) {
252 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
257 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
258 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
259 *(*spmin + i) = DBL_MAX; /* Init min and max values */
260 *(*spmax + i) = -DBL_MAX;
267 ***************************************************************************
268 * Save SVG code for current graph.
271 * @data SVG code to append to current graph definition.
272 * @out Pointer on array of chars for current graph definition.
273 * @outsize Size of array of chars for current graph definition.
276 * @out Pointer on array of chars for current graph definition that
277 * has been updated with the addition of current sample data.
278 * @outsize Array that containing the (possibly new) sizes of each
279 * element in array of chars.
280 ***************************************************************************
282 void save_svg_data(char *data, char **out, int *outsize)
288 /* Determine space left in array */
289 len = *outsize - strlen(out_p) - 1;
290 if (strlen(data) >= len) {
292 * If current array of chars doesn't have enough space left
293 * then reallocate it with CHUNKSIZE more bytes.
295 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
297 *outsize += CHUNKSIZE;
300 strncat(out_p, data, len);
304 ***************************************************************************
305 * Update line graph definition by appending current X,Y coordinates.
308 * @timetag Timestamp in seconds since the epoch for current sample
309 * stats. Will be used as X coordinate.
310 * @value Value of current sample metric. Will be used as Y coordinate.
311 * @out Pointer on array of chars for current graph definition.
312 * @outsize Size of array of chars for current graph definition.
313 * @restart Set to TRUE if a RESTART record has been read since the last
317 * @out Pointer on array of chars for current graph definition that
318 * has been updated with the addition of current sample data.
319 * @outsize Array that containing the (possibly new) sizes of each
320 * element in array of chars.
321 ***************************************************************************
323 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
328 /* Prepare additional graph definition data */
329 snprintf(data, 128, " %c%llu,%.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 long timetag, unsigned long value, char **out,
357 int *outsize, int restart)
361 /* Prepare additional graph definition data */
362 snprintf(data, 128, " %c%llu,%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 long timetag, double offset, double value, char **out,
391 int *outsize, unsigned long long dt)
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=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
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 long timetag, double *offset, double value, char **out,
434 int *outsize, unsigned long 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 long timetag, double p_value, double value, char **out,
477 int *outsize, int restart, unsigned long long dt,
478 double *spmin, double *spmax)
480 char data[128], data1[128], data2[128];
482 /* Save min and max values */
483 if (value < *spmin) {
486 if (value > *spmax) {
489 /* Prepare additional graph definition data */
491 snprintf(data1, 128, " M%llu,%.2f", timetag - dt, p_value);
494 if (p_value != value) {
495 snprintf(data2, 128, " L%llu,%.2f", timetag, value);
498 snprintf(data, 128, "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
499 p_value != value ? data2 : "");
502 save_svg_data(data, out, outsize);
506 ***************************************************************************
507 * Calculate 10 raised to the power of n.
510 * @n Power number to use.
513 * 10 raised to the power of n.
514 ***************************************************************************
516 unsigned int pwr10(int n)
521 for (i = 0; i < n; i++) {
529 ***************************************************************************
530 * Autoscale graphs of a given view.
533 * @asf_nr (Maximum) number of autoscale factors.
534 * @group Number of graphs in current view.
535 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
536 * @pos Position in array for the first graph in view.
537 * @gmax Global max value for all graphs in view.
538 * @spmax Array containing max values for graphs.
541 * @asfactor Autoscale factors (one for each graph).
542 ***************************************************************************
544 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
545 double gmax, double *spmax)
550 for (j = 0; j < asf_nr; j++) {
551 /* Init autoscale factors */
555 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
557 for (j = 0; (j < group) && (j < asf_nr); j++) {
558 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
561 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
562 if (strlen(val) > 0) {
563 asfactor[j] = pwr10(strlen(val) - 1);
570 ***************************************************************************
571 * Display background grid (horizontal lines) and corresponding graduations.
574 * @ypos Gap between two horizontal lines.
575 * @yfactor Scaling factor on Y axis.
576 * @lmax Max value for current view.
577 * @dp Number of decimal places for graduations.
578 ***************************************************************************
580 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
586 /* Display horizontal lines (except on X axis) */
588 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
589 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
590 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
594 * Display graduations.
595 * Use same rounded value for graduation numbers as for grid lines
596 * to make sure they are properly aligned.
598 sprintf(stmp, "%.2f", ypos * j);
599 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
600 "text-anchor: end\">%.*f.</text>\n",
601 (long) (atof(stmp) * yfactor), dp, ypos * j);
604 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
608 ***************************************************************************
609 * Display background grid (vertical lines) and corresponding graduations.
612 * @xpos Gap between two vertical lines.
613 * @xfactor Scaling factor on X axis.
614 * @v_gridnr Number of vertical lines to display.
615 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
616 ***************************************************************************
618 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
620 struct record_header stamp;
622 char cur_time[TIMESTAMP_LEN];
625 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
627 for (j = 0; (j <= v_gridnr) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
629 /* Display vertical lines */
630 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
631 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
632 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
633 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
634 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
636 * Display graduations.
637 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
638 * In this case, we should rather display the exact time instead of only the hour.
640 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
641 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
642 "text-anchor: start\">%2dH</text>\n",
643 (long) (xpos * j * xfactor) - 8, rectime.tm_hour);
646 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
647 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
648 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
650 stamp.ust_time += xpos;
653 if (!PRINT_LOCAL_TIME(flags)) {
654 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
655 "text-anchor: end\">UTC</text>\n");
660 ***************************************************************************
661 * Calculate the value on the Y axis between two horizontal lines that will
662 * make the graph background grid.
665 * @lmax Max value reached for this graph.
668 * @dp Number of decimal places for Y graduations.
671 * Value between two horizontal lines.
672 ***************************************************************************
674 double ygrid(double lmax, int *dp)
685 n = (long) (lmax / SVG_H_GRIDNR);
688 return (lmax / SVG_H_GRIDNR);
690 snprintf(val, 32, "%ld", n);
697 return ((double) (((long) (n / e)) * e));
701 ***************************************************************************
702 * Calculate the value on the X axis between two vertical lines that will
703 * make the graph background grid.
706 * @timestart First data timestamp (X coordinate of the first data point).
707 * @timeend Last data timestamp (X coordinate of the last data point).
708 * @v_gridnr Number of vertical lines to display. Its value is normally
709 * SVG_V_GRIDNR, except when option "oneday" is used, in which
710 * case it is set to 12.
713 * Value between two vertical lines.
714 ***************************************************************************
716 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
718 if ((timeend - timestart) <= v_gridnr)
721 return ((timeend - timestart) / v_gridnr);
725 ***************************************************************************
726 * Free global graphs structures.
729 * @out Pointer on array of chars for each graph definition.
730 * @outsize Size of array of chars for each graph definition.
731 * @spmin Array containing min values for graphs.
732 * @spmax Array containing max values for graphs.
733 ***************************************************************************
735 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
752 ***************************************************************************
753 * Skip current view where all graphs have only zero values. This function
754 * is called when option "skipempty" has been used, or when "No data" have
755 * been found for current view.
758 * @out Pointer on array of chars for each graph definition.
759 * @pos Position of current view in the array of graphs definitions.
760 * @group Number of graphs in current view.
763 * @pos Position of next view in the array of graphs definitions.
764 ***************************************************************************
766 void skip_current_view(char **out, int *pos, int group)
771 for (j = 0; j < group; j++) {
772 out_p = *(out + *pos + j);
774 /* Even if not displayed, current graph data have to be freed */
782 ***************************************************************************
783 * Display all graphs for current activity.
786 * @g_nr Number of views to display.
787 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
788 * @title Titles for each set of graphs.
789 * @g_title Titles for each graph.
790 * @item_name Item (network interface, etc.) name.
791 * @group Indicate how graphs are grouped together to make sets.
792 * @spmin Array containing min values for graphs.
793 * @spmax Array containing max values for graphs.
794 * @out Pointer on array of chars for each graph definition.
795 * @outsize Size of array of chars for each graph definition.
796 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
797 * time for the first sample of stats (.@ust_time_first), and
798 * times used as start and end values on the X axis
799 * (.@ust_time_ref and .@ust_time_end).
800 * @record_hdr Pointer on record header of current stats sample.
801 ***************************************************************************
803 void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
804 int group[], double *spmin, double *spmax, char **out, int *outsize,
805 struct svg_parm *svg_p, struct record_header *record_hdr)
808 int i, j, dp, pos = 0, views_nr = 0;
809 int v_gridnr, xv, yv;
810 unsigned int asfactor[16];
812 double lmax, xfactor, yfactor, ypos, gmin, gmax;
813 char val[32], cur_date[TIMESTAMP_LEN];
815 /* Translate to proper position for current activity */
816 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
818 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
820 /* For each view which is part of current activity */
821 for (i = 0; i < g_nr; i++) {
823 /* Get global min and max value for current view */
824 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
826 /* Don't display empty views if requested */
827 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
828 skip_current_view(out, &pos, group[i]);
831 /* Increment number of views actually displayed */
834 /* Compute top left position of view */
835 if (PACK_VIEWS(flags)) {
836 xv = (views_nr - 1) * SVG_T_XSIZE;
841 yv = (views_nr - 1) * SVG_T_YSIZE;
844 /* Graph background */
845 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
846 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
849 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
850 xv, 20 + yv, title[i]);
852 printf(" [%s]", item_name);
855 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
856 "(Min, Max values)</tspan>\n</text>\n",
857 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
860 * At least two samples are needed.
861 * And a min and max value should have been found.
863 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
864 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
866 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
867 xv, yv + SVG_M_YSIZE);
868 skip_current_view(out, &pos, group[i]);
873 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
874 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
875 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
876 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
878 /* Autoscaling graphs if needed */
879 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
882 for (j = 0; j < group[i]; j++) {
883 /* Set dp to TRUE (1) if current metric is based on integer values */
884 dp = (g_title[pos + j][0] == '~');
885 snprintf(val, 32, "x%u ", asfactor[j]);
886 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
887 "%s %s(%.*f, %.*f)</text>\n",
888 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
889 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
890 asfactor[j] == 1 ? "" : val,
891 !dp * 2, *(spmin + pos + j) * asfactor[j],
892 !dp * 2, *(spmax + pos + j) * asfactor[j]);
895 if (DISPLAY_INFO(flags)) {
896 /* Display additional info (hostname, date) */
897 printf("<text x=\"%d\" y=\"%d\" "
898 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
900 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
901 svg_p->file_hdr->sa_nodename);
903 /* Get report date */
904 set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
905 cur_date, sizeof(cur_date));
906 printf("<tspan x=\"%d\" y=\"%d\" "
907 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
908 "%s</tspan>\n</text>\n",
909 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
913 /* Translate to proper position for current graph within current activity */
914 printf("<g transform=\"translate(%d,%d)\">\n",
915 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
918 if (g_type[i] == SVG_LINE_GRAPH) {
919 /* For line graphs */
921 /* If all values are zero then set current max value to 1 */
927 /* Max value cannot be too small, else Y graduations will be meaningless */
928 if (lmax < SVG_H_GRIDNR * 0.01) {
929 lmax = SVG_H_GRIDNR * 0.01;
931 ypos = ygrid(lmax, &dp);
934 /* For bar graphs (used for %values) */
935 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
936 dp = 0; /* No decimals */
938 /* Max should be always 100% except for percentage values greater than 100% */
946 yfactor = (double) -SVG_G_YSIZE / lmax;
948 /* Display horizontal lines and graduations */
949 display_hgrid(ypos, yfactor, lmax, dp);
951 /* Set number of vertical lines to 12 when option "oneday" is used */
952 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
954 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
955 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
957 /* Display vertical lines and graduations */
958 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
960 /* Draw current graphs set */
961 for (j = 0; j < group[i]; j++) {
962 out_p = *(out + pos + j);
963 if (g_type[i] == SVG_LINE_GRAPH) {
965 printf("<path id=\"g%dp%d\" d=\"%s\" "
966 "style=\"vector-effect: non-scaling-stroke; "
967 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
968 "transform=\"scale(%f,%f)\"/>\n",
969 svg_p->graph_no, pos + j, out_p,
970 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
972 yfactor * asfactor[j]);
974 else if (*out_p) { /* Ignore flat bars */
976 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
977 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
978 printf("%s\n", out_p);
988 /* For next row of views */
989 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
993 ***************************************************************************
994 * Display CPU statistics in SVG.
997 * @a Activity structure with statistics.
998 * @curr Index in array for current sample statistics.
999 * @action Action expected from current function.
1000 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1001 * flag indicating that a restart record has been previously
1002 * found (.@restart), and time used for the X axis origin
1004 * @itv Interval of time in jiffies (only with F_MAIN action).
1006 * @record_hdr Pointer on record header of current stats sample.
1007 ***************************************************************************
1009 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1010 unsigned long long itv, struct record_header *record_hdr)
1012 struct stats_cpu *scc, *scp;
1013 unsigned long long tot_jiffies[3];
1014 unsigned long long deltot_jiffies;
1017 int g_type[] = {SVG_BAR_GRAPH};
1018 char *title[] = {"CPU load"};
1019 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1020 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1021 static double *spmin, *spmax;
1023 static int *outsize;
1026 int i, j, k, pos, cpu_offline;
1028 if (action & F_BEGIN) {
1030 * Allocate arrays that will contain the graphs data
1031 * and the min/max values.
1033 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
1036 if (action & F_MAIN) {
1038 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1040 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1041 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1043 /* Should current CPU (including CPU "all") be displayed? */
1044 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1049 * Yes: Compute the total number of jiffies spent by current processor.
1050 * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
1051 * already include them.
1053 tot_jiffies[curr] = scc->cpu_user + scc->cpu_nice +
1054 scc->cpu_sys + scc->cpu_idle +
1055 scc->cpu_iowait + scc->cpu_hardirq +
1056 scc->cpu_steal + scc->cpu_softirq;
1057 tot_jiffies[!curr] = scp->cpu_user + scp->cpu_nice +
1058 scp->cpu_sys + scp->cpu_idle +
1059 scp->cpu_iowait + scp->cpu_hardirq +
1060 scp->cpu_steal + scp->cpu_softirq;
1062 /* Total number of jiffies spent on the interval */
1063 deltot_jiffies = get_interval(tot_jiffies[!curr], tot_jiffies[curr]);
1068 if (i) { /* Don't test CPU "all" here */
1070 * If the CPU is offline then it is omited from /proc/stat:
1071 * All the fields couldn't have been read and the sum of them is zero.
1072 * (Remember that guest/guest_nice times are already included in
1075 if (tot_jiffies[curr] == 0) {
1077 * Set current struct fields (which have been set to zero)
1078 * to values from previous iteration. Hence their values won't
1079 * jump from zero when the CPU comes back online.
1088 * Recalculate interval for current proc.
1089 * If result is 0 then current CPU is a tickless one.
1091 deltot_jiffies = get_per_cpu_interval(scc, scp);
1092 cpu_offline = FALSE;
1095 if (!deltot_jiffies) { /* Current CPU is offline or tickless */
1097 val = (cpu_offline ? 0.0 /* Offline CPU: %idle = 0% */
1098 : 100.0); /* Tickless CPU: %idle = 100% */
1100 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1103 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1107 /* Check min/max values for %user, etc. */
1108 for (k = 0; k < j; k++) {
1109 if (0.0 < *(spmin + pos + k)) {
1110 *(spmin + pos + k) = 0.0;
1112 if (0.0 > *(spmax + pos + k)) {
1113 *(spmax + pos + k) = 0.0;
1118 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1120 out + pos + j, outsize + pos + j, svg_p->dt,
1121 spmin + pos + j, spmax + pos + j);
1126 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1128 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1129 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1130 out + pos, outsize + pos, svg_p->dt,
1131 spmin + pos, spmax + pos);
1135 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1137 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1139 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1140 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1141 out + pos, outsize + pos, svg_p->dt,
1142 spmin + pos, spmax + pos);
1145 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1147 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1148 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1149 out + pos + 1, outsize + pos + 1, svg_p->dt,
1150 spmin + pos + 1, spmax + pos + 1);
1154 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1156 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1158 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1159 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1160 out + pos + 1, outsize + pos + 1, svg_p->dt,
1161 spmin + pos + 1, spmax + pos + 1);
1164 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1166 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1168 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1169 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1171 out + pos + 2, outsize + pos + 2, svg_p->dt,
1172 spmin + pos + 2, spmax + pos + 2);
1176 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1177 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1178 out + pos + 2, outsize + pos + 2, svg_p->dt,
1179 spmin + pos + 2, spmax + pos + 2);
1183 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1184 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1185 out + pos + 3, outsize + pos + 3, svg_p->dt,
1186 spmin + pos + 3, spmax + pos + 3);
1188 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1189 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1190 out + pos + 4, outsize + pos + 4, svg_p->dt,
1191 spmin + pos + 4, spmax + pos + 4);
1193 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1195 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1196 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1197 out + pos + 5, outsize + pos + 5, svg_p->dt,
1198 spmin + pos + 5, spmax + pos + 5);
1200 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1201 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1202 out + pos + 6, outsize + pos + 6, svg_p->dt,
1203 spmin + pos + 6, spmax + pos + 6);
1205 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1206 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1207 out + pos + 7, outsize + pos + 7, svg_p->dt,
1208 spmin + pos + 7, spmax + pos + 7);
1210 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1211 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1212 out + pos + 8, outsize + pos + 8, svg_p->dt,
1213 spmin + pos + 8, spmax + pos + 8);
1222 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1224 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1225 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1226 out + pos + j, outsize + pos + j, svg_p->dt,
1227 spmin + pos + j, spmax + pos + j);
1231 if (action & F_END) {
1232 if (DISPLAY_IDLE(flags)) {
1233 /* Include additional %idle field */
1238 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1240 /* Should current CPU (including CPU "all") be displayed? */
1241 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1247 /* This is CPU "all" */
1248 strcpy(item_name, "all");
1251 sprintf(item_name, "%d", i - 1);
1254 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1255 draw_activity_graphs(a->g_nr, g_type,
1256 title, g_title1, item_name, group1,
1257 spmin + pos, spmax + pos, out + pos, outsize + pos,
1261 draw_activity_graphs(a->g_nr, g_type,
1262 title, g_title2, item_name, group2,
1263 spmin + pos, spmax + pos, out + pos, outsize + pos,
1268 /* Free remaining structures */
1269 free_graphs(out, outsize, spmin, spmax);
1274 ***************************************************************************
1275 * Display task creation and context switch statistics in SVG.
1278 * @a Activity structure with statistics.
1279 * @curr Index in array for current sample statistics.
1280 * @action Action expected from current function.
1281 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1282 * flag indicating that a restart record has been previously
1283 * found (.@restart) and time used for the X axis origin
1285 * @itv Interval of time in jiffies (only with F_MAIN action).
1286 * @record_hdr Pointer on record header of current stats sample.
1287 ***************************************************************************
1289 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1290 unsigned long long itv, struct record_header *record_hdr)
1293 *spc = (struct stats_pcsw *) a->buf[curr],
1294 *spp = (struct stats_pcsw *) a->buf[!curr];
1295 int group[] = {1, 1};
1296 int g_fields[] = {1, 0};
1297 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1298 char *title[] = {"Task creation", "Switching activity"};
1299 char *g_title[] = {"proc/s",
1301 static double *spmin, *spmax;
1303 static int *outsize;
1305 if (action & F_BEGIN) {
1307 * Allocate arrays that will contain the graphs data
1308 * and the min/max values.
1310 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1313 if (action & F_MAIN) {
1314 /* Check for min/max values */
1315 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1316 itv, spmin, spmax, g_fields);
1318 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1319 S_VALUE(spp->processes, spc->processes, itv),
1320 out, outsize, svg_p->restart);
1322 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1323 S_VALUE(spp->context_switch, spc->context_switch, itv),
1324 out + 1, outsize + 1, svg_p->restart);
1327 if (action & F_END) {
1328 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1329 spmin, spmax, out, outsize, svg_p, record_hdr);
1331 /* Free remaining structures */
1332 free_graphs(out, outsize, spmin, spmax);
1337 ***************************************************************************
1338 * Display swap statistics in SVG.
1341 * @a Activity structure with statistics.
1342 * @curr Index in array for current sample statistics.
1343 * @action Action expected from current function.
1344 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1345 * flag indicating that a restart record has been previously
1346 * found (.@restart) and time used for the X axis origin
1348 * @itv Interval of time in jiffies (only with F_MAIN action).
1349 * @record_hdr Pointer on record header of current stats sample.
1350 ***************************************************************************
1352 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1353 unsigned long long itv, struct record_header *record_hdr)
1356 *ssc = (struct stats_swap *) a->buf[curr],
1357 *ssp = (struct stats_swap *) a->buf[!curr];
1359 int g_type[] = {SVG_LINE_GRAPH};
1360 char *title[] = {"Swap activity"};
1361 char *g_title[] = {"pswpin/s", "pswpout/s" };
1362 int g_fields[] = {0, 1};
1363 static double *spmin, *spmax;
1365 static int *outsize;
1367 if (action & F_BEGIN) {
1369 * Allocate arrays that will contain the graphs data
1370 * and the min/max values.
1372 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1375 if (action & F_MAIN) {
1376 /* Check for min/max values */
1377 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1378 itv, spmin, spmax, g_fields);
1380 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1381 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1382 out, outsize, svg_p->restart);
1384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1385 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1386 out + 1, outsize + 1, svg_p->restart);
1389 if (action & F_END) {
1390 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1391 spmin, spmax, out, outsize, svg_p, record_hdr);
1393 /* Free remaining structures */
1394 free_graphs(out, outsize, spmin, spmax);
1399 ***************************************************************************
1400 * Display paging statistics in SVG.
1403 * @a Activity structure with statistics.
1404 * @curr Index in array for current sample statistics.
1405 * @action Action expected from current function.
1406 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1407 * flag indicating that a restart record has been previously
1408 * found (.@restart) and time used for the X axis origin
1410 * @itv Interval of time in jiffies (only with F_MAIN action).
1411 * @record_hdr Pointer on record header of current stats sample.
1412 ***************************************************************************
1414 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1415 unsigned long long itv, struct record_header *record_hdr)
1418 *spc = (struct stats_paging *) a->buf[curr],
1419 *spp = (struct stats_paging *) a->buf[!curr];
1420 int group[] = {2, 2, 4};
1421 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1422 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1423 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1424 "fault/s", "majflt/s",
1425 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1426 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1427 static double *spmin, *spmax;
1429 static int *outsize;
1431 if (action & F_BEGIN) {
1433 * Allocate arrays that will contain the graphs data
1434 * and the min/max values.
1436 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1439 if (action & F_MAIN) {
1440 /* Check for min/max values */
1441 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1442 itv, spmin, spmax, g_fields);
1444 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1445 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1446 out, outsize, svg_p->restart);
1448 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1449 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1450 out + 1, outsize + 1, svg_p->restart);
1452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1453 S_VALUE(spp->pgfault, spc->pgfault, itv),
1454 out + 2, outsize + 2, svg_p->restart);
1456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1457 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1458 out + 3, outsize + 3, svg_p->restart);
1460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1461 S_VALUE(spp->pgfree, spc->pgfree, itv),
1462 out + 4, outsize + 4, svg_p->restart);
1464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1465 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1466 out + 5, outsize + 5, svg_p->restart);
1468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1469 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1470 out + 6, outsize + 6, svg_p->restart);
1472 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1473 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1474 out + 7, outsize + 7, svg_p->restart);
1477 if (action & F_END) {
1478 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1479 spmin, spmax, out, outsize, svg_p, record_hdr);
1481 /* Free remaining structures */
1482 free_graphs(out, outsize, spmin, spmax);
1487 ***************************************************************************
1488 * Display I/O and transfer rate statistics in SVG.
1491 * @a Activity structure with statistics.
1492 * @curr Index in array for current sample statistics.
1493 * @action Action expected from current function.
1494 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1495 * flag indicating that a restart record has been previously
1496 * found (.@restart) and time used for the X axis origin
1498 * @itv Interval of time in jiffies (only with F_MAIN action).
1499 * @record_hdr Pointer on record header of current stats sample.
1500 ***************************************************************************
1502 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1503 unsigned long long itv, struct record_header *record_hdr)
1506 *sic = (struct stats_io *) a->buf[curr],
1507 *sip = (struct stats_io *) a->buf[!curr];
1508 int group[] = {3, 2};
1509 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1510 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1511 char *g_title[] = {"tps", "rtps", "wtps",
1512 "bread/s", "bwrtn/s"};
1513 int g_fields[] = {0, 1, 2, 3, 4};
1514 static double *spmin, *spmax;
1516 static int *outsize;
1518 if (action & F_BEGIN) {
1520 * Allocate arrays that will contain the graphs data
1521 * and the min/max values.
1523 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1526 if (action & F_MAIN) {
1527 /* Check for min/max values */
1528 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1529 itv, spmin, spmax, g_fields);
1532 * If we get negative values, this is probably because
1533 * one or more devices/filesystems have been unmounted.
1534 * We display 0.0 in this case though we should rather tell
1535 * the user that the value cannot be calculated here.
1538 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1539 sic->dk_drive < sip->dk_drive ? 0.0 :
1540 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1541 out, outsize, svg_p->restart);
1543 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1544 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1545 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1546 out + 1, outsize + 1, svg_p->restart);
1548 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1549 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1550 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1551 out + 2, outsize + 2, svg_p->restart);
1553 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1554 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1555 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1556 out + 3, outsize + 3, svg_p->restart);
1558 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1559 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1560 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1561 out + 4, outsize + 4, svg_p->restart);
1564 if (action & F_END) {
1565 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1566 spmin, spmax, out, outsize, svg_p, record_hdr);
1568 /* Free remaining structures */
1569 free_graphs(out, outsize, spmin, spmax);
1574 ***************************************************************************
1575 * Display memory statistics in SVG.
1578 * @a Activity structure with statistics.
1579 * @curr Index in array for current sample statistics.
1580 * @action Action expected from current function.
1581 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1582 * flag indicating that a restart record has been previously
1583 * found (.@restart) and time used for the X axis origin
1585 * @itv Interval of time in jiffies (only with F_MAIN action).
1586 * @record_hdr Pointer on record header of current stats sample.
1587 ***************************************************************************
1589 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1590 unsigned long long itv, struct record_header *record_hdr)
1593 *smc = (struct stats_memory *) a->buf[curr];
1594 int group1[] = {3, 1, 3, 1, 3, 5};
1595 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1596 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1597 int group2[] = {3, 1, 1};
1598 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1599 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1600 "Memory utilization (3)", "Memory utilization (4)",
1601 "Memory utilization (5)", "Memory utilization (6)"};
1602 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1603 "Swap utilization (3)"};
1604 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1605 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1606 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1608 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1610 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1611 static double *spmin, *spmax;
1613 static int *outsize;
1617 if (action & F_BEGIN) {
1619 * Allocate arrays that will contain the graphs data
1620 * and the min/max values.
1622 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1625 if (action & F_MAIN) {
1626 /* Check for min/max values */
1627 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1628 itv, spmin, spmax, g_fields);
1629 /* Compute %memused min/max values */
1630 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1631 if (tval > *(spmax + 3)) {
1632 *(spmax + 3) = tval;
1634 if (tval < *(spmin + 3)) {
1635 *(spmin + 3) = tval;
1637 /* Compute %commit min/max values */
1638 tval = (smc->tlmkb + smc->tlskb) ?
1639 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1640 if (tval > *(spmax + 7)) {
1641 *(spmax + 7) = tval;
1643 if (tval < *(spmin + 7)) {
1644 *(spmin + 7) = tval;
1646 /* Compute %swpused min/max values */
1648 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1649 if (tval > *(spmax + 19)) {
1650 *(spmax + 19) = tval;
1652 if (tval < *(spmin + 19)) {
1653 *(spmin + 19) = tval;
1655 /* Compute %swpcad min/max values */
1656 tval = (smc->tlskb - smc->frskb) ?
1657 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1658 if (tval > *(spmax + 20)) {
1659 *(spmax + 20) = tval;
1661 if (tval < *(spmin + 20)) {
1662 *(spmin + 20) = tval;
1664 /* Compute memused min/max values in MB */
1665 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1666 if (tval > *(spmax + 2)) {
1667 *(spmax + 2) = tval;
1669 if (tval < *(spmin + 2)) {
1670 *(spmin + 2) = tval;
1672 /* Compute swpused min/max values in MB */
1673 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1674 if (tval > *(spmax + 17)) {
1675 *(spmax + 17) = tval;
1677 if (tval < *(spmin + 17)) {
1678 *(spmin + 17) = tval;
1682 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1683 ((double) smc->frmkb) / 1024,
1684 out, outsize, svg_p->restart);
1686 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1687 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1688 out + 2, outsize + 2, svg_p->restart);
1690 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1691 ((double) smc->availablekb) / 1024,
1692 out + 1, outsize + 1, svg_p->restart);
1694 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1695 ((double) smc->bufkb) / 1024,
1696 out + 4, outsize + 4, svg_p->restart);
1698 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1699 ((double) smc->camkb) / 1024,
1700 out + 5, outsize + 5, svg_p->restart);
1702 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1703 ((double) smc->frskb) / 1024,
1704 out + 16, outsize + 16, svg_p->restart);
1706 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1707 ((double) (smc->tlskb - smc->frskb)) / 1024,
1708 out + 17, outsize + 17, svg_p->restart);
1710 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1711 ((double) smc->caskb) / 1024,
1712 out + 18, outsize + 18, svg_p->restart);
1714 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1715 ((double) smc->comkb) / 1024,
1716 out + 6, outsize + 6, svg_p->restart);
1718 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1719 ((double) smc->activekb) / 1024,
1720 out + 8, outsize + 8, svg_p->restart);
1722 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1723 ((double) smc->inactkb) / 1024,
1724 out + 9, outsize + 9, svg_p->restart);
1726 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1727 ((double) smc->dirtykb) / 1024,
1728 out + 10, outsize + 10, svg_p->restart);
1730 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1731 ((double) smc->anonpgkb) / 1024,
1732 out + 11, outsize + 11, svg_p->restart);
1734 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1735 ((double) smc->slabkb) / 1024,
1736 out + 12, outsize + 12, svg_p->restart);
1738 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1739 ((double) smc->kstackkb) / 1024,
1740 out + 13, outsize + 13, svg_p->restart);
1742 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1743 ((double) smc->pgtblkb) / 1024,
1744 out + 14, outsize + 14, svg_p->restart);
1746 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1747 ((double) smc->vmusedkb) / 1024,
1748 out + 15, outsize + 15, svg_p->restart);
1750 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1753 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1754 out + 3, outsize + 3, svg_p->dt);
1756 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1758 (smc->tlmkb + smc->tlskb) ?
1759 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1760 out + 7, outsize + 7, svg_p->dt);
1762 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1765 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1766 out + 19, outsize + 19, svg_p->dt);
1768 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1770 (smc->tlskb - smc->frskb) ?
1771 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1772 out + 20, outsize + 20, svg_p->dt);
1775 if (action & F_END) {
1777 /* Conversion kB -> MB */
1778 for (i = 0; i < 17; i++) {
1779 *(spmin + g_fields[i]) /= 1024;
1780 *(spmax + g_fields[i]) /= 1024;
1783 if (DISPLAY_MEMORY(a->opt_flags)) {
1784 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1785 g_type1, title1, g_title1, NULL, group1,
1786 spmin, spmax, out, outsize, svg_p, record_hdr);
1789 if (DISPLAY_SWAP(a->opt_flags)) {
1790 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1791 spmin + 16, spmax + 16, out + 16, outsize + 16,
1795 /* Free remaining structures */
1796 free_graphs(out, outsize, spmin, spmax);
1801 ***************************************************************************
1802 * Display kernel tables statistics in SVG.
1805 * @a Activity structure with statistics.
1806 * @curr Index in array for current sample statistics.
1807 * @action Action expected from current function.
1808 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1809 * flag indicating that a restart record has been previously
1810 * found (.@restart) and time used for the X axis origin
1812 * @itv Interval of time in jiffies (only with F_MAIN action).
1813 * @record_hdr Pointer on record header of current stats sample.
1814 ***************************************************************************
1816 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1817 unsigned long long itv, struct record_header *record_hdr)
1819 struct stats_ktables
1820 *skc = (struct stats_ktables *) a->buf[curr];
1821 int group[] = {3, 1};
1822 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1823 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1824 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1826 int g_fields[] = {1, 2, 0, 3};
1827 static double *spmin, *spmax;
1829 static int *outsize;
1831 if (action & F_BEGIN) {
1833 * Allocate arrays that will contain the graphs data
1834 * and the min/max values.
1836 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1839 if (action & F_MAIN) {
1840 /* Check for min/max values */
1841 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1842 itv, spmin, spmax, g_fields);
1844 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1845 (unsigned long) skc->dentry_stat,
1846 out, outsize, svg_p->restart);
1848 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1849 (unsigned long) skc->file_used,
1850 out + 1, outsize + 1, svg_p->restart);
1852 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1853 (unsigned long) skc->inode_used,
1854 out + 2, outsize + 2, svg_p->restart);
1856 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1857 (unsigned long) skc->pty_nr,
1858 out + 3, outsize + 3, svg_p->restart);
1861 if (action & F_END) {
1862 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1863 spmin, spmax, out, outsize, svg_p, record_hdr);
1865 /* Free remaining structures */
1866 free_graphs(out, outsize, spmin, spmax);
1871 ***************************************************************************
1872 * Display queue and load statistics in SVG.
1875 * @a Activity structure with statistics.
1876 * @curr Index in array for current sample statistics.
1877 * @action Action expected from current function.
1878 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1879 * flag indicating that a restart record has been previously
1880 * found (.@restart) and time used for the X axis origin
1882 * @itv Interval of time in jiffies (only with F_MAIN action).
1883 * @record_hdr Pointer on record header of current stats sample.
1884 ***************************************************************************
1886 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1887 unsigned long long itv, struct record_header *record_hdr)
1890 *sqc = (struct stats_queue *) a->buf[curr];
1891 int group[] = {2, 1, 3};
1892 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1893 char *title[] = {"Queue length", "Task list", "Load average"};
1894 char *g_title[] = {"~runq-sz", "~blocked",
1896 "ldavg-1", "ldavg-5", "ldavg-15"};
1897 int g_fields[] = {0, 1, 3, 4, 5, 2};
1898 static double *spmin, *spmax;
1900 static int *outsize;
1902 if (action & F_BEGIN) {
1904 * Allocate arrays that will contain the graphs data
1905 * and the min/max values.
1907 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1910 if (action & F_MAIN) {
1911 /* Check for min/max values */
1912 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1913 itv, spmin, spmax, g_fields);
1915 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1916 (unsigned long) sqc->nr_running,
1917 out, outsize, svg_p->restart);
1919 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1920 (unsigned long) sqc->procs_blocked,
1921 out + 1, outsize + 1, svg_p->restart);
1923 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1924 (unsigned long) sqc->nr_threads,
1925 out + 2, outsize + 2, svg_p->restart);
1927 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1928 (double) sqc->load_avg_1 / 100,
1929 out + 3, outsize + 3, svg_p->restart);
1931 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1932 (double) sqc->load_avg_5 / 100,
1933 out + 4, outsize + 4, svg_p->restart);
1935 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1936 (double) sqc->load_avg_15 / 100,
1937 out + 5, outsize + 5, svg_p->restart);
1940 if (action & F_END) {
1941 /* Fix min/max values for load average */
1942 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1943 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1944 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1946 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1947 spmin, spmax, out, outsize, svg_p, record_hdr);
1949 /* Free remaining structures */
1950 free_graphs(out, outsize, spmin, spmax);
1955 ***************************************************************************
1956 * Display disk statistics in SVG.
1959 * @a Activity structure with statistics.
1960 * @curr Index in array for current sample statistics.
1961 * @action Action expected from current function.
1962 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1963 * flag indicating that a restart record has been previously
1964 * found (.@restart) and time used for the X axis origin
1966 * @itv Interval of time in jiffies (only with F_MAIN action).
1967 * @record_hdr Pointer on record header of current stats sample.
1968 ***************************************************************************
1970 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1971 unsigned long long itv, struct record_header *record_hdr)
1973 struct stats_disk *sdc, *sdp, sdpzero;
1974 struct ext_disk_stats xds;
1975 int group[] = {1, 2, 2, 2, 1};
1976 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
1977 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
1978 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
1979 "Disk statistics (3)", "Disk statistics (4)",
1980 "Disk statistics (5)"};
1981 char *g_title[] = {"tps",
1983 "areq-sz", "aqu-sz",
1986 int g_fields[] = {0, 1, 2};
1987 unsigned int local_types_nr[] = {1, 0, 0};
1988 static double *spmin, *spmax;
1990 static int *outsize;
1991 char *item_name, *persist_dev_name;
1992 double rkB, wkB, aqusz;
1993 int i, j, k, pos, restart, *unregistered;
1995 if (action & F_BEGIN) {
1997 * Allocate arrays (#0..7) that will contain the graphs data
1998 * and the min/max values.
1999 * Also allocate one additional array (#8) for each disk device:
2000 * spmax + 8 will contain the device major number,
2001 * spmin + 8 will contain the device minor number,
2002 * outsize + 8 will contain a positive value (TRUE) if the device
2003 * has either still not been registered, or has been unregistered.
2005 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2008 if (action & F_MAIN) {
2009 memset(&sdpzero, 0, STATS_DISK_SIZE);
2010 restart = svg_p->restart;
2012 * Mark previously registered devices as now
2013 * possibly unregistered for all graphs.
2015 for (k = 0; k < a->nr; k++) {
2016 unregistered = outsize + k * 9 + 8;
2017 if (*unregistered == FALSE) {
2018 *unregistered = MAYBE;
2022 /* For each device structure */
2023 for (i = 0; i < a->nr; i++) {
2024 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2025 if (!(sdc->major + sdc->minor))
2026 /* Empty structure: Ignore it */
2029 /* Look for corresponding graph */
2030 for (k = 0; k < a->nr; k++) {
2031 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2032 (sdc->minor == *(spmin + k * 9 + 8)))
2037 /* Graph not found: Look for first free entry */
2038 for (k = 0; k < a->nr; k++) {
2039 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2043 /* No free graph entry: Graph for this item won't be drawn */
2047 unregistered = outsize + pos + 8;
2049 j = check_disk_reg(a, curr, !curr, i);
2051 /* This is a newly registered interface. Previous stats are zero */
2055 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2059 * If current device was marked as previously unregistered,
2060 * then set restart variable to TRUE so that the graph will be
2061 * discontinuous, and mark it as now registered.
2063 if (*unregistered == TRUE) {
2066 *unregistered = FALSE;
2068 if (*(spmax + pos + 8) == -DBL_MAX) {
2069 /* Save device major and minor numbers (if not already done) */
2070 *(spmax + pos + 8) = sdc->major;
2071 *(spmin + pos + 8) = sdc->minor;
2074 /* Check for min/max values */
2075 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2076 itv, spmin + pos, spmax + pos, g_fields);
2078 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2079 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2080 if (rkB < *(spmin + pos + 1)) {
2081 *(spmin + pos + 1) = rkB;
2083 if (rkB > *(spmax + pos + 1)) {
2084 *(spmax + pos + 1) = rkB;
2086 if (wkB < *(spmin + pos + 2)) {
2087 *(spmin + pos + 2) = wkB;
2089 if (wkB > *(spmax + pos + 2)) {
2090 *(spmax + pos + 2) = wkB;
2093 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2094 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2095 *(spmin + pos + 3) = xds.arqsz / 2;
2097 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2098 *(spmax + pos + 3) = xds.arqsz / 2;
2100 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2101 if (aqusz < *(spmin + pos + 4)) {
2102 *(spmin + pos + 4) = aqusz;
2104 if (aqusz > *(spmax + pos + 4)) {
2105 *(spmax + pos + 4) = aqusz;
2107 if (xds.await < *(spmin + pos + 5)) {
2108 *(spmin + pos + 5) = xds.await;
2110 if (xds.await > *(spmax + pos + 5)) {
2111 *(spmax + pos + 5) = xds.await;
2113 if (xds.svctm < *(spmin + pos + 6)) {
2114 *(spmin + pos + 6) = xds.svctm;
2116 if (xds.svctm > *(spmax + pos + 6)) {
2117 *(spmax + pos + 6) = xds.svctm;
2119 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2120 *(spmin + pos + 7) = xds.util / 10.0;
2122 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2123 *(spmax + pos + 7) = xds.util / 10.0;
2127 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2128 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2129 out + pos, outsize + pos, restart);
2131 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2132 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2133 out + pos + 1, outsize + pos + 1, restart);
2135 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2136 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2137 out + pos + 2, outsize + pos + 2, restart);
2139 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2141 out + pos + 3, outsize + pos + 3, restart);
2143 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2145 out + pos + 4, outsize + pos + 4, restart);
2147 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2149 out + pos + 5, outsize + pos + 5, restart);
2151 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2153 out + pos + 6, outsize + pos + 6, restart);
2155 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2156 0.0, xds.util / 10.0,
2157 out + pos + 7, outsize + pos + 7, svg_p->dt);
2160 /* Mark devices not seen here as now unregistered */
2161 for (k = 0; k < a->nr; k++) {
2162 unregistered = outsize + k * 9 + 8;
2163 if (*unregistered != FALSE) {
2164 *unregistered = TRUE;
2169 if (action & F_END) {
2170 for (i = 0; i < a->nr; i++) {
2171 /* Check if there is something to display */
2177 persist_dev_name = NULL;
2179 if (DISPLAY_PERSIST_NAME_S(flags)) {
2180 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2184 if (persist_dev_name) {
2185 item_name = persist_dev_name;
2188 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2189 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2193 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2194 USE_PRETTY_OPTION(flags));
2198 draw_activity_graphs(a->g_nr, g_type,
2199 title, g_title, item_name, group,
2200 spmin + pos, spmax + pos, out + pos, outsize + pos,
2204 /* Free remaining structures */
2205 free_graphs(out, outsize, spmin, spmax);
2210 ***************************************************************************
2211 * Display network interfaces statistics in SVG.
2214 * @a Activity structure with statistics.
2215 * @curr Index in array for current sample statistics.
2216 * @action Action expected from current function.
2217 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2218 * flag indicating that a restart record has been previously
2219 * found (.@restart) and time used for the X axis origin
2221 * @itv Interval of time in jiffies (only with F_MAIN action).
2222 * @record_hdr Pointer on record header of current stats sample.
2223 ***************************************************************************
2225 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2226 unsigned long long itv, struct record_header *record_hdr)
2228 struct stats_net_dev *sndc, *sndp, sndzero;
2229 int group[] = {2, 2, 3, 1};
2230 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2232 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2233 "Network statistics (3)", "Network statistics (4)"};
2234 char *g_title[] = {"rxpck/s", "txpck/s",
2236 "rxcmp/s", "txcmp/s", "rxmcst/s",
2238 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2239 unsigned int local_types_nr[] = {7, 0, 0};
2240 static double *spmin, *spmax;
2242 static int *outsize;
2244 double rxkb, txkb, ifutil;
2245 int i, j, k, pos, restart, *unregistered;
2247 if (action & F_BEGIN) {
2249 * Allocate arrays (#0..7) that will contain the graphs data
2250 * and the min/max values.
2251 * Also allocate one additional array (#8) for each interface:
2252 * out + 8 will contain the interface name,
2253 * outsize + 8 will contain a positive value (TRUE) if the interface
2254 * has either still not been registered, or has been unregistered.
2256 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2259 if (action & F_MAIN) {
2260 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2261 restart = svg_p->restart;
2263 * Mark previously registered interfaces as now
2264 * possibly unregistered for all graphs.
2266 for (k = 0; k < a->nr; k++) {
2267 unregistered = outsize + k * 9 + 8;
2268 if (*unregistered == FALSE) {
2269 *unregistered = MAYBE;
2273 /* For each network interfaces structure */
2274 for (i = 0; i < a->nr; i++) {
2275 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2276 if (!strcmp(sndc->interface, ""))
2277 /* Empty structure: This is the end of the list */
2280 /* Look for corresponding graph */
2281 for (k = 0; k < a->nr; k++) {
2282 item_name = *(out + k * 9 + 8);
2283 if (!strcmp(sndc->interface, item_name))
2288 /* Graph not found: Look for first free entry */
2289 for (k = 0; k < a->nr; k++) {
2290 item_name = *(out + k * 9 + 8);
2291 if (!strcmp(item_name, ""))
2295 /* No free graph entry: Graph for this item won't be drawn */
2300 unregistered = outsize + pos + 8;
2302 j = check_net_dev_reg(a, curr, !curr, i);
2304 /* This is a newly registered interface. Previous stats are zero */
2308 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2312 * If current interface was marked as previously unregistered,
2313 * then set restart variable to TRUE so that the graph will be
2314 * discontinuous, and mark it as now registered.
2316 if (*unregistered == TRUE) {
2319 *unregistered = FALSE;
2321 if (!item_name[0]) {
2322 /* Save network interface name (if not already done) */
2323 strncpy(item_name, sndc->interface, CHUNKSIZE);
2324 item_name[CHUNKSIZE - 1] = '\0';
2327 /* Check for min/max values */
2328 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2329 itv, spmin + pos, spmax + pos, g_fields);
2331 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2332 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2333 ifutil = compute_ifutil(sndc, rxkb, txkb);
2334 if (ifutil < *(spmin + pos + 7)) {
2335 *(spmin + pos + 7) = ifutil;
2337 if (ifutil > *(spmax + pos + 7)) {
2338 *(spmax + pos + 7) = ifutil;
2342 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2343 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2344 out + pos, outsize + pos, restart);
2346 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2347 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2348 out + pos + 1, outsize + pos + 1, restart);
2350 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2352 out + pos + 2, outsize + pos + 2, restart);
2354 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2356 out + pos + 3, outsize + pos + 3, restart);
2358 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2359 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2360 out + pos + 4, outsize + pos + 4, restart);
2362 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2363 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2364 out + pos + 5, outsize + pos + 5, restart);
2366 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2367 S_VALUE(sndp->multicast, sndc->multicast, itv),
2368 out + pos + 6, outsize + pos + 6, restart);
2370 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2372 out + pos + 7, outsize + pos + 7, svg_p->dt);
2375 /* Mark interfaces not seen here as now unregistered */
2376 for (k = 0; k < a->nr; k++) {
2377 unregistered = outsize + k * 9 + 8;
2378 if (*unregistered != FALSE) {
2379 *unregistered = TRUE;
2384 if (action & F_END) {
2385 for (i = 0; i < a->nr; i++) {
2387 * Check if there is something to display.
2388 * Don't test sndc->interface because maybe the network
2389 * interface has been registered later.
2395 /* Recalculate min and max values in kB, not in B */
2396 *(spmin + pos + 2) /= 1024;
2397 *(spmax + pos + 2) /= 1024;
2398 *(spmin + pos + 3) /= 1024;
2399 *(spmax + pos + 3) /= 1024;
2401 item_name = *(out + pos + 8);
2402 draw_activity_graphs(a->g_nr, g_type,
2403 title, g_title, item_name, group,
2404 spmin + pos, spmax + pos, out + pos, outsize + pos,
2408 /* Free remaining structures */
2409 free_graphs(out, outsize, spmin, spmax);
2414 ***************************************************************************
2415 * Display network interface errors statistics in SVG.
2418 * @a Activity structure with statistics.
2419 * @curr Index in array for current sample statistics.
2420 * @action Action expected from current function.
2421 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2422 * flag indicating that a restart record has been previously
2423 * found (.@restart) and time used for the X axis origin
2425 * @itv Interval of time in jiffies (only with F_MAIN action).
2426 * @record_hdr Pointer on record header of current stats sample.
2427 ***************************************************************************
2429 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2430 unsigned long long itv, struct record_header *record_hdr)
2432 struct stats_net_edev *snedc, *snedp, snedzero;
2433 int group[] = {2, 2, 2, 3};
2434 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2436 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2437 "Network errors statistics (3)", "Network errors statistics (4)"};
2438 char *g_title[] = {"rxerr/s", "txerr/s",
2439 "rxdrop/s", "txdrop/s",
2440 "rxfifo/s", "txfifo/s",
2441 "coll/s", "txcarr/s", "rxfram/s"};
2442 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2443 static double *spmin, *spmax;
2445 static int *outsize;
2447 int i, j, k, pos, restart, *unregistered;
2449 if (action & F_BEGIN) {
2451 * Allocate arrays (#0..8) that will contain the graphs data
2452 * and the min/max values.
2453 * Also allocate one additional array (#9) for each interface:
2454 * out + 9 will contain the interface name,
2455 * outsize + 9 will contain a positive value (TRUE) if the interface
2456 * has either still not been registered, or has been unregistered.
2458 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
2461 if (action & F_MAIN) {
2462 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2463 restart = svg_p->restart;
2465 * Mark previously registered interfaces as now
2466 * possibly unregistered for all graphs.
2468 for (k = 0; k < a->nr; k++) {
2469 unregistered = outsize + k * 10 + 9;
2470 if (*unregistered == FALSE) {
2471 *unregistered = MAYBE;
2475 /* For each network interfaces structure */
2476 for (i = 0; i < a->nr; i++) {
2477 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2478 if (!strcmp(snedc->interface, ""))
2479 /* Empty structure: This is the end of the list */
2482 /* Look for corresponding graph */
2483 for (k = 0; k < a->nr; k++) {
2484 item_name = *(out + k * 10 + 9);
2485 if (!strcmp(snedc->interface, item_name))
2490 /* Graph not found: Look for first free entry */
2491 for (k = 0; k < a->nr; k++) {
2492 item_name = *(out + k * 10 + 9);
2493 if (!strcmp(item_name, ""))
2497 /* No free graph entry: Graph for this item won't be drawn */
2502 unregistered = outsize + pos + 9;
2504 j = check_net_edev_reg(a, curr, !curr, i);
2506 /* This is a newly registered interface. Previous stats are zero */
2510 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2514 * If current interface was marked as previously unregistered,
2515 * then set restart variable to TRUE so that the graph will be
2516 * discontinuous, and mark it as now registered.
2518 if (*unregistered == TRUE) {
2521 *unregistered = FALSE;
2523 if (!item_name[0]) {
2524 /* Save network interface name (if not already done) */
2525 strncpy(item_name, snedc->interface, CHUNKSIZE);
2526 item_name[CHUNKSIZE - 1] = '\0';
2529 /* Check for min/max values */
2530 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2531 itv, spmin + pos, spmax + pos, g_fields);
2534 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2535 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2536 out + pos, outsize + pos, restart);
2538 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2539 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2540 out + pos + 1, outsize + pos + 1, restart);
2542 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2543 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2544 out + pos + 2, outsize + pos + 2, restart);
2546 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2547 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2548 out + pos + 3, outsize + pos + 3, restart);
2550 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2551 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2552 out + pos + 4, outsize + pos + 4, restart);
2554 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2555 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2556 out + pos + 5, outsize + pos + 5, restart);
2558 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2559 S_VALUE(snedp->collisions, snedc->collisions, itv),
2560 out + pos + 6, outsize + pos + 6, restart);
2562 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2563 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2564 out + pos + 7, outsize + pos + 7, restart);
2566 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2567 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2568 out + pos + 8, outsize + pos + 8, restart);
2571 /* Mark interfaces not seen here as now unregistered */
2572 for (k = 0; k < a->nr; k++) {
2573 unregistered = outsize + k * 10 + 9;
2574 if (*unregistered != FALSE) {
2575 *unregistered = TRUE;
2580 if (action & F_END) {
2581 for (i = 0; i < a->nr; i++) {
2583 * Check if there is something to display.
2584 * Don't test snedc->interface because maybe the network
2585 * interface has been registered later.
2591 item_name = *(out + pos + 9);
2592 draw_activity_graphs(a->g_nr, g_type,
2593 title, g_title, item_name, group,
2594 spmin + pos, spmax + pos, out + pos, outsize + pos,
2598 /* Free remaining structures */
2599 free_graphs(out, outsize, spmin, spmax);
2604 ***************************************************************************
2605 * Display NFS client statistics in SVG.
2608 * @a Activity structure with statistics.
2609 * @curr Index in array for current sample statistics.
2610 * @action Action expected from current function.
2611 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2612 * flag indicating that a restart record has been previously
2613 * found (.@restart) and time used for the X axis origin
2615 * @itv Interval of time in jiffies (only with F_MAIN action).
2616 * @record_hdr Pointer on record header of current stats sample.
2617 ***************************************************************************
2619 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2620 unsigned long long itv, struct record_header *record_hdr)
2622 struct stats_net_nfs
2623 *snnc = (struct stats_net_nfs *) a->buf[curr],
2624 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2625 int group[] = {2, 2, 2};
2626 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2627 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2628 "NFS client statistics (3)"};
2629 char *g_title[] = {"call/s", "retrans/s",
2630 "read/s", "write/s",
2631 "access/s", "getatt/s"};
2632 int g_fields[] = {0, 1, 2, 3, 4, 5};
2633 static double *spmin, *spmax;
2635 static int *outsize;
2637 if (action & F_BEGIN) {
2639 * Allocate arrays that will contain the graphs data
2640 * and the min/max values.
2642 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2645 if (action & F_MAIN) {
2646 /* Check for min/max values */
2647 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2648 itv, spmin, spmax, g_fields);
2651 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2652 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2653 out, outsize, svg_p->restart);
2655 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2656 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2657 out + 1, outsize + 1, svg_p->restart);
2659 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2660 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2661 out + 2, outsize + 2, svg_p->restart);
2663 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2664 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2665 out + 3, outsize + 3, svg_p->restart);
2667 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2668 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2669 out + 4, outsize + 4, svg_p->restart);
2671 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2672 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2673 out + 5, outsize + 5, svg_p->restart);
2676 if (action & F_END) {
2677 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2678 spmin, spmax, out, outsize, svg_p, record_hdr);
2680 /* Free remaining structures */
2681 free_graphs(out, outsize, spmin, spmax);
2686 ***************************************************************************
2687 * Display NFS server statistics in SVG.
2690 * @a Activity structure with statistics.
2691 * @curr Index in array for current sample statistics.
2692 * @action Action expected from current function.
2693 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2694 * flag indicating that a restart record has been previously
2695 * found (.@restart) and time used for the X axis origin
2697 * @itv Interval of time in jiffies (only with F_MAIN action).
2698 * @record_hdr Pointer on record header of current stats sample.
2699 ***************************************************************************
2701 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2702 unsigned long long itv, struct record_header *record_hdr)
2704 struct stats_net_nfsd
2705 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2706 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2707 int group[] = {2, 3, 2, 2, 2};
2708 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2709 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2710 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2711 "NFS server statistics (3)", "NFS server statistics (4)",
2712 "NFS server statistics (5)"};
2713 char *g_title[] = {"scall/s", "badcall/s",
2714 "packet/s", "udp/s", "tcp/s",
2716 "sread/s", "swrite/s",
2717 "saccess/s", "sgetatt/s"};
2718 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2719 static double *spmin, *spmax;
2721 static int *outsize;
2723 if (action & F_BEGIN) {
2725 * Allocate arrays that will contain the graphs data
2726 * and the min/max values.
2728 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2731 if (action & F_MAIN) {
2732 /* Check for min/max values */
2733 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2734 itv, spmin, spmax, g_fields);
2737 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2738 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2739 out, outsize, svg_p->restart);
2741 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2742 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2743 out + 1, outsize + 1, svg_p->restart);
2745 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2746 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2747 out + 2, outsize + 2, svg_p->restart);
2749 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2750 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2751 out + 3, outsize + 3, svg_p->restart);
2753 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2754 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2755 out + 4, outsize + 4, svg_p->restart);
2757 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2758 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2759 out + 5, outsize + 5, svg_p->restart);
2761 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2762 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2763 out + 6, outsize + 6, svg_p->restart);
2765 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2766 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2767 out + 7, outsize + 7, svg_p->restart);
2769 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2770 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2771 out + 8, outsize + 8, svg_p->restart);
2773 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2774 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2775 out + 9, outsize + 9, svg_p->restart);
2777 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2778 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2779 out + 10, outsize + 10, svg_p->restart);
2782 if (action & F_END) {
2783 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2784 spmin, spmax, out, outsize, svg_p, record_hdr);
2786 /* Free remaining structures */
2787 free_graphs(out, outsize, spmin, spmax);
2792 ***************************************************************************
2793 * Display network socket statistics in SVG.
2796 * @a Activity structure with statistics.
2797 * @curr Index in array for current sample statistics.
2798 * @action Action expected from current function.
2799 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2800 * flag indicating that a restart record has been previously
2801 * found (.@restart) and time used for the X axis origin
2803 * @itv Interval of time in jiffies (only with F_MAIN action).
2804 * @record_hdr Pointer on record header of current stats sample.
2805 ***************************************************************************
2807 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2808 unsigned long long itv, struct record_header *record_hdr)
2810 struct stats_net_sock
2811 *snsc = (struct stats_net_sock *) a->buf[curr];
2812 int group[] = {1, 5};
2813 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2814 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2815 char *g_title[] = {"~totsck",
2816 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2817 int g_fields[] = {0, 1, 5, 2, 3, 4};
2818 static double *spmin, *spmax;
2820 static int *outsize;
2822 if (action & F_BEGIN) {
2824 * Allocate arrays that will contain the graphs data
2825 * and the min/max values.
2827 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2830 if (action & F_MAIN) {
2831 /* Check for min/max values */
2832 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2833 itv, spmin, spmax, g_fields);
2835 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2836 (unsigned long) snsc->sock_inuse,
2837 out, outsize, svg_p->restart);
2839 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2840 (unsigned long) snsc->tcp_inuse,
2841 out + 1, outsize + 1, svg_p->restart);
2843 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2844 (unsigned long) snsc->udp_inuse,
2845 out + 2, outsize + 2, svg_p->restart);
2847 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2848 (unsigned long) snsc->raw_inuse,
2849 out + 3, outsize + 3, svg_p->restart);
2851 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2852 (unsigned long) snsc->frag_inuse,
2853 out + 4, outsize + 4, svg_p->restart);
2855 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2856 (unsigned long) snsc->tcp_tw,
2857 out + 5, outsize + 5, svg_p->restart);
2860 if (action & F_END) {
2861 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2862 spmin, spmax, out, outsize, svg_p, record_hdr);
2864 /* Free remaining structures */
2865 free_graphs(out, outsize, spmin, spmax);
2870 ***************************************************************************
2871 * Display IPv4 network statistics in SVG.
2874 * @a Activity structure with statistics.
2875 * @curr Index in array for current sample statistics.
2876 * @action Action expected from current function.
2877 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2878 * flag indicating that a restart record has been previously
2879 * found (.@restart) and time used for the X axis origin
2881 * @itv Interval of time in jiffies (only with F_MAIN action).
2882 * @record_hdr Pointer on record header of current stats sample.
2883 ***************************************************************************
2885 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2886 unsigned long long itv, struct record_header *record_hdr)
2889 *snic = (struct stats_net_ip *) a->buf[curr],
2890 *snip = (struct stats_net_ip *) a->buf[!curr];
2891 int group[] = {4, 2, 2};
2892 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2893 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2894 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2895 "asmrq/s", "asmok/s",
2896 "fragok/s", "fragcrt/s"};
2897 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2898 static double *spmin, *spmax;
2900 static int *outsize;
2902 if (action & F_BEGIN) {
2904 * Allocate arrays that will contain the graphs data
2905 * and the min/max values.
2907 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2910 if (action & F_MAIN) {
2911 /* Check for min/max values */
2912 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2913 itv, spmin, spmax, g_fields);
2916 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2917 S_VALUE(snip->InReceives, snic->InReceives, itv),
2918 out, outsize, svg_p->restart);
2920 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2921 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2922 out + 1, outsize + 1, svg_p->restart);
2924 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2925 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2926 out + 2, outsize + 2, svg_p->restart);
2928 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2929 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2930 out + 3, outsize + 3, svg_p->restart);
2932 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2933 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2934 out + 4, outsize + 4, svg_p->restart);
2936 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2937 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2938 out + 5, outsize + 5, svg_p->restart);
2940 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2941 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2942 out + 6, outsize + 6, svg_p->restart);
2944 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2945 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2946 out + 7, outsize + 7, svg_p->restart);
2949 if (action & F_END) {
2950 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2951 spmin, spmax, out, outsize, svg_p, record_hdr);
2953 /* Free remaining structures */
2954 free_graphs(out, outsize, spmin, spmax);
2959 ***************************************************************************
2960 * Display IPv4 network errors statistics in SVG.
2963 * @a Activity structure with statistics.
2964 * @curr Index in array for current sample statistics.
2965 * @action Action expected from current function.
2966 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2967 * flag indicating that a restart record has been previously
2968 * found (.@restart) and time used for the X axis origin
2970 * @itv Interval of time in jiffies (only with F_MAIN action).
2971 * @record_hdr Pointer on record header of current stats sample.
2972 ***************************************************************************
2974 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2975 unsigned long long itv, struct record_header *record_hdr)
2977 struct stats_net_eip
2978 *sneic = (struct stats_net_eip *) a->buf[curr],
2979 *sneip = (struct stats_net_eip *) a->buf[!curr];
2980 int group[] = {3, 2, 3};
2981 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2982 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
2983 "IPv4 network errors statistics (3)"};
2984 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
2985 "idisc/s", "odisc/s",
2986 "onort/s", "asmf/s", "fragf/s"};
2987 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2988 static double *spmin, *spmax;
2990 static int *outsize;
2992 if (action & F_BEGIN) {
2994 * Allocate arrays that will contain the graphs data
2995 * and the min/max values.
2997 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3000 if (action & F_MAIN) {
3001 /* Check for min/max values */
3002 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3003 itv, spmin, spmax, g_fields);
3006 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3007 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3008 out, outsize, svg_p->restart);
3010 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3011 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3012 out + 1, outsize + 1, svg_p->restart);
3014 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3015 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3016 out + 2, outsize + 2, svg_p->restart);
3018 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3019 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3020 out + 3, outsize + 3, svg_p->restart);
3022 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3023 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3024 out + 4, outsize + 4, svg_p->restart);
3026 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3027 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3028 out + 5, outsize + 5, svg_p->restart);
3030 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3031 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3032 out + 6, outsize + 6, svg_p->restart);
3034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3035 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3036 out + 7, outsize + 7, svg_p->restart);
3039 if (action & F_END) {
3040 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3041 spmin, spmax, out, outsize, svg_p, record_hdr);
3043 /* Free remaining structures */
3044 free_graphs(out, outsize, spmin, spmax);
3049 ***************************************************************************
3050 * Display ICMPv4 network statistics in SVG.
3053 * @a Activity structure with statistics.
3054 * @curr Index in array for current sample statistics.
3055 * @action Action expected from current function.
3056 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3057 * flag indicating that a restart record has been previously
3058 * found (.@restart) and time used for the X axis origin
3060 * @itv Interval of time in jiffies (only with F_MAIN action).
3061 * @record_hdr Pointer on record header of current stats sample.
3062 ***************************************************************************
3064 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3065 unsigned long long itv, struct record_header *record_hdr)
3067 struct stats_net_icmp
3068 *snic = (struct stats_net_icmp *) a->buf[curr],
3069 *snip = (struct stats_net_icmp *) a->buf[!curr];
3070 int group[] = {2, 4, 4, 4};
3071 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3073 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3074 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3075 char *g_title[] = {"imsg/s", "omsg/s",
3076 "iech/s", "iechr/s", "oech/s", "oechr/s",
3077 "itm/s", "itmr/s", "otm/s", "otmr/s",
3078 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3079 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3080 static double *spmin, *spmax;
3082 static int *outsize;
3084 if (action & F_BEGIN) {
3086 * Allocate arrays that will contain the graphs data
3087 * and the min/max values.
3089 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3092 if (action & F_MAIN) {
3093 /* Check for min/max values */
3094 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3095 itv, spmin, spmax, g_fields);
3098 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3099 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3100 out, outsize, svg_p->restart);
3102 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3103 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3104 out + 1, outsize + 1, svg_p->restart);
3106 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3107 S_VALUE(snip->InEchos, snic->InEchos, itv),
3108 out + 2, outsize + 2, svg_p->restart);
3110 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3111 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3112 out + 3, outsize + 3, svg_p->restart);
3114 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3115 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3116 out + 4, outsize + 4, svg_p->restart);
3118 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3119 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3120 out + 5, outsize + 5, svg_p->restart);
3122 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3123 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3124 out + 6, outsize + 6, svg_p->restart);
3126 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3127 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3128 out + 7, outsize + 7, svg_p->restart);
3130 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3131 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3132 out + 8, outsize + 8, svg_p->restart);
3134 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3135 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3136 out + 9, outsize + 9, svg_p->restart);
3138 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3139 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3140 out + 10, outsize + 10, svg_p->restart);
3142 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3143 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3144 out + 11, outsize + 11, svg_p->restart);
3146 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3147 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3148 out + 12, outsize + 12, svg_p->restart);
3150 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3151 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3152 out + 13, outsize + 13, svg_p->restart);
3155 if (action & F_END) {
3156 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3157 spmin, spmax, out, outsize, svg_p, record_hdr);
3159 /* Free remaining structures */
3160 free_graphs(out, outsize, spmin, spmax);
3165 ***************************************************************************
3166 * Display ICMPv4 network errors statistics in SVG.
3169 * @a Activity structure with statistics.
3170 * @curr Index in array for current sample statistics.
3171 * @action Action expected from current function.
3172 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3173 * flag indicating that a restart record has been previously
3174 * found (.@restart) and time used for the X axis origin
3176 * @itv Interval of time in jiffies (only with F_MAIN action).
3177 * @record_hdr Pointer on record header of current stats sample.
3178 ***************************************************************************
3180 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3181 unsigned long long itv, struct record_header *record_hdr)
3183 struct stats_net_eicmp
3184 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3185 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3186 int group[] = {2, 2, 2, 2, 2, 2};
3187 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3188 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3189 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3190 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3191 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3192 char *g_title[] = {"ierr/s", "oerr/s",
3193 "idstunr/s", "odstunr/s",
3194 "itmex/s", "otmex/s",
3195 "iparmpb/s", "oparmpb/s",
3196 "isrcq/s", "osrcq/s",
3197 "iredir/s", "oredir/s"};
3198 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3199 static double *spmin, *spmax;
3201 static int *outsize;
3203 if (action & F_BEGIN) {
3205 * Allocate arrays that will contain the graphs data
3206 * and the min/max values.
3208 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3211 if (action & F_MAIN) {
3212 /* Check for min/max values */
3213 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3214 itv, spmin, spmax, g_fields);
3217 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3218 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3219 out, outsize, svg_p->restart);
3221 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3222 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3223 out + 1, outsize + 1, svg_p->restart);
3225 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3226 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3227 out + 2, outsize + 2, svg_p->restart);
3229 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3230 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3231 out + 3, outsize + 3, svg_p->restart);
3233 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3234 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3235 out + 4, outsize + 4, svg_p->restart);
3237 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3238 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3239 out + 5, outsize + 5, svg_p->restart);
3241 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3242 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3243 out + 6, outsize + 6, svg_p->restart);
3245 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3246 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3247 out + 7, outsize + 7, svg_p->restart);
3249 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3250 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3251 out + 8, outsize + 8, svg_p->restart);
3253 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3254 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3255 out + 9, outsize + 9, svg_p->restart);
3257 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3258 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3259 out + 10, outsize + 10, svg_p->restart);
3261 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3262 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3263 out + 11, outsize + 11, svg_p->restart);
3266 if (action & F_END) {
3267 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3268 spmin, spmax, out, outsize, svg_p, record_hdr);
3270 /* Free remaining structures */
3271 free_graphs(out, outsize, spmin, spmax);
3276 ***************************************************************************
3277 * Display TCPv4 network statistics in SVG.
3280 * @a Activity structure with statistics.
3281 * @curr Index in array for current sample statistics.
3282 * @action Action expected from current function.
3283 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3284 * flag indicating that a restart record has been previously
3285 * found (.@restart) and time used for the X axis origin
3287 * @itv Interval of time in jiffies (only with F_MAIN action).
3288 * @record_hdr Pointer on record header of current stats sample.
3289 ***************************************************************************
3291 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3292 unsigned long long itv, struct record_header *record_hdr)
3294 struct stats_net_tcp
3295 *sntc = (struct stats_net_tcp *) a->buf[curr],
3296 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3297 int group[] = {2, 2};
3298 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3299 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3300 char *g_title[] = {"active/s", "passive/s",
3301 "iseg/s", "oseg/s"};
3302 int g_fields[] = {0, 1, 2, 3};
3303 static double *spmin, *spmax;
3305 static int *outsize;
3307 if (action & F_BEGIN) {
3309 * Allocate arrays that will contain the graphs data
3310 * and the min/max values.
3312 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3315 if (action & F_MAIN) {
3316 /* Check for min/max values */
3317 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3318 itv, spmin, spmax, g_fields);
3321 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3322 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3323 out, outsize, svg_p->restart);
3325 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3326 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3327 out + 1, outsize + 1, svg_p->restart);
3329 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3330 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3331 out + 2, outsize + 2, svg_p->restart);
3333 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3334 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3335 out + 3, outsize + 3, svg_p->restart);
3338 if (action & F_END) {
3339 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3340 spmin, spmax, out, outsize, svg_p, record_hdr);
3342 /* Free remaining structures */
3343 free_graphs(out, outsize, spmin, spmax);
3348 ***************************************************************************
3349 * Display TCPv4 network errors statistics in SVG.
3352 * @a Activity structure with statistics.
3353 * @curr Index in array for current sample statistics.
3354 * @action Action expected from current function.
3355 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3356 * flag indicating that a restart record has been previously
3357 * found (.@restart) and time used for the X axis origin
3359 * @itv Interval of time in jiffies (only with F_MAIN action).
3360 * @record_hdr Pointer on record header of current stats sample.
3361 ***************************************************************************
3363 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3364 unsigned long long itv, struct record_header *record_hdr)
3366 struct stats_net_etcp
3367 *snetc = (struct stats_net_etcp *) a->buf[curr],
3368 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3369 int group[] = {2, 3};
3370 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3371 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3372 char *g_title[] = {"atmptf/s", "estres/s",
3373 "retrans/s", "isegerr/s", "orsts/s"};
3374 int g_fields[] = {0, 1, 2, 3, 4};
3375 static double *spmin, *spmax;
3377 static int *outsize;
3379 if (action & F_BEGIN) {
3381 * Allocate arrays that will contain the graphs data
3382 * and the min/max values.
3384 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3387 if (action & F_MAIN) {
3388 /* Check for min/max values */
3389 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3390 itv, spmin, spmax, g_fields);
3393 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3394 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3395 out, outsize, svg_p->restart);
3397 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3398 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3399 out + 1, outsize + 1, svg_p->restart);
3401 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3402 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3403 out + 2, outsize + 2, svg_p->restart);
3405 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3406 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3407 out + 3, outsize + 3, svg_p->restart);
3409 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3410 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3411 out + 4, outsize + 4, svg_p->restart);
3414 if (action & F_END) {
3415 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3416 spmin, spmax, out, outsize, svg_p, record_hdr);
3418 /* Free remaining structures */
3419 free_graphs(out, outsize, spmin, spmax);
3424 ***************************************************************************
3425 * Display UDPv4 network statistics in SVG.
3428 * @a Activity structure with statistics.
3429 * @curr Index in array for current sample statistics.
3430 * @action Action expected from current function.
3431 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3432 * flag indicating that a restart record has been previously
3433 * found (.@restart) and time used for the X axis origin
3435 * @itv Interval of time in jiffies (only with F_MAIN action).
3436 * @record_hdr Pointer on record header of current stats sample.
3437 ***************************************************************************
3439 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3440 unsigned long long itv, struct record_header *record_hdr)
3442 struct stats_net_udp
3443 *snuc = (struct stats_net_udp *) a->buf[curr],
3444 *snup = (struct stats_net_udp *) a->buf[!curr];
3445 int group[] = {2, 2};
3446 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3447 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3448 char *g_title[] = {"idgm/s", "odgm/s",
3449 "noport/s", "idgmerr/s"};
3450 int g_fields[] = {0, 1, 2, 3};
3451 static double *spmin, *spmax;
3453 static int *outsize;
3455 if (action & F_BEGIN) {
3457 * Allocate arrays that will contain the graphs data
3458 * and the min/max values.
3460 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3463 if (action & F_MAIN) {
3464 /* Check for min/max values */
3465 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3466 itv, spmin, spmax, g_fields);
3469 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3470 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3471 out, outsize, svg_p->restart);
3473 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3474 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3475 out + 1, outsize + 1, svg_p->restart);
3477 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3478 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3479 out + 2, outsize + 2, svg_p->restart);
3481 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3482 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3483 out + 3, outsize + 3, svg_p->restart);
3486 if (action & F_END) {
3487 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3488 spmin, spmax, out, outsize, svg_p, record_hdr);
3490 /* Free remaining structures */
3491 free_graphs(out, outsize, spmin, spmax);
3496 ***************************************************************************
3497 * Display IPV6 network socket statistics in SVG.
3500 * @a Activity structure with statistics.
3501 * @curr Index in array for current sample statistics.
3502 * @action Action expected from current function.
3503 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3504 * flag indicating that a restart record has been previously
3505 * found (.@restart) and time used for the X axis origin
3507 * @itv Interval of time in jiffies (only with F_MAIN action).
3508 * @record_hdr Pointer on record header of current stats sample.
3509 ***************************************************************************
3511 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3512 unsigned long long itv, struct record_header *record_hdr)
3514 struct stats_net_sock6
3515 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3517 int g_type[] = {SVG_LINE_GRAPH};
3518 char *title[] = {"IPv6 network sockets"};
3519 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3520 int g_fields[] = {0, 1, 2, 3};
3521 static double *spmin, *spmax;
3523 static int *outsize;
3525 if (action & F_BEGIN) {
3527 * Allocate arrays that will contain the graphs data
3528 * and the min/max values.
3530 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3533 if (action & F_MAIN) {
3534 /* Check for min/max values */
3535 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3536 itv, spmin, spmax, g_fields);
3538 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3539 (unsigned long) snsc->tcp6_inuse,
3540 out, outsize, svg_p->restart);
3542 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3543 (unsigned long) snsc->udp6_inuse,
3544 out + 1, outsize + 1, svg_p->restart);
3546 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3547 (unsigned long) snsc->raw6_inuse,
3548 out + 2, outsize + 2, svg_p->restart);
3550 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3551 (unsigned long) snsc->frag6_inuse,
3552 out + 3, outsize + 3, svg_p->restart);
3555 if (action & F_END) {
3556 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3557 spmin, spmax, out, outsize, svg_p, record_hdr);
3559 /* Free remaining structures */
3560 free_graphs(out, outsize, spmin, spmax);
3565 ***************************************************************************
3566 * Display IPv6 network statistics in SVG.
3569 * @a Activity structure with statistics.
3570 * @curr Index in array for current sample statistics.
3571 * @action Action expected from current function.
3572 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3573 * flag indicating that a restart record has been previously
3574 * found (.@restart) and time used for the X axis origin
3576 * @itv Interval of time in jiffies (only with F_MAIN action).
3577 * @record_hdr Pointer on record header of current stats sample.
3578 ***************************************************************************
3580 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3581 unsigned long long itv, struct record_header *record_hdr)
3583 struct stats_net_ip6
3584 *snic = (struct stats_net_ip6 *) a->buf[curr],
3585 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3586 int group[] = {4, 2, 2, 2};
3587 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3589 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3590 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3591 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3592 "asmrq6/s", "asmok6/s",
3593 "imcpck6/s", "omcpck6/s",
3594 "fragok6/s", "fragcr6/s"};
3595 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3596 static double *spmin, *spmax;
3598 static int *outsize;
3600 if (action & F_BEGIN) {
3602 * Allocate arrays that will contain the graphs data
3603 * and the min/max values.
3605 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3608 if (action & F_MAIN) {
3609 /* Check for min/max values */
3610 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3611 itv, spmin, spmax, g_fields);
3614 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3615 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3616 out, outsize, svg_p->restart);
3618 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3619 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3620 out + 1, outsize + 1, svg_p->restart);
3622 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3623 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3624 out + 2, outsize + 2, svg_p->restart);
3626 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3627 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3628 out + 3, outsize + 3, svg_p->restart);
3630 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3631 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3632 out + 4, outsize + 4, svg_p->restart);
3634 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3635 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3636 out + 5, outsize + 5, svg_p->restart);
3638 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3639 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3640 out + 6, outsize + 6, svg_p->restart);
3642 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3643 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3644 out + 7, outsize + 7, svg_p->restart);
3646 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3647 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3648 out + 8, outsize + 8, svg_p->restart);
3650 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3651 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3652 out + 9, outsize + 9, svg_p->restart);
3655 if (action & F_END) {
3656 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3657 spmin, spmax, out, outsize, svg_p, record_hdr);
3659 /* Free remaining structures */
3660 free_graphs(out, outsize, spmin, spmax);
3665 ***************************************************************************
3666 * Display IPv6 network errors statistics in SVG.
3669 * @a Activity structure with statistics.
3670 * @curr Index in array for current sample statistics.
3671 * @action Action expected from current function.
3672 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3673 * flag indicating that a restart record has been previously
3674 * found (.@restart) and time used for the X axis origin
3676 * @itv Interval of time in jiffies (only with F_MAIN action).
3677 * @record_hdr Pointer on record header of current stats sample.
3678 ***************************************************************************
3680 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3681 unsigned long long itv, struct record_header *record_hdr)
3683 struct stats_net_eip6
3684 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3685 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3686 int group[] = {4, 2, 2, 3};
3687 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3689 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3690 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3691 "IPv6 network errors statistics (5)"};
3692 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3693 "idisc6/s", "odisc6/s",
3694 "inort6/s", "onort6/s",
3695 "asmf6/s", "fragf6/s", "itrpck6/s"};
3696 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3697 static double *spmin, *spmax;
3699 static int *outsize;
3701 if (action & F_BEGIN) {
3703 * Allocate arrays that will contain the graphs data
3704 * and the min/max values.
3706 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3709 if (action & F_MAIN) {
3710 /* Check for min/max values */
3711 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3712 itv, spmin, spmax, g_fields);
3715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3716 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3717 out, outsize, svg_p->restart);
3719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3720 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3721 out + 1, outsize + 1, svg_p->restart);
3723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3724 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3725 out + 2, outsize + 2, svg_p->restart);
3727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3728 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3729 out + 3, outsize + 3, svg_p->restart);
3731 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3732 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3733 out + 4, outsize + 4, svg_p->restart);
3735 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3736 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3737 out + 5, outsize + 5, svg_p->restart);
3739 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3740 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3741 out + 6, outsize + 6, svg_p->restart);
3743 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3744 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3745 out + 7, outsize + 7, svg_p->restart);
3747 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3748 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3749 out + 8, outsize + 8, svg_p->restart);
3751 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3752 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3753 out + 9, outsize + 9, svg_p->restart);
3755 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3756 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3757 out + 10, outsize + 10, svg_p->restart);
3760 if (action & F_END) {
3761 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3762 spmin, spmax, out, outsize, svg_p, record_hdr);
3764 /* Free remaining structures */
3765 free_graphs(out, outsize, spmin, spmax);
3770 ***************************************************************************
3771 * Display ICMPv6 network statistics in SVG.
3774 * @a Activity structure with statistics.
3775 * @curr Index in array for current sample statistics.
3776 * @action Action expected from current function.
3777 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3778 * flag indicating that a restart record has been previously
3779 * found (.@restart) and time used for the X axis origin
3781 * @itv Interval of time in jiffies (only with F_MAIN action).
3782 * @record_hdr Pointer on record header of current stats sample.
3783 ***************************************************************************
3785 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3786 unsigned long long itv, struct record_header *record_hdr)
3788 struct stats_net_icmp6
3789 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3790 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3791 int group[] = {2, 3, 5, 3, 4};
3792 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3793 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3794 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3795 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3796 "ICMPv6 network statistics (5)"};
3797 char *g_title[] = {"imsg6/s", "omsg6/s",
3798 "iech6/s", "iechr6/s", "oechr6/s",
3799 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3800 "irtsol6/s", "ortsol6/s", "irtad6/s",
3801 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3802 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3803 static double *spmin, *spmax;
3805 static int *outsize;
3807 if (action & F_BEGIN) {
3809 * Allocate arrays that will contain the graphs data
3810 * and the min/max values.
3812 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3815 if (action & F_MAIN) {
3816 /* Check for min/max values */
3817 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3818 itv, spmin, spmax, g_fields);
3821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3822 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3823 out, outsize, svg_p->restart);
3825 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3826 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3827 out + 1, outsize + 1, svg_p->restart);
3829 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3830 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3831 out + 2, outsize + 2, svg_p->restart);
3833 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3834 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3835 out + 3, outsize + 3, svg_p->restart);
3837 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3838 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3839 out + 4, outsize + 4, svg_p->restart);
3841 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3842 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3843 out + 5, outsize + 5, svg_p->restart);
3845 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3846 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3847 out + 6, outsize + 6, svg_p->restart);
3849 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3850 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3851 out + 7, outsize + 7, svg_p->restart);
3853 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3854 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3855 out + 8, outsize + 8, svg_p->restart);
3857 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3858 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3859 out + 9, outsize + 9, svg_p->restart);
3861 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3862 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3863 out + 10, outsize + 10, svg_p->restart);
3865 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3866 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3867 out + 11, outsize + 11, svg_p->restart);
3869 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3870 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3871 out + 12, outsize + 12, svg_p->restart);
3873 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3874 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3875 out + 13, outsize + 13, svg_p->restart);
3877 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3878 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3879 out + 14, outsize + 14, svg_p->restart);
3881 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3882 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3883 out + 15, outsize + 15, svg_p->restart);
3885 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3886 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3887 out + 16, outsize + 16, svg_p->restart);
3890 if (action & F_END) {
3891 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3892 spmin, spmax, out, outsize, svg_p, record_hdr);
3894 /* Free remaining structures */
3895 free_graphs(out, outsize, spmin, spmax);
3900 ***************************************************************************
3901 * Display ICMPv6 network errors statistics in SVG.
3904 * @a Activity structure with statistics.
3905 * @curr Index in array for current sample statistics.
3906 * @action Action expected from current function.
3907 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3908 * flag indicating that a restart record has been previously
3909 * found (.@restart) and time used for the X axis origin
3911 * @itv Interval of time in jiffies (only with F_MAIN action).
3912 * @record_hdr Pointer on record header of current stats sample.
3913 ***************************************************************************
3915 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3916 unsigned long long itv, struct record_header *record_hdr)
3918 struct stats_net_eicmp6
3919 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3920 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3921 int group[] = {1, 2, 2, 2, 2, 2};
3922 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3923 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3924 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3925 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3926 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3927 char *g_title[] = {"ierr6/s",
3928 "idtunr6/s", "odtunr6/s",
3929 "itmex6/s", "otmex6/s",
3930 "iprmpb6/s", "oprmpb6/s",
3931 "iredir6/s", "oredir6/s",
3932 "ipck2b6/s", "opck2b6/s"};
3933 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3934 static double *spmin, *spmax;
3936 static int *outsize;
3938 if (action & F_BEGIN) {
3940 * Allocate arrays that will contain the graphs data
3941 * and the min/max values.
3943 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3946 if (action & F_MAIN) {
3947 /* Check for min/max values */
3948 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3949 itv, spmin, spmax, g_fields);
3952 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3953 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
3954 out, outsize, svg_p->restart);
3956 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3957 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
3958 out + 1, outsize + 1, svg_p->restart);
3960 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3961 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
3962 out + 2, outsize + 2, svg_p->restart);
3964 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3965 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
3966 out + 3, outsize + 3, svg_p->restart);
3968 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3969 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
3970 out + 4, outsize + 4, svg_p->restart);
3972 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3973 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
3974 out + 5, outsize + 5, svg_p->restart);
3976 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3977 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
3978 out + 6, outsize + 6, svg_p->restart);
3980 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3981 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
3982 out + 7, outsize + 7, svg_p->restart);
3984 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3985 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
3986 out + 8, outsize + 8, svg_p->restart);
3988 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3989 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
3990 out + 9, outsize + 9, svg_p->restart);
3992 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3993 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
3994 out + 10, outsize + 10, svg_p->restart);
3997 if (action & F_END) {
3998 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3999 spmin, spmax, out, outsize, svg_p, record_hdr);
4001 /* Free remaining structures */
4002 free_graphs(out, outsize, spmin, spmax);
4007 ***************************************************************************
4008 * Display UDPv6 network statistics in SVG.
4011 * @a Activity structure with statistics.
4012 * @curr Index in array for current sample statistics.
4013 * @action Action expected from current function.
4014 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4015 * flag indicating that a restart record has been previously
4016 * found (.@restart) and time used for the X axis origin
4018 * @itv Interval of time in jiffies (only with F_MAIN action).
4019 * @record_hdr Pointer on record header of current stats sample.
4020 ***************************************************************************
4022 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4023 unsigned long long itv, struct record_header *record_hdr)
4025 struct stats_net_udp6
4026 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4027 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4028 int group[] = {2, 2};
4029 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4030 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
4031 char *g_title[] = {"idgm6/s", "odgm6/s",
4032 "noport6/s", "idgmer6/s"};
4033 int g_fields[] = {0, 1, 2, 3};
4034 static double *spmin, *spmax;
4036 static int *outsize;
4038 if (action & F_BEGIN) {
4040 * Allocate arrays that will contain the graphs data
4041 * and the min/max values.
4043 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4046 if (action & F_MAIN) {
4047 /* Check for min/max values */
4048 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4049 itv, spmin, spmax, g_fields);
4052 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4053 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4054 out, outsize, svg_p->restart);
4056 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4057 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4058 out + 1, outsize + 1, svg_p->restart);
4060 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4061 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4062 out + 2, outsize + 2, svg_p->restart);
4064 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4065 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4066 out + 3, outsize + 3, svg_p->restart);
4069 if (action & F_END) {
4070 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4071 spmin, spmax, out, outsize, svg_p, record_hdr);
4073 /* Free remaining structures */
4074 free_graphs(out, outsize, spmin, spmax);
4079 ***************************************************************************
4080 * Display CPU frequency statistics in SVG.
4083 * @a Activity structure with statistics.
4084 * @curr Index in array for current sample statistics.
4085 * @action Action expected from current function.
4086 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4087 * flag indicating that a restart record has been previously
4088 * found (.@restart) and time used for the X axis origin
4090 * @itv Interval of time in jiffies (unused here).
4091 * @record_hdr Pointer on record header of current stats sample.
4092 ***************************************************************************
4094 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4095 unsigned long long itv, struct record_header *record_hdr)
4097 struct stats_pwr_cpufreq *spc, *spp;
4099 int g_type[] = {SVG_LINE_GRAPH};
4100 char *title[] = {"CPU frequency"};
4101 char *g_title[] = {"MHz"};
4102 static double *spmin, *spmax;
4104 static int *outsize;
4108 if (action & F_BEGIN) {
4110 * Allocate arrays that will contain the graphs data
4111 * and the min/max values.
4113 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4116 if (action & F_MAIN) {
4118 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4120 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4121 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4123 /* Should current CPU (including CPU "all") be displayed? */
4124 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4129 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4130 ((double) spp->cpufreq) / 100,
4131 ((double) spc->cpufreq) / 100,
4132 out + i, outsize + i, svg_p->restart, svg_p->dt,
4133 spmin + i, spmax + i);
4137 if (action & F_END) {
4138 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4140 /* Should current CPU (including CPU "all") be displayed? */
4141 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4146 /* This is CPU "all" */
4147 strcpy(item_name, "all");
4150 sprintf(item_name, "%d", i - 1);
4153 draw_activity_graphs(a->g_nr, g_type,
4154 title, g_title, item_name, group,
4155 spmin + i, spmax + i, out + i, outsize + i,
4159 /* Free remaining structures */
4160 free_graphs(out, outsize, spmin, spmax);
4165 ***************************************************************************
4166 * Display fan statistics in SVG.
4169 * @a Activity structure with statistics.
4170 * @curr Index in array for current sample statistics.
4171 * @action Action expected from current function.
4172 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4173 * flag indicating that a restart record has been previously
4174 * found (.@restart) and time used for the X axis origin
4176 * @itv Interval of time in jiffies (unused here).
4177 * @record_hdr Pointer on record header of current stats sample.
4178 ***************************************************************************
4180 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4181 unsigned long long itv, struct record_header *record_hdr)
4183 struct stats_pwr_fan *spc, *spp;
4185 int g_type[] = {SVG_LINE_GRAPH};
4186 char *title[] = {"Fan speed"};
4187 char *g_title[] = {"~rpm"};
4188 static double *spmin, *spmax;
4190 static int *outsize;
4191 char item_name[MAX_SENSORS_DEV_LEN + 8];
4194 if (action & F_BEGIN) {
4196 * Allocate arrays that will contain the graphs data
4197 * and the min/max values.
4199 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4202 if (action & F_MAIN) {
4204 for (i = 0; i < a->nr; i++) {
4206 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4207 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4210 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4213 out + i, outsize + i, svg_p->restart, svg_p->dt,
4214 spmin + i, spmax + i);
4218 if (action & F_END) {
4219 for (i = 0; i < a->nr; i++) {
4221 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4223 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4224 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4226 draw_activity_graphs(a->g_nr, g_type,
4227 title, g_title, item_name, group,
4228 spmin + i, spmax + i, out + i, outsize + i,
4232 /* Free remaining structures */
4233 free_graphs(out, outsize, spmin, spmax);
4238 ***************************************************************************
4239 * Display temperature statistics in SVG.
4242 * @a Activity structure with statistics.
4243 * @curr Index in array for current sample statistics.
4244 * @action Action expected from current function.
4245 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4246 * flag indicating that a restart record has been previously
4247 * found (.@restart) and time used for the X axis origin
4249 * @itv Interval of time in jiffies (unused here).
4250 * @record_hdr Pointer on record header of current stats sample.
4251 ***************************************************************************
4253 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4254 unsigned long long itv, struct record_header *record_hdr)
4256 struct stats_pwr_temp *spc;
4257 int group[] = {1, 1};
4258 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4259 char *title[] = {"Device temperature (1)",
4260 "Device temperature (2)"};
4261 char *g_title[] = {"~degC",
4263 static double *spmin, *spmax;
4265 static int *outsize;
4266 char item_name[MAX_SENSORS_DEV_LEN + 8];
4270 if (action & F_BEGIN) {
4272 * Allocate arrays that will contain the graphs data
4273 * and the min/max values.
4275 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4278 if (action & F_MAIN) {
4279 /* For each temperature sensor */
4280 for (i = 0; i < a->nr; i++) {
4282 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4284 /* Look for min/max values */
4285 if (spc->temp < *(spmin + 2 * i)) {
4286 *(spmin + 2 * i) = spc->temp;
4288 if (spc->temp > *(spmax + 2 * i)) {
4289 *(spmax + 2 * i) = spc->temp;
4291 tval = (spc->temp_max - spc->temp_min) ?
4292 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4294 if (tval < *(spmin + 2 * i + 1)) {
4295 *(spmin + 2 * i + 1) = tval;
4297 if (tval > *(spmax + 2 * i + 1)) {
4298 *(spmax + 2 * i + 1) = tval;
4302 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4304 out + 2 * i, outsize + 2 * i, svg_p->restart);
4306 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4308 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4312 if (action & F_END) {
4313 for (i = 0; i < a->nr; i++) {
4315 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4317 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4318 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4320 draw_activity_graphs(a->g_nr, g_type,
4321 title, g_title, item_name, group,
4322 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4326 /* Free remaining structures */
4327 free_graphs(out, outsize, spmin, spmax);
4332 ***************************************************************************
4333 * Display voltage inputs statistics in SVG.
4336 * @a Activity structure with statistics.
4337 * @curr Index in array for current sample statistics.
4338 * @action Action expected from current function.
4339 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4340 * flag indicating that a restart record has been previously
4341 * found (.@restart) and time used for the X axis origin
4343 * @itv Interval of time in jiffies (only with F_MAIN action).
4344 * @record_hdr Pointer on record header of current stats sample.
4345 ***************************************************************************
4347 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4348 unsigned long long itv, struct record_header *record_hdr)
4350 struct stats_pwr_in *spc;
4351 int group[] = {1, 1};
4352 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4353 char *title[] = {"Voltage inputs (1)",
4354 "Voltage inputs (2)"};
4355 char *g_title[] = {"inV",
4357 static double *spmin, *spmax;
4359 static int *outsize;
4360 char item_name[MAX_SENSORS_DEV_LEN + 8];
4364 if (action & F_BEGIN) {
4366 * Allocate arrays that will contain the graphs data
4367 * and the min/max values.
4369 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4372 if (action & F_MAIN) {
4373 /* For each temperature sensor */
4374 for (i = 0; i < a->nr; i++) {
4376 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4378 /* Look for min/max values */
4379 if (spc->in < *(spmin + 2 * i)) {
4380 *(spmin + 2 * i) = spc->in;
4382 if (spc->in > *(spmax + 2 * i)) {
4383 *(spmax + 2 * i) = spc->in;
4385 tval = (spc->in_max - spc->in_min) ?
4386 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4388 if (tval < *(spmin + 2 * i + 1)) {
4389 *(spmin + 2 * i + 1) = tval;
4391 if (tval > *(spmax + 2 * i + 1)) {
4392 *(spmax + 2 * i + 1) = tval;
4396 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4398 out + 2 * i, outsize + 2 * i, svg_p->restart);
4400 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4402 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4406 if (action & F_END) {
4407 for (i = 0; i < a->nr; i++) {
4409 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4411 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4412 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4414 draw_activity_graphs(a->g_nr, g_type,
4415 title, g_title, item_name, group,
4416 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4420 /* Free remaining structures */
4421 free_graphs(out, outsize, spmin, spmax);
4426 ***************************************************************************
4427 * Display huge pages statistics in SVG.
4430 * @a Activity structure with statistics.
4431 * @curr Index in array for current sample statistics.
4432 * @action Action expected from current function.
4433 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4434 * flag indicating that a restart record has been previously
4435 * found (.@restart) and time used for the X axis origin
4437 * @itv Interval of time in jiffies (only with F_MAIN action).
4438 * @record_hdr Pointer on record header of current stats sample.
4439 ***************************************************************************
4441 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4442 unsigned long long itv, struct record_header *record_hdr)
4445 *smc = (struct stats_huge *) a->buf[curr];
4446 int group[] = {2, 1};
4447 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4448 char *title[] = {"Huge pages utilization (1)",
4449 "Huge pages utilization (2)"};
4450 char *g_title[] = {"~kbhugfree", "~kbhugused",
4452 int g_fields[] = {0};
4453 unsigned int local_types_nr[] = {0, 1, 0};
4454 static double *spmin, *spmax;
4456 static int *outsize;
4459 if (action & F_BEGIN) {
4461 * Allocate arrays that will contain the graphs data
4462 * and the min/max values.
4464 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4467 if (action & F_MAIN) {
4468 /* Check for min/max values */
4469 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4470 itv, spmin, spmax, g_fields);
4472 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4473 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4475 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4476 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4478 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4479 if (tval < *(spmin + 2)) {
4480 *(spmin + 2) = tval;
4482 if (tval > *(spmax + 2)) {
4483 *(spmax + 2) = tval;
4487 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4488 (unsigned long) smc->frhkb,
4489 out, outsize, svg_p->restart);
4491 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4492 (unsigned long) smc->tlhkb - smc->frhkb,
4493 out + 1, outsize + 1, svg_p->restart);
4495 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4497 out + 2, outsize + 2, svg_p->dt);
4500 if (action & F_END) {
4501 draw_activity_graphs(a->g_nr, g_type,
4502 title, g_title, NULL, group,
4503 spmin, spmax, out, outsize, svg_p, record_hdr);
4505 /* Free remaining structures */
4506 free_graphs(out, outsize, spmin, spmax);
4511 ***************************************************************************
4512 * Display filesystem statistics in SVG.
4515 * @a Activity structure with statistics.
4516 * @curr Index in array for current sample statistics.
4517 * @action Action expected from current function.
4518 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4519 * flag indicating that a restart record has been previously
4520 * found (.@restart) and time used for the X axis origin
4522 * @itv Interval of time in jiffies (unused here).
4523 * @record_hdr Pointer on record header of current stats sample.
4524 ***************************************************************************
4526 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4527 unsigned long long itv, struct record_header *record_hdr)
4529 struct stats_filesystem *sfc, *sfp;
4530 int group[] = {2, 2, 2, 1};
4531 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4532 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4533 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4534 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4535 char *g_title[] = {"~MBfsfree", "~MBfsused",
4536 "%ufsused", "%fsused",
4537 "Ifree/1000", "Iused/1000",
4539 static double *spmin, *spmax;
4541 static int *outsize;
4542 char *item_name = NULL;
4544 int i, k, pos, restart;
4546 if (action & F_BEGIN) {
4548 * Allocate arrays (#0..6) that will contain the graphs data
4549 * and the min/max values.
4550 * Also allocate two additional arrays (#7..8) for each filesystem:
4551 * out + 7 will contain the filesystem name,
4552 * out + 8 will contain the mount point.
4554 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
4557 if (action & F_MAIN) {
4558 /* For each filesystem structure */
4559 for (i = 0; i < a->nr; i++) {
4560 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4563 /* Size of filesystem is zero: We are at the end of the list */
4566 /* Look for corresponding graph */
4567 for (k = 0; k < a->nr; k++) {
4568 item_name = *(out + k * 9 + 7);
4569 if (!strcmp(sfc->fs_name, item_name))
4575 /* Graph not found: Look for first free entry */
4576 for (k = 0; k < a->nr; k++) {
4577 item_name = *(out + k * 9 + 7);
4578 if (!strcmp(item_name, ""))
4582 /* No free graph entry: Graph for this item won't be drawn */
4588 if (!item_name[0]) {
4589 /* Save filesystem name and mount point (if not already done) */
4590 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4591 item_name[CHUNKSIZE - 1] = '\0';
4592 item_name = *(out + pos + 8);
4593 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4594 item_name[CHUNKSIZE - 1] = '\0';
4598 for (k = 0; k < a->nr; k++) {
4599 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4600 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4601 /* Filesystem found in previous sample */
4602 restart = svg_p->restart;
4606 /* Check for min/max values */
4608 /* Compute fsfree min/max values */
4609 tval = (double) sfc->f_bfree;
4610 if (tval > *(spmax + pos)) {
4611 *(spmax + pos) = tval;
4613 if (tval < *(spmin + pos)) {
4614 *(spmin + pos) = tval;
4616 /* Compute fsused min/max values */
4617 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4618 if (tval > *(spmax + pos + 1)) {
4619 *(spmax + pos + 1) = tval;
4621 if (tval < *(spmin + pos + 1)) {
4622 *(spmin + pos + 1) = tval;
4624 /* Compute %ufsused min/max values */
4625 tval = sfc->f_blocks ?
4626 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4627 if (tval > *(spmax + pos + 2)) {
4628 *(spmax + pos + 2) = tval;
4630 if (tval < *(spmin + pos + 2)) {
4631 *(spmin + pos + 2) = tval;
4633 /* Compute %fsused min/max values */
4634 tval = sfc->f_blocks ?
4635 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4636 if (tval > *(spmax + pos + 3)) {
4637 *(spmax + pos + 3) = tval;
4639 if (tval < *(spmin + pos + 3)) {
4640 *(spmin + pos + 3) = tval;
4642 /* Compute Ifree min/max values */
4643 tval = (double) sfc->f_ffree;
4644 if (tval > *(spmax + pos + 4)) {
4645 *(spmax + pos + 4) = tval;
4647 if (tval < *(spmin + pos + 4)) {
4648 *(spmin + pos + 4) = tval;
4650 /* Compute Iused min/max values */
4651 tval = (double) (sfc->f_files - sfc->f_ffree);
4652 if (tval > *(spmax + pos + 5)) {
4653 *(spmax + pos + 5) = tval;
4655 if (tval < *(spmin + pos + 5)) {
4656 *(spmin + pos + 5) = tval;
4658 /* Compute %Iused min/max values */
4659 tval = sfc->f_files ?
4660 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4661 if (tval > *(spmax + pos + 6)) {
4662 *(spmax + pos + 6) = tval;
4664 if (tval < *(spmin + pos + 6)) {
4665 *(spmin + pos + 6) = tval;
4669 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4670 (double) sfc->f_bfree / 1024 / 1024,
4671 out + pos, outsize + pos, restart);
4673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4674 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4675 out + pos + 1, outsize + pos + 1, restart);
4677 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4680 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4681 out + pos + 2, outsize + pos + 2, svg_p->dt);
4683 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4686 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4687 out + pos + 3, outsize + pos + 3, svg_p->dt);
4689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4690 ((double) sfc->f_ffree) / 1000,
4691 out + pos + 4, outsize + pos + 4, restart);
4693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4694 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4695 out + pos + 5, outsize + pos + 5, restart);
4697 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4700 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4701 out + pos + 6, outsize + pos + 6, svg_p->dt);
4705 if (action & F_END) {
4707 for (i = 0; i < a->nr; i++) {
4709 /* Check if there is something to display */
4714 /* Conversion B -> MB and inodes/1000 */
4715 for (k = 0; k < 2; k++) {
4716 *(spmin + pos + k) /= (1024 * 1024);
4717 *(spmax + pos + k) /= (1024 * 1024);
4718 *(spmin + pos + 4 + k) /= 1000;
4719 *(spmax + pos + 4 + k) /= 1000;
4722 if (DISPLAY_MOUNT(a->opt_flags)) {
4723 item_name = *(out + pos + 8);
4726 item_name = *(out + pos + 7);
4729 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4730 spmin + pos, spmax + pos, out + pos, outsize + pos,
4734 /* Free remaining structures */
4735 free_graphs(out, outsize, spmin, spmax);
4740 ***************************************************************************
4741 * Display Fibre Channel HBA statistics in SVG.
4744 * @a Activity structure with statistics.
4745 * @curr Index in array for current sample statistics.
4746 * @action Action expected from current function.
4747 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4748 * flag indicating that a restart record has been previously
4749 * found (.@restart) and time used for the X axis origin
4751 * @itv Interval of time in jiffies (only with F_MAIN action).
4752 * @record_hdr Pointer on record header of current stats sample.
4753 ***************************************************************************
4755 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4756 unsigned long long itv, struct record_header *record_hdr)
4758 struct stats_fchost *sfcc, *sfcp;
4759 int group[] = {2, 2};
4760 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4761 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4762 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4763 "fch_rxw/s", "fch_txw/s"};
4764 int g_fields[] = {0, 1, 2, 3};
4765 static double *spmin, *spmax;
4767 static int *outsize;
4771 if (action & F_BEGIN) {
4773 * Allocate arrays (#0..3) that will contain the graphs data
4774 * and the min/max values.
4775 * Also allocate one additional array (#4) that will contain
4778 out = allocate_graph_lines(4 * a->nr, &outsize, &spmin, &spmax);
4781 if (action & F_MAIN) {
4782 /* For each FC HBA */
4783 for (i = 0; i < a->nr; i++) {
4785 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4786 if (!sfcc->fchost_name[0])
4787 /* We are at the end of the list */
4790 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
4793 item_name = *(out + pos + 4);
4794 if (!item_name[0]) {
4795 /* Save FC HBA name */
4796 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4797 item_name[CHUNKSIZE - 1] = '\0';
4800 /* Look for min/max values */
4801 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4802 itv, spmin + pos, spmax + pos, g_fields);
4805 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4806 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4807 out + pos, outsize + pos, svg_p->restart);
4809 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4810 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4811 out + pos + 1, outsize + pos + 1, svg_p->restart);
4813 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4814 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4815 out + pos + 2, outsize + pos + 2, svg_p->restart);
4817 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4818 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4819 out + pos + 3, outsize + pos + 3, svg_p->restart);
4823 if (action & F_END) {
4824 for (i = 0; i < a->nr; i++) {
4826 /* Check if there is something to display */
4831 item_name = *(out + pos + 4);
4832 draw_activity_graphs(a->g_nr, g_type,
4833 title, g_title, item_name, group,
4834 spmin + pos, spmax + pos, out + pos, outsize + pos,
4838 /* Free remaining structures */
4839 free_graphs(out, outsize, spmin, spmax);
4844 ***************************************************************************
4845 * Display softnet statistics in SVG.
4848 * @a Activity structure with statistics.
4849 * @curr Index in array for current sample statistics.
4850 * @action Action expected from current function.
4851 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4852 * flag indicating that a restart record has been previously
4853 * found (.@restart) and time used for the X axis origin
4855 * @itv Interval of time in jiffies (only with F_MAIN action).
4856 * @record_hdr Pointer on record header of current stats sample.
4857 ***************************************************************************
4859 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4860 unsigned long long itv, struct record_header *record_hdr)
4862 struct stats_softnet *ssnc, *ssnp;
4863 int group[] = {2, 3};
4864 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4865 char *title[] = {"Software-based network processing statistics (1)",
4866 "Software-based network processing statistics (2)"};
4867 char *g_title[] = {"total/s", "dropd/s",
4868 "squeezd/s", "rx_rps/s", "flw_lim/s"};
4869 int g_fields[] = {0, 1, 2, 3, 4};
4870 static double *spmin, *spmax;
4872 static int *outsize;
4876 if (action & F_BEGIN) {
4878 * Allocate arrays that will contain the graphs data
4879 * and the min/max values.
4881 out = allocate_graph_lines(5 * a->nr, &outsize, &spmin, &spmax);
4884 if (action & F_MAIN) {
4886 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4888 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
4889 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
4891 /* Should current CPU (including CPU "all") be displayed? */
4892 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4898 /* Check for min/max values */
4899 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
4900 itv, spmin + pos, spmax + pos, g_fields);
4903 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4904 S_VALUE(ssnp->processed, ssnc->processed, itv),
4905 out + pos, outsize + pos, svg_p->restart);
4907 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4908 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
4909 out + pos + 1, outsize + pos + 1, svg_p->restart);
4911 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4912 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
4913 out + pos + 2, outsize + pos + 2, svg_p->restart);
4915 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4916 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
4917 out + pos + 3, outsize + pos + 3, svg_p->restart);
4919 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4920 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
4921 out + pos + 4, outsize + pos + 4, svg_p->restart);
4925 if (action & F_END) {
4926 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4928 /* Should current CPU (including CPU "all") be displayed? */
4929 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4936 /* This is CPU "all" */
4937 strcpy(item_name, "all");
4940 sprintf(item_name, "%d", i - 1);
4943 draw_activity_graphs(a->g_nr, g_type,
4944 title, g_title, item_name, group,
4945 spmin + pos, spmax + pos, out + pos, outsize + pos,
4949 /* Free remaining structures */
4950 free_graphs(out, outsize, spmin, spmax);