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).
1005 * @record_hdr Pointer on record header of current stats sample.
1006 ***************************************************************************
1008 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1009 unsigned long long g_itv, struct record_header *record_hdr)
1011 struct stats_cpu *scc, *scp;
1014 int g_type[] = {SVG_BAR_GRAPH};
1015 char *title[] = {"CPU load"};
1016 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1017 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1018 static double *spmin, *spmax;
1020 static int *outsize;
1023 int i, j, k, pos, cpu_offline;
1025 if (action & F_BEGIN) {
1027 * Allocate arrays that will contain the graphs data
1028 * and the min/max values.
1030 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
1033 if (action & F_MAIN) {
1035 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1037 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1038 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1040 /* Should current CPU (including CPU "all") be displayed? */
1041 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1048 if (i) { /* Don't test CPU "all" here */
1050 * If the CPU is offline then it is omited from /proc/stat:
1051 * All the fields couldn't have been read and the sum of them is zero.
1052 * (Remember that guest/guest_nice times are already included in
1055 if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys +
1056 scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal +
1057 scc->cpu_hardirq + scc->cpu_softirq) == 0) {
1059 * Set current struct fields (which have been set to zero)
1060 * to values from previous iteration. Hence their values won't
1061 * jump from zero when the CPU comes back online.
1070 * Recalculate interval for current proc.
1071 * If result is 0 then current CPU is a tickless one.
1073 g_itv = get_per_cpu_interval(scc, scp);
1074 cpu_offline = FALSE;
1077 if (!g_itv) { /* Current CPU is offline or tickless */
1079 val = (cpu_offline ? 0.0 /* Offline CPU: %idle = 0% */
1080 : 100.0); /* Tickless CPU: %idle = 100% */
1082 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1085 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1089 /* Check min/max values for %user, etc. */
1090 for (k = 0; k < j; k++) {
1091 if (0.0 < *(spmin + pos + k)) {
1092 *(spmin + pos + k) = 0.0;
1094 if (0.0 > *(spmax + pos + k)) {
1095 *(spmax + pos + k) = 0.0;
1100 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1102 out + pos + j, outsize + pos + j, svg_p->dt,
1103 spmin + pos + j, spmax + pos + j);
1108 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1110 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1111 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, g_itv),
1112 out + pos, outsize + pos, svg_p->dt,
1113 spmin + pos, spmax + pos);
1117 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1119 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1121 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1122 scc->cpu_user - scc->cpu_guest, g_itv),
1123 out + pos, outsize + pos, svg_p->dt,
1124 spmin + pos, spmax + pos);
1127 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1129 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1130 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, g_itv),
1131 out + pos + 1, outsize + pos + 1, svg_p->dt,
1132 spmin + pos + 1, spmax + pos + 1);
1136 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1138 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1140 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1141 scc->cpu_nice - scc->cpu_guest_nice, g_itv),
1142 out + pos + 1, outsize + pos + 1, svg_p->dt,
1143 spmin + pos + 1, spmax + pos + 1);
1146 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1148 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1150 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1151 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1153 out + pos + 2, outsize + pos + 2, svg_p->dt,
1154 spmin + pos + 2, spmax + pos + 2);
1158 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1159 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, g_itv),
1160 out + pos + 2, outsize + pos + 2, svg_p->dt,
1161 spmin + pos + 2, spmax + pos + 2);
1165 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1166 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, g_itv),
1167 out + pos + 3, outsize + pos + 3, svg_p->dt,
1168 spmin + pos + 3, spmax + pos + 3);
1170 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1171 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, g_itv),
1172 out + pos + 4, outsize + pos + 4, svg_p->dt,
1173 spmin + pos + 4, spmax + pos + 4);
1175 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1177 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1178 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, g_itv),
1179 out + pos + 5, outsize + pos + 5, svg_p->dt,
1180 spmin + pos + 5, spmax + pos + 5);
1182 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1183 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, g_itv),
1184 out + pos + 6, outsize + pos + 6, svg_p->dt,
1185 spmin + pos + 6, spmax + pos + 6);
1187 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1188 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, g_itv),
1189 out + pos + 7, outsize + pos + 7, svg_p->dt,
1190 spmin + pos + 7, spmax + pos + 7);
1192 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1193 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, g_itv),
1194 out + pos + 8, outsize + pos + 8, svg_p->dt,
1195 spmin + pos + 8, spmax + pos + 8);
1204 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1206 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1207 ll_sp_value(scp->cpu_idle, scc->cpu_idle, g_itv)),
1208 out + pos + j, outsize + pos + j, svg_p->dt,
1209 spmin + pos + j, spmax + pos + j);
1213 if (action & F_END) {
1214 if (DISPLAY_IDLE(flags)) {
1215 /* Include additional %idle field */
1220 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
1222 /* Should current CPU (including CPU "all") be displayed? */
1223 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1229 /* This is CPU "all" */
1230 strcpy(item_name, "all");
1233 sprintf(item_name, "%d", i - 1);
1236 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1237 draw_activity_graphs(a->g_nr, g_type,
1238 title, g_title1, item_name, group1,
1239 spmin + pos, spmax + pos, out + pos, outsize + pos,
1243 draw_activity_graphs(a->g_nr, g_type,
1244 title, g_title2, item_name, group2,
1245 spmin + pos, spmax + pos, out + pos, outsize + pos,
1250 /* Free remaining structures */
1251 free_graphs(out, outsize, spmin, spmax);
1256 ***************************************************************************
1257 * Display task creation and context switch statistics in SVG.
1260 * @a Activity structure with statistics.
1261 * @curr Index in array for current sample statistics.
1262 * @action Action expected from current function.
1263 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1264 * flag indicating that a restart record has been previously
1265 * found (.@restart) and time used for the X axis origin
1267 * @itv Interval of time in jiffies (only with F_MAIN action).
1268 * @record_hdr Pointer on record header of current stats sample.
1269 ***************************************************************************
1271 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1272 unsigned long long itv, struct record_header *record_hdr)
1275 *spc = (struct stats_pcsw *) a->buf[curr],
1276 *spp = (struct stats_pcsw *) a->buf[!curr];
1277 int group[] = {1, 1};
1278 int g_fields[] = {1, 0};
1279 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1280 char *title[] = {"Task creation", "Switching activity"};
1281 char *g_title[] = {"proc/s",
1283 static double *spmin, *spmax;
1285 static int *outsize;
1287 if (action & F_BEGIN) {
1289 * Allocate arrays that will contain the graphs data
1290 * and the min/max values.
1292 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1295 if (action & F_MAIN) {
1296 /* Check for min/max values */
1297 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1298 itv, spmin, spmax, g_fields);
1300 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1301 S_VALUE(spp->processes, spc->processes, itv),
1302 out, outsize, svg_p->restart);
1304 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1305 S_VALUE(spp->context_switch, spc->context_switch, itv),
1306 out + 1, outsize + 1, svg_p->restart);
1309 if (action & F_END) {
1310 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1311 spmin, spmax, out, outsize, svg_p, record_hdr);
1313 /* Free remaining structures */
1314 free_graphs(out, outsize, spmin, spmax);
1319 ***************************************************************************
1320 * Display swap statistics in SVG.
1323 * @a Activity structure with statistics.
1324 * @curr Index in array for current sample statistics.
1325 * @action Action expected from current function.
1326 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1327 * flag indicating that a restart record has been previously
1328 * found (.@restart) and time used for the X axis origin
1330 * @itv Interval of time in jiffies (only with F_MAIN action).
1331 * @record_hdr Pointer on record header of current stats sample.
1332 ***************************************************************************
1334 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1335 unsigned long long itv, struct record_header *record_hdr)
1338 *ssc = (struct stats_swap *) a->buf[curr],
1339 *ssp = (struct stats_swap *) a->buf[!curr];
1341 int g_type[] = {SVG_LINE_GRAPH};
1342 char *title[] = {"Swap activity"};
1343 char *g_title[] = {"pswpin/s", "pswpout/s" };
1344 int g_fields[] = {0, 1};
1345 static double *spmin, *spmax;
1347 static int *outsize;
1349 if (action & F_BEGIN) {
1351 * Allocate arrays that will contain the graphs data
1352 * and the min/max values.
1354 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1357 if (action & F_MAIN) {
1358 /* Check for min/max values */
1359 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1360 itv, spmin, spmax, g_fields);
1362 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1363 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1364 out, outsize, svg_p->restart);
1366 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1367 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1368 out + 1, outsize + 1, svg_p->restart);
1371 if (action & F_END) {
1372 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1373 spmin, spmax, out, outsize, svg_p, record_hdr);
1375 /* Free remaining structures */
1376 free_graphs(out, outsize, spmin, spmax);
1381 ***************************************************************************
1382 * Display paging statistics in SVG.
1385 * @a Activity structure with statistics.
1386 * @curr Index in array for current sample statistics.
1387 * @action Action expected from current function.
1388 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1389 * flag indicating that a restart record has been previously
1390 * found (.@restart) and time used for the X axis origin
1392 * @itv Interval of time in jiffies (only with F_MAIN action).
1393 * @record_hdr Pointer on record header of current stats sample.
1394 ***************************************************************************
1396 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1397 unsigned long long itv, struct record_header *record_hdr)
1400 *spc = (struct stats_paging *) a->buf[curr],
1401 *spp = (struct stats_paging *) a->buf[!curr];
1402 int group[] = {2, 2, 4};
1403 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1404 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1405 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1406 "fault/s", "majflt/s",
1407 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1408 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1409 static double *spmin, *spmax;
1411 static int *outsize;
1413 if (action & F_BEGIN) {
1415 * Allocate arrays that will contain the graphs data
1416 * and the min/max values.
1418 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1421 if (action & F_MAIN) {
1422 /* Check for min/max values */
1423 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1424 itv, spmin, spmax, g_fields);
1426 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1427 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1428 out, outsize, svg_p->restart);
1430 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1431 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1432 out + 1, outsize + 1, svg_p->restart);
1434 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1435 S_VALUE(spp->pgfault, spc->pgfault, itv),
1436 out + 2, outsize + 2, svg_p->restart);
1438 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1439 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1440 out + 3, outsize + 3, svg_p->restart);
1442 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1443 S_VALUE(spp->pgfree, spc->pgfree, itv),
1444 out + 4, outsize + 4, svg_p->restart);
1446 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1447 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1448 out + 5, outsize + 5, svg_p->restart);
1450 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1451 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1452 out + 6, outsize + 6, svg_p->restart);
1454 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1455 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1456 out + 7, outsize + 7, svg_p->restart);
1459 if (action & F_END) {
1460 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1461 spmin, spmax, out, outsize, svg_p, record_hdr);
1463 /* Free remaining structures */
1464 free_graphs(out, outsize, spmin, spmax);
1469 ***************************************************************************
1470 * Display I/O and transfer rate statistics in SVG.
1473 * @a Activity structure with statistics.
1474 * @curr Index in array for current sample statistics.
1475 * @action Action expected from current function.
1476 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1477 * flag indicating that a restart record has been previously
1478 * found (.@restart) and time used for the X axis origin
1480 * @itv Interval of time in jiffies (only with F_MAIN action).
1481 * @record_hdr Pointer on record header of current stats sample.
1482 ***************************************************************************
1484 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1485 unsigned long long itv, struct record_header *record_hdr)
1488 *sic = (struct stats_io *) a->buf[curr],
1489 *sip = (struct stats_io *) a->buf[!curr];
1490 int group[] = {3, 2};
1491 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1492 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1493 char *g_title[] = {"tps", "rtps", "wtps",
1494 "bread/s", "bwrtn/s"};
1495 int g_fields[] = {0, 1, 2, 3, 4};
1496 static double *spmin, *spmax;
1498 static int *outsize;
1500 if (action & F_BEGIN) {
1502 * Allocate arrays that will contain the graphs data
1503 * and the min/max values.
1505 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1508 if (action & F_MAIN) {
1509 /* Check for min/max values */
1510 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1511 itv, spmin, spmax, g_fields);
1514 * If we get negative values, this is probably because
1515 * one or more devices/filesystems have been unmounted.
1516 * We display 0.0 in this case though we should rather tell
1517 * the user that the value cannot be calculated here.
1520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1521 sic->dk_drive < sip->dk_drive ? 0.0 :
1522 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1523 out, outsize, svg_p->restart);
1525 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1526 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1527 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1528 out + 1, outsize + 1, svg_p->restart);
1530 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1531 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1532 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1533 out + 2, outsize + 2, svg_p->restart);
1535 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1536 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1537 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1538 out + 3, outsize + 3, svg_p->restart);
1540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1541 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1542 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1543 out + 4, outsize + 4, svg_p->restart);
1546 if (action & F_END) {
1547 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1548 spmin, spmax, out, outsize, svg_p, record_hdr);
1550 /* Free remaining structures */
1551 free_graphs(out, outsize, spmin, spmax);
1556 ***************************************************************************
1557 * Display memory statistics in SVG.
1560 * @a Activity structure with statistics.
1561 * @curr Index in array for current sample statistics.
1562 * @action Action expected from current function.
1563 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1564 * flag indicating that a restart record has been previously
1565 * found (.@restart) and time used for the X axis origin
1567 * @itv Interval of time in jiffies (only with F_MAIN action).
1568 * @record_hdr Pointer on record header of current stats sample.
1569 ***************************************************************************
1571 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1572 unsigned long long itv, struct record_header *record_hdr)
1575 *smc = (struct stats_memory *) a->buf[curr];
1576 int group1[] = {3, 1, 3, 1, 3, 5};
1577 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1578 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1579 int group2[] = {3, 1, 1};
1580 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1581 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1582 "Memory utilization (3)", "Memory utilization (4)",
1583 "Memory utilization (5)", "Memory utilization (6)"};
1584 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1585 "Swap utilization (3)"};
1586 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1587 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1588 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1590 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1592 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1593 static double *spmin, *spmax;
1595 static int *outsize;
1599 if (action & F_BEGIN) {
1601 * Allocate arrays that will contain the graphs data
1602 * and the min/max values.
1604 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1607 if (action & F_MAIN) {
1608 /* Check for min/max values */
1609 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1610 itv, spmin, spmax, g_fields);
1611 /* Compute %memused min/max values */
1612 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1613 if (tval > *(spmax + 3)) {
1614 *(spmax + 3) = tval;
1616 if (tval < *(spmin + 3)) {
1617 *(spmin + 3) = tval;
1619 /* Compute %commit min/max values */
1620 tval = (smc->tlmkb + smc->tlskb) ?
1621 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1622 if (tval > *(spmax + 7)) {
1623 *(spmax + 7) = tval;
1625 if (tval < *(spmin + 7)) {
1626 *(spmin + 7) = tval;
1628 /* Compute %swpused min/max values */
1630 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1631 if (tval > *(spmax + 19)) {
1632 *(spmax + 19) = tval;
1634 if (tval < *(spmin + 19)) {
1635 *(spmin + 19) = tval;
1637 /* Compute %swpcad min/max values */
1638 tval = (smc->tlskb - smc->frskb) ?
1639 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1640 if (tval > *(spmax + 20)) {
1641 *(spmax + 20) = tval;
1643 if (tval < *(spmin + 20)) {
1644 *(spmin + 20) = tval;
1646 /* Compute memused min/max values in MB */
1647 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1648 if (tval > *(spmax + 2)) {
1649 *(spmax + 2) = tval;
1651 if (tval < *(spmin + 2)) {
1652 *(spmin + 2) = tval;
1654 /* Compute swpused min/max values in MB */
1655 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1656 if (tval > *(spmax + 17)) {
1657 *(spmax + 17) = tval;
1659 if (tval < *(spmin + 17)) {
1660 *(spmin + 17) = tval;
1664 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1665 ((double) smc->frmkb) / 1024,
1666 out, outsize, svg_p->restart);
1668 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1669 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1670 out + 2, outsize + 2, svg_p->restart);
1672 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1673 ((double) smc->availablekb) / 1024,
1674 out + 1, outsize + 1, svg_p->restart);
1676 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1677 ((double) smc->bufkb) / 1024,
1678 out + 4, outsize + 4, svg_p->restart);
1680 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1681 ((double) smc->camkb) / 1024,
1682 out + 5, outsize + 5, svg_p->restart);
1684 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1685 ((double) smc->frskb) / 1024,
1686 out + 16, outsize + 16, svg_p->restart);
1688 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1689 ((double) (smc->tlskb - smc->frskb)) / 1024,
1690 out + 17, outsize + 17, svg_p->restart);
1692 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1693 ((double) smc->caskb) / 1024,
1694 out + 18, outsize + 18, svg_p->restart);
1696 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1697 ((double) smc->comkb) / 1024,
1698 out + 6, outsize + 6, svg_p->restart);
1700 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1701 ((double) smc->activekb) / 1024,
1702 out + 8, outsize + 8, svg_p->restart);
1704 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1705 ((double) smc->inactkb) / 1024,
1706 out + 9, outsize + 9, svg_p->restart);
1708 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1709 ((double) smc->dirtykb) / 1024,
1710 out + 10, outsize + 10, svg_p->restart);
1712 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1713 ((double) smc->anonpgkb) / 1024,
1714 out + 11, outsize + 11, svg_p->restart);
1716 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1717 ((double) smc->slabkb) / 1024,
1718 out + 12, outsize + 12, svg_p->restart);
1720 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1721 ((double) smc->kstackkb) / 1024,
1722 out + 13, outsize + 13, svg_p->restart);
1724 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1725 ((double) smc->pgtblkb) / 1024,
1726 out + 14, outsize + 14, svg_p->restart);
1728 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1729 ((double) smc->vmusedkb) / 1024,
1730 out + 15, outsize + 15, svg_p->restart);
1732 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1735 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1736 out + 3, outsize + 3, svg_p->dt);
1738 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1740 (smc->tlmkb + smc->tlskb) ?
1741 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1742 out + 7, outsize + 7, svg_p->dt);
1744 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1747 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1748 out + 19, outsize + 19, svg_p->dt);
1750 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1752 (smc->tlskb - smc->frskb) ?
1753 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1754 out + 20, outsize + 20, svg_p->dt);
1757 if (action & F_END) {
1759 /* Conversion kB -> MB */
1760 for (i = 0; i < 17; i++) {
1761 *(spmin + g_fields[i]) /= 1024;
1762 *(spmax + g_fields[i]) /= 1024;
1765 if (DISPLAY_MEMORY(a->opt_flags)) {
1766 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1767 g_type1, title1, g_title1, NULL, group1,
1768 spmin, spmax, out, outsize, svg_p, record_hdr);
1771 if (DISPLAY_SWAP(a->opt_flags)) {
1772 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1773 spmin + 16, spmax + 16, out + 16, outsize + 16,
1777 /* Free remaining structures */
1778 free_graphs(out, outsize, spmin, spmax);
1783 ***************************************************************************
1784 * Display kernel tables statistics in SVG.
1787 * @a Activity structure with statistics.
1788 * @curr Index in array for current sample statistics.
1789 * @action Action expected from current function.
1790 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1791 * flag indicating that a restart record has been previously
1792 * found (.@restart) and time used for the X axis origin
1794 * @itv Interval of time in jiffies (only with F_MAIN action).
1795 * @record_hdr Pointer on record header of current stats sample.
1796 ***************************************************************************
1798 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1799 unsigned long long itv, struct record_header *record_hdr)
1801 struct stats_ktables
1802 *skc = (struct stats_ktables *) a->buf[curr];
1803 int group[] = {3, 1};
1804 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1805 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1806 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1808 int g_fields[] = {1, 2, 0, 3};
1809 static double *spmin, *spmax;
1811 static int *outsize;
1813 if (action & F_BEGIN) {
1815 * Allocate arrays that will contain the graphs data
1816 * and the min/max values.
1818 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1821 if (action & F_MAIN) {
1822 /* Check for min/max values */
1823 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1824 itv, spmin, spmax, g_fields);
1826 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1827 (unsigned long) skc->dentry_stat,
1828 out, outsize, svg_p->restart);
1830 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1831 (unsigned long) skc->file_used,
1832 out + 1, outsize + 1, svg_p->restart);
1834 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1835 (unsigned long) skc->inode_used,
1836 out + 2, outsize + 2, svg_p->restart);
1838 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1839 (unsigned long) skc->pty_nr,
1840 out + 3, outsize + 3, svg_p->restart);
1843 if (action & F_END) {
1844 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1845 spmin, spmax, out, outsize, svg_p, record_hdr);
1847 /* Free remaining structures */
1848 free_graphs(out, outsize, spmin, spmax);
1853 ***************************************************************************
1854 * Display queue and load statistics in SVG.
1857 * @a Activity structure with statistics.
1858 * @curr Index in array for current sample statistics.
1859 * @action Action expected from current function.
1860 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1861 * flag indicating that a restart record has been previously
1862 * found (.@restart) and time used for the X axis origin
1864 * @itv Interval of time in jiffies (only with F_MAIN action).
1865 * @record_hdr Pointer on record header of current stats sample.
1866 ***************************************************************************
1868 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1869 unsigned long long itv, struct record_header *record_hdr)
1872 *sqc = (struct stats_queue *) a->buf[curr];
1873 int group[] = {2, 1, 3};
1874 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1875 char *title[] = {"Queue length", "Task list", "Load average"};
1876 char *g_title[] = {"~runq-sz", "~blocked",
1878 "ldavg-1", "ldavg-5", "ldavg-15"};
1879 int g_fields[] = {0, 1, 3, 4, 5, 2};
1880 static double *spmin, *spmax;
1882 static int *outsize;
1884 if (action & F_BEGIN) {
1886 * Allocate arrays that will contain the graphs data
1887 * and the min/max values.
1889 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1892 if (action & F_MAIN) {
1893 /* Check for min/max values */
1894 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1895 itv, spmin, spmax, g_fields);
1897 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1898 (unsigned long) sqc->nr_running,
1899 out, outsize, svg_p->restart);
1901 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1902 (unsigned long) sqc->procs_blocked,
1903 out + 1, outsize + 1, svg_p->restart);
1905 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1906 (unsigned long) sqc->nr_threads,
1907 out + 2, outsize + 2, svg_p->restart);
1909 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1910 (double) sqc->load_avg_1 / 100,
1911 out + 3, outsize + 3, svg_p->restart);
1913 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1914 (double) sqc->load_avg_5 / 100,
1915 out + 4, outsize + 4, svg_p->restart);
1917 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1918 (double) sqc->load_avg_15 / 100,
1919 out + 5, outsize + 5, svg_p->restart);
1922 if (action & F_END) {
1923 /* Fix min/max values for load average */
1924 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1925 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1926 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1928 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1929 spmin, spmax, out, outsize, svg_p, record_hdr);
1931 /* Free remaining structures */
1932 free_graphs(out, outsize, spmin, spmax);
1937 ***************************************************************************
1938 * Display disk statistics in SVG.
1941 * @a Activity structure with statistics.
1942 * @curr Index in array for current sample statistics.
1943 * @action Action expected from current function.
1944 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1945 * flag indicating that a restart record has been previously
1946 * found (.@restart) and time used for the X axis origin
1948 * @itv Interval of time in jiffies (only with F_MAIN action).
1949 * @record_hdr Pointer on record header of current stats sample.
1950 ***************************************************************************
1952 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1953 unsigned long long itv, struct record_header *record_hdr)
1955 struct stats_disk *sdc, *sdp, sdpzero;
1956 struct ext_disk_stats xds;
1957 int group[] = {1, 2, 2, 2, 1};
1958 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
1959 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
1960 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
1961 "Disk statistics (3)", "Disk statistics (4)",
1962 "Disk statistics (5)"};
1963 char *g_title[] = {"tps",
1965 "areq-sz", "aqu-sz",
1968 int g_fields[] = {0, 1, 2};
1969 unsigned int local_types_nr[] = {1, 0, 0};
1970 static double *spmin, *spmax;
1972 static int *outsize;
1973 char *item_name, *persist_dev_name;
1974 double rkB, wkB, aqusz;
1975 int i, j, k, pos, restart, *unregistered;
1977 if (action & F_BEGIN) {
1979 * Allocate arrays (#0..7) that will contain the graphs data
1980 * and the min/max values.
1981 * Also allocate one additional array (#8) for each disk device:
1982 * spmax + 8 will contain the device major number,
1983 * spmin + 8 will contain the device minor number,
1984 * outsize + 8 will contain a positive value (TRUE) if the device
1985 * has either still not been registered, or has been unregistered.
1987 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
1990 if (action & F_MAIN) {
1991 memset(&sdpzero, 0, STATS_DISK_SIZE);
1992 restart = svg_p->restart;
1994 * Mark previously registered devices as now
1995 * possibly unregistered for all graphs.
1997 for (k = 0; k < a->nr; k++) {
1998 unregistered = outsize + k * 9 + 8;
1999 if (*unregistered == FALSE) {
2000 *unregistered = MAYBE;
2004 /* For each device structure */
2005 for (i = 0; i < a->nr; i++) {
2006 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2007 if (!(sdc->major + sdc->minor))
2008 /* Empty structure: Ignore it */
2011 /* Look for corresponding graph */
2012 for (k = 0; k < a->nr; k++) {
2013 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2014 (sdc->minor == *(spmin + k * 9 + 8)))
2019 /* Graph not found: Look for first free entry */
2020 for (k = 0; k < a->nr; k++) {
2021 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2025 /* No free graph entry: Graph for this item won't be drawn */
2029 unregistered = outsize + pos + 8;
2031 j = check_disk_reg(a, curr, !curr, i);
2033 /* This is a newly registered interface. Previous stats are zero */
2037 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2041 * If current device was marked as previously unregistered,
2042 * then set restart variable to TRUE so that the graph will be
2043 * discontinuous, and mark it as now registered.
2045 if (*unregistered == TRUE) {
2048 *unregistered = FALSE;
2050 if (*(spmax + pos + 8) == -DBL_MAX) {
2051 /* Save device major and minor numbers (if not already done) */
2052 *(spmax + pos + 8) = sdc->major;
2053 *(spmin + pos + 8) = sdc->minor;
2056 /* Check for min/max values */
2057 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2058 itv, spmin + pos, spmax + pos, g_fields);
2060 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2061 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2062 if (rkB < *(spmin + pos + 1)) {
2063 *(spmin + pos + 1) = rkB;
2065 if (rkB > *(spmax + pos + 1)) {
2066 *(spmax + pos + 1) = rkB;
2068 if (wkB < *(spmin + pos + 2)) {
2069 *(spmin + pos + 2) = wkB;
2071 if (wkB > *(spmax + pos + 2)) {
2072 *(spmax + pos + 2) = wkB;
2075 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2076 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2077 *(spmin + pos + 3) = xds.arqsz / 2;
2079 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2080 *(spmax + pos + 3) = xds.arqsz / 2;
2082 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2083 if (aqusz < *(spmin + pos + 4)) {
2084 *(spmin + pos + 4) = aqusz;
2086 if (aqusz > *(spmax + pos + 4)) {
2087 *(spmax + pos + 4) = aqusz;
2089 if (xds.await < *(spmin + pos + 5)) {
2090 *(spmin + pos + 5) = xds.await;
2092 if (xds.await > *(spmax + pos + 5)) {
2093 *(spmax + pos + 5) = xds.await;
2095 if (xds.svctm < *(spmin + pos + 6)) {
2096 *(spmin + pos + 6) = xds.svctm;
2098 if (xds.svctm > *(spmax + pos + 6)) {
2099 *(spmax + pos + 6) = xds.svctm;
2101 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2102 *(spmin + pos + 7) = xds.util / 10.0;
2104 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2105 *(spmax + pos + 7) = xds.util / 10.0;
2109 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2110 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2111 out + pos, outsize + pos, restart);
2113 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2114 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2115 out + pos + 1, outsize + pos + 1, restart);
2117 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2118 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2119 out + pos + 2, outsize + pos + 2, restart);
2121 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2123 out + pos + 3, outsize + pos + 3, restart);
2125 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2127 out + pos + 4, outsize + pos + 4, restart);
2129 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2131 out + pos + 5, outsize + pos + 5, restart);
2133 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2135 out + pos + 6, outsize + pos + 6, restart);
2137 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2138 0.0, xds.util / 10.0,
2139 out + pos + 7, outsize + pos + 7, svg_p->dt);
2142 /* Mark devices not seen here as now unregistered */
2143 for (k = 0; k < a->nr; k++) {
2144 unregistered = outsize + k * 9 + 8;
2145 if (*unregistered != FALSE) {
2146 *unregistered = TRUE;
2151 if (action & F_END) {
2152 for (i = 0; i < a->nr; i++) {
2153 /* Check if there is something to display */
2159 persist_dev_name = NULL;
2161 if (DISPLAY_PERSIST_NAME_S(flags)) {
2162 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2166 if (persist_dev_name) {
2167 item_name = persist_dev_name;
2170 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2171 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2175 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2176 USE_PRETTY_OPTION(flags));
2180 draw_activity_graphs(a->g_nr, g_type,
2181 title, g_title, item_name, group,
2182 spmin + pos, spmax + pos, out + pos, outsize + pos,
2186 /* Free remaining structures */
2187 free_graphs(out, outsize, spmin, spmax);
2192 ***************************************************************************
2193 * Display network interfaces statistics in SVG.
2196 * @a Activity structure with statistics.
2197 * @curr Index in array for current sample statistics.
2198 * @action Action expected from current function.
2199 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2200 * flag indicating that a restart record has been previously
2201 * found (.@restart) and time used for the X axis origin
2203 * @itv Interval of time in jiffies (only with F_MAIN action).
2204 * @record_hdr Pointer on record header of current stats sample.
2205 ***************************************************************************
2207 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2208 unsigned long long itv, struct record_header *record_hdr)
2210 struct stats_net_dev *sndc, *sndp, sndzero;
2211 int group[] = {2, 2, 3, 1};
2212 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2214 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2215 "Network statistics (3)", "Network statistics (4)"};
2216 char *g_title[] = {"rxpck/s", "txpck/s",
2218 "rxcmp/s", "txcmp/s", "rxmcst/s",
2220 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2221 unsigned int local_types_nr[] = {7, 0, 0};
2222 static double *spmin, *spmax;
2224 static int *outsize;
2226 double rxkb, txkb, ifutil;
2227 int i, j, k, pos, restart, *unregistered;
2229 if (action & F_BEGIN) {
2231 * Allocate arrays (#0..7) that will contain the graphs data
2232 * and the min/max values.
2233 * Also allocate one additional array (#8) for each interface:
2234 * out + 8 will contain the interface name,
2235 * outsize + 8 will contain a positive value (TRUE) if the interface
2236 * has either still not been registered, or has been unregistered.
2238 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
2241 if (action & F_MAIN) {
2242 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2243 restart = svg_p->restart;
2245 * Mark previously registered interfaces as now
2246 * possibly unregistered for all graphs.
2248 for (k = 0; k < a->nr; k++) {
2249 unregistered = outsize + k * 9 + 8;
2250 if (*unregistered == FALSE) {
2251 *unregistered = MAYBE;
2255 /* For each network interfaces structure */
2256 for (i = 0; i < a->nr; i++) {
2257 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2258 if (!strcmp(sndc->interface, ""))
2259 /* Empty structure: This is the end of the list */
2262 /* Look for corresponding graph */
2263 for (k = 0; k < a->nr; k++) {
2264 item_name = *(out + k * 9 + 8);
2265 if (!strcmp(sndc->interface, item_name))
2270 /* Graph not found: Look for first free entry */
2271 for (k = 0; k < a->nr; k++) {
2272 item_name = *(out + k * 9 + 8);
2273 if (!strcmp(item_name, ""))
2277 /* No free graph entry: Graph for this item won't be drawn */
2282 unregistered = outsize + pos + 8;
2284 j = check_net_dev_reg(a, curr, !curr, i);
2286 /* This is a newly registered interface. Previous stats are zero */
2290 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2294 * If current interface was marked as previously unregistered,
2295 * then set restart variable to TRUE so that the graph will be
2296 * discontinuous, and mark it as now registered.
2298 if (*unregistered == TRUE) {
2301 *unregistered = FALSE;
2303 if (!item_name[0]) {
2304 /* Save network interface name (if not already done) */
2305 strncpy(item_name, sndc->interface, CHUNKSIZE);
2306 item_name[CHUNKSIZE - 1] = '\0';
2309 /* Check for min/max values */
2310 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2311 itv, spmin + pos, spmax + pos, g_fields);
2313 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2314 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2315 ifutil = compute_ifutil(sndc, rxkb, txkb);
2316 if (ifutil < *(spmin + pos + 7)) {
2317 *(spmin + pos + 7) = ifutil;
2319 if (ifutil > *(spmax + pos + 7)) {
2320 *(spmax + pos + 7) = ifutil;
2324 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2325 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2326 out + pos, outsize + pos, restart);
2328 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2329 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2330 out + pos + 1, outsize + pos + 1, restart);
2332 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2334 out + pos + 2, outsize + pos + 2, restart);
2336 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2338 out + pos + 3, outsize + pos + 3, restart);
2340 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2341 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2342 out + pos + 4, outsize + pos + 4, restart);
2344 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2345 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2346 out + pos + 5, outsize + pos + 5, restart);
2348 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2349 S_VALUE(sndp->multicast, sndc->multicast, itv),
2350 out + pos + 6, outsize + pos + 6, restart);
2352 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2354 out + pos + 7, outsize + pos + 7, svg_p->dt);
2357 /* Mark interfaces not seen here as now unregistered */
2358 for (k = 0; k < a->nr; k++) {
2359 unregistered = outsize + k * 9 + 8;
2360 if (*unregistered != FALSE) {
2361 *unregistered = TRUE;
2366 if (action & F_END) {
2367 for (i = 0; i < a->nr; i++) {
2369 * Check if there is something to display.
2370 * Don't test sndc->interface because maybe the network
2371 * interface has been registered later.
2377 /* Recalculate min and max values in kB, not in B */
2378 *(spmin + pos + 2) /= 1024;
2379 *(spmax + pos + 2) /= 1024;
2380 *(spmin + pos + 3) /= 1024;
2381 *(spmax + pos + 3) /= 1024;
2383 item_name = *(out + pos + 8);
2384 draw_activity_graphs(a->g_nr, g_type,
2385 title, g_title, item_name, group,
2386 spmin + pos, spmax + pos, out + pos, outsize + pos,
2390 /* Free remaining structures */
2391 free_graphs(out, outsize, spmin, spmax);
2396 ***************************************************************************
2397 * Display network interface errors statistics in SVG.
2400 * @a Activity structure with statistics.
2401 * @curr Index in array for current sample statistics.
2402 * @action Action expected from current function.
2403 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2404 * flag indicating that a restart record has been previously
2405 * found (.@restart) and time used for the X axis origin
2407 * @itv Interval of time in jiffies (only with F_MAIN action).
2408 * @record_hdr Pointer on record header of current stats sample.
2409 ***************************************************************************
2411 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2412 unsigned long long itv, struct record_header *record_hdr)
2414 struct stats_net_edev *snedc, *snedp, snedzero;
2415 int group[] = {2, 2, 2, 3};
2416 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2418 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2419 "Network errors statistics (3)", "Network errors statistics (4)"};
2420 char *g_title[] = {"rxerr/s", "txerr/s",
2421 "rxdrop/s", "txdrop/s",
2422 "rxfifo/s", "txfifo/s",
2423 "coll/s", "txcarr/s", "rxfram/s"};
2424 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2425 static double *spmin, *spmax;
2427 static int *outsize;
2429 int i, j, k, pos, restart, *unregistered;
2431 if (action & F_BEGIN) {
2433 * Allocate arrays (#0..8) that will contain the graphs data
2434 * and the min/max values.
2435 * Also allocate one additional array (#9) for each interface:
2436 * out + 9 will contain the interface name,
2437 * outsize + 9 will contain a positive value (TRUE) if the interface
2438 * has either still not been registered, or has been unregistered.
2440 out = allocate_graph_lines(10 * a->nr, &outsize, &spmin, &spmax);
2443 if (action & F_MAIN) {
2444 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2445 restart = svg_p->restart;
2447 * Mark previously registered interfaces as now
2448 * possibly unregistered for all graphs.
2450 for (k = 0; k < a->nr; k++) {
2451 unregistered = outsize + k * 10 + 9;
2452 if (*unregistered == FALSE) {
2453 *unregistered = MAYBE;
2457 /* For each network interfaces structure */
2458 for (i = 0; i < a->nr; i++) {
2459 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2460 if (!strcmp(snedc->interface, ""))
2461 /* Empty structure: This is the end of the list */
2464 /* Look for corresponding graph */
2465 for (k = 0; k < a->nr; k++) {
2466 item_name = *(out + k * 10 + 9);
2467 if (!strcmp(snedc->interface, item_name))
2472 /* Graph not found: Look for first free entry */
2473 for (k = 0; k < a->nr; k++) {
2474 item_name = *(out + k * 10 + 9);
2475 if (!strcmp(item_name, ""))
2479 /* No free graph entry: Graph for this item won't be drawn */
2484 unregistered = outsize + pos + 9;
2486 j = check_net_edev_reg(a, curr, !curr, i);
2488 /* This is a newly registered interface. Previous stats are zero */
2492 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2496 * If current interface was marked as previously unregistered,
2497 * then set restart variable to TRUE so that the graph will be
2498 * discontinuous, and mark it as now registered.
2500 if (*unregistered == TRUE) {
2503 *unregistered = FALSE;
2505 if (!item_name[0]) {
2506 /* Save network interface name (if not already done) */
2507 strncpy(item_name, snedc->interface, CHUNKSIZE);
2508 item_name[CHUNKSIZE - 1] = '\0';
2511 /* Check for min/max values */
2512 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2513 itv, spmin + pos, spmax + pos, g_fields);
2516 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2517 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2518 out + pos, outsize + pos, restart);
2520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2521 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2522 out + pos + 1, outsize + pos + 1, restart);
2524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2525 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2526 out + pos + 2, outsize + pos + 2, restart);
2528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2529 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2530 out + pos + 3, outsize + pos + 3, restart);
2532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2533 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2534 out + pos + 4, outsize + pos + 4, restart);
2536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2537 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2538 out + pos + 5, outsize + pos + 5, restart);
2540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2541 S_VALUE(snedp->collisions, snedc->collisions, itv),
2542 out + pos + 6, outsize + pos + 6, restart);
2544 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2545 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2546 out + pos + 7, outsize + pos + 7, restart);
2548 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2549 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2550 out + pos + 8, outsize + pos + 8, restart);
2553 /* Mark interfaces not seen here as now unregistered */
2554 for (k = 0; k < a->nr; k++) {
2555 unregistered = outsize + k * 10 + 9;
2556 if (*unregistered != FALSE) {
2557 *unregistered = TRUE;
2562 if (action & F_END) {
2563 for (i = 0; i < a->nr; i++) {
2565 * Check if there is something to display.
2566 * Don't test snedc->interface because maybe the network
2567 * interface has been registered later.
2573 item_name = *(out + pos + 9);
2574 draw_activity_graphs(a->g_nr, g_type,
2575 title, g_title, item_name, group,
2576 spmin + pos, spmax + pos, out + pos, outsize + pos,
2580 /* Free remaining structures */
2581 free_graphs(out, outsize, spmin, spmax);
2586 ***************************************************************************
2587 * Display NFS client statistics in SVG.
2590 * @a Activity structure with statistics.
2591 * @curr Index in array for current sample statistics.
2592 * @action Action expected from current function.
2593 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2594 * flag indicating that a restart record has been previously
2595 * found (.@restart) and time used for the X axis origin
2597 * @itv Interval of time in jiffies (only with F_MAIN action).
2598 * @record_hdr Pointer on record header of current stats sample.
2599 ***************************************************************************
2601 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2602 unsigned long long itv, struct record_header *record_hdr)
2604 struct stats_net_nfs
2605 *snnc = (struct stats_net_nfs *) a->buf[curr],
2606 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2607 int group[] = {2, 2, 2};
2608 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2609 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2610 "NFS client statistics (3)"};
2611 char *g_title[] = {"call/s", "retrans/s",
2612 "read/s", "write/s",
2613 "access/s", "getatt/s"};
2614 int g_fields[] = {0, 1, 2, 3, 4, 5};
2615 static double *spmin, *spmax;
2617 static int *outsize;
2619 if (action & F_BEGIN) {
2621 * Allocate arrays that will contain the graphs data
2622 * and the min/max values.
2624 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2627 if (action & F_MAIN) {
2628 /* Check for min/max values */
2629 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2630 itv, spmin, spmax, g_fields);
2633 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2634 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2635 out, outsize, svg_p->restart);
2637 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2638 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2639 out + 1, outsize + 1, svg_p->restart);
2641 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2642 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2643 out + 2, outsize + 2, svg_p->restart);
2645 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2646 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2647 out + 3, outsize + 3, svg_p->restart);
2649 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2650 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2651 out + 4, outsize + 4, svg_p->restart);
2653 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2654 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2655 out + 5, outsize + 5, svg_p->restart);
2658 if (action & F_END) {
2659 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2660 spmin, spmax, out, outsize, svg_p, record_hdr);
2662 /* Free remaining structures */
2663 free_graphs(out, outsize, spmin, spmax);
2668 ***************************************************************************
2669 * Display NFS server statistics in SVG.
2672 * @a Activity structure with statistics.
2673 * @curr Index in array for current sample statistics.
2674 * @action Action expected from current function.
2675 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2676 * flag indicating that a restart record has been previously
2677 * found (.@restart) and time used for the X axis origin
2679 * @itv Interval of time in jiffies (only with F_MAIN action).
2680 * @record_hdr Pointer on record header of current stats sample.
2681 ***************************************************************************
2683 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2684 unsigned long long itv, struct record_header *record_hdr)
2686 struct stats_net_nfsd
2687 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2688 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2689 int group[] = {2, 3, 2, 2, 2};
2690 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2691 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2692 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2693 "NFS server statistics (3)", "NFS server statistics (4)",
2694 "NFS server statistics (5)"};
2695 char *g_title[] = {"scall/s", "badcall/s",
2696 "packet/s", "udp/s", "tcp/s",
2698 "sread/s", "swrite/s",
2699 "saccess/s", "sgetatt/s"};
2700 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2701 static double *spmin, *spmax;
2703 static int *outsize;
2705 if (action & F_BEGIN) {
2707 * Allocate arrays that will contain the graphs data
2708 * and the min/max values.
2710 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2713 if (action & F_MAIN) {
2714 /* Check for min/max values */
2715 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2716 itv, spmin, spmax, g_fields);
2719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2720 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2721 out, outsize, svg_p->restart);
2723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2724 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2725 out + 1, outsize + 1, svg_p->restart);
2727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2728 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2729 out + 2, outsize + 2, svg_p->restart);
2731 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2732 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2733 out + 3, outsize + 3, svg_p->restart);
2735 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2736 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2737 out + 4, outsize + 4, svg_p->restart);
2739 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2740 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2741 out + 5, outsize + 5, svg_p->restart);
2743 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2744 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2745 out + 6, outsize + 6, svg_p->restart);
2747 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2748 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2749 out + 7, outsize + 7, svg_p->restart);
2751 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2752 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2753 out + 8, outsize + 8, svg_p->restart);
2755 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2756 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2757 out + 9, outsize + 9, svg_p->restart);
2759 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2760 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2761 out + 10, outsize + 10, svg_p->restart);
2764 if (action & F_END) {
2765 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2766 spmin, spmax, out, outsize, svg_p, record_hdr);
2768 /* Free remaining structures */
2769 free_graphs(out, outsize, spmin, spmax);
2774 ***************************************************************************
2775 * Display network socket statistics in SVG.
2778 * @a Activity structure with statistics.
2779 * @curr Index in array for current sample statistics.
2780 * @action Action expected from current function.
2781 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2782 * flag indicating that a restart record has been previously
2783 * found (.@restart) and time used for the X axis origin
2785 * @itv Interval of time in jiffies (only with F_MAIN action).
2786 * @record_hdr Pointer on record header of current stats sample.
2787 ***************************************************************************
2789 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2790 unsigned long long itv, struct record_header *record_hdr)
2792 struct stats_net_sock
2793 *snsc = (struct stats_net_sock *) a->buf[curr];
2794 int group[] = {1, 5};
2795 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2796 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2797 char *g_title[] = {"~totsck",
2798 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2799 int g_fields[] = {0, 1, 5, 2, 3, 4};
2800 static double *spmin, *spmax;
2802 static int *outsize;
2804 if (action & F_BEGIN) {
2806 * Allocate arrays that will contain the graphs data
2807 * and the min/max values.
2809 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2812 if (action & F_MAIN) {
2813 /* Check for min/max values */
2814 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2815 itv, spmin, spmax, g_fields);
2817 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2818 (unsigned long) snsc->sock_inuse,
2819 out, outsize, svg_p->restart);
2821 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2822 (unsigned long) snsc->tcp_inuse,
2823 out + 1, outsize + 1, svg_p->restart);
2825 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2826 (unsigned long) snsc->udp_inuse,
2827 out + 2, outsize + 2, svg_p->restart);
2829 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2830 (unsigned long) snsc->raw_inuse,
2831 out + 3, outsize + 3, svg_p->restart);
2833 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2834 (unsigned long) snsc->frag_inuse,
2835 out + 4, outsize + 4, svg_p->restart);
2837 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2838 (unsigned long) snsc->tcp_tw,
2839 out + 5, outsize + 5, svg_p->restart);
2842 if (action & F_END) {
2843 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2844 spmin, spmax, out, outsize, svg_p, record_hdr);
2846 /* Free remaining structures */
2847 free_graphs(out, outsize, spmin, spmax);
2852 ***************************************************************************
2853 * Display IPv4 network statistics in SVG.
2856 * @a Activity structure with statistics.
2857 * @curr Index in array for current sample statistics.
2858 * @action Action expected from current function.
2859 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2860 * flag indicating that a restart record has been previously
2861 * found (.@restart) and time used for the X axis origin
2863 * @itv Interval of time in jiffies (only with F_MAIN action).
2864 * @record_hdr Pointer on record header of current stats sample.
2865 ***************************************************************************
2867 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2868 unsigned long long itv, struct record_header *record_hdr)
2871 *snic = (struct stats_net_ip *) a->buf[curr],
2872 *snip = (struct stats_net_ip *) a->buf[!curr];
2873 int group[] = {4, 2, 2};
2874 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2875 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2876 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2877 "asmrq/s", "asmok/s",
2878 "fragok/s", "fragcrt/s"};
2879 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2880 static double *spmin, *spmax;
2882 static int *outsize;
2884 if (action & F_BEGIN) {
2886 * Allocate arrays that will contain the graphs data
2887 * and the min/max values.
2889 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2892 if (action & F_MAIN) {
2893 /* Check for min/max values */
2894 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2895 itv, spmin, spmax, g_fields);
2898 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2899 S_VALUE(snip->InReceives, snic->InReceives, itv),
2900 out, outsize, svg_p->restart);
2902 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2903 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2904 out + 1, outsize + 1, svg_p->restart);
2906 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2907 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2908 out + 2, outsize + 2, svg_p->restart);
2910 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2911 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2912 out + 3, outsize + 3, svg_p->restart);
2914 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2915 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2916 out + 4, outsize + 4, svg_p->restart);
2918 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2919 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2920 out + 5, outsize + 5, svg_p->restart);
2922 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2923 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2924 out + 6, outsize + 6, svg_p->restart);
2926 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2927 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2928 out + 7, outsize + 7, svg_p->restart);
2931 if (action & F_END) {
2932 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2933 spmin, spmax, out, outsize, svg_p, record_hdr);
2935 /* Free remaining structures */
2936 free_graphs(out, outsize, spmin, spmax);
2941 ***************************************************************************
2942 * Display IPv4 network errors statistics in SVG.
2945 * @a Activity structure with statistics.
2946 * @curr Index in array for current sample statistics.
2947 * @action Action expected from current function.
2948 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2949 * flag indicating that a restart record has been previously
2950 * found (.@restart) and time used for the X axis origin
2952 * @itv Interval of time in jiffies (only with F_MAIN action).
2953 * @record_hdr Pointer on record header of current stats sample.
2954 ***************************************************************************
2956 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2957 unsigned long long itv, struct record_header *record_hdr)
2959 struct stats_net_eip
2960 *sneic = (struct stats_net_eip *) a->buf[curr],
2961 *sneip = (struct stats_net_eip *) a->buf[!curr];
2962 int group[] = {3, 2, 3};
2963 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2964 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
2965 "IPv4 network errors statistics (3)"};
2966 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
2967 "idisc/s", "odisc/s",
2968 "onort/s", "asmf/s", "fragf/s"};
2969 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2970 static double *spmin, *spmax;
2972 static int *outsize;
2974 if (action & F_BEGIN) {
2976 * Allocate arrays that will contain the graphs data
2977 * and the min/max values.
2979 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2982 if (action & F_MAIN) {
2983 /* Check for min/max values */
2984 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2985 itv, spmin, spmax, g_fields);
2988 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2989 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
2990 out, outsize, svg_p->restart);
2992 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2993 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
2994 out + 1, outsize + 1, svg_p->restart);
2996 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2997 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
2998 out + 2, outsize + 2, svg_p->restart);
3000 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3001 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3002 out + 3, outsize + 3, svg_p->restart);
3004 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3005 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3006 out + 4, outsize + 4, svg_p->restart);
3008 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3009 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3010 out + 5, outsize + 5, svg_p->restart);
3012 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3013 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3014 out + 6, outsize + 6, svg_p->restart);
3016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3017 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3018 out + 7, outsize + 7, svg_p->restart);
3021 if (action & F_END) {
3022 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3023 spmin, spmax, out, outsize, svg_p, record_hdr);
3025 /* Free remaining structures */
3026 free_graphs(out, outsize, spmin, spmax);
3031 ***************************************************************************
3032 * Display ICMPv4 network statistics in SVG.
3035 * @a Activity structure with statistics.
3036 * @curr Index in array for current sample statistics.
3037 * @action Action expected from current function.
3038 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3039 * flag indicating that a restart record has been previously
3040 * found (.@restart) and time used for the X axis origin
3042 * @itv Interval of time in jiffies (only with F_MAIN action).
3043 * @record_hdr Pointer on record header of current stats sample.
3044 ***************************************************************************
3046 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3047 unsigned long long itv, struct record_header *record_hdr)
3049 struct stats_net_icmp
3050 *snic = (struct stats_net_icmp *) a->buf[curr],
3051 *snip = (struct stats_net_icmp *) a->buf[!curr];
3052 int group[] = {2, 4, 4, 4};
3053 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3055 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3056 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3057 char *g_title[] = {"imsg/s", "omsg/s",
3058 "iech/s", "iechr/s", "oech/s", "oechr/s",
3059 "itm/s", "itmr/s", "otm/s", "otmr/s",
3060 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3061 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3062 static double *spmin, *spmax;
3064 static int *outsize;
3066 if (action & F_BEGIN) {
3068 * Allocate arrays that will contain the graphs data
3069 * and the min/max values.
3071 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3074 if (action & F_MAIN) {
3075 /* Check for min/max values */
3076 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3077 itv, spmin, spmax, g_fields);
3080 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3081 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3082 out, outsize, svg_p->restart);
3084 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3085 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3086 out + 1, outsize + 1, svg_p->restart);
3088 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3089 S_VALUE(snip->InEchos, snic->InEchos, itv),
3090 out + 2, outsize + 2, svg_p->restart);
3092 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3093 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3094 out + 3, outsize + 3, svg_p->restart);
3096 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3097 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3098 out + 4, outsize + 4, svg_p->restart);
3100 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3101 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3102 out + 5, outsize + 5, svg_p->restart);
3104 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3105 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3106 out + 6, outsize + 6, svg_p->restart);
3108 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3109 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3110 out + 7, outsize + 7, svg_p->restart);
3112 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3113 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3114 out + 8, outsize + 8, svg_p->restart);
3116 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3117 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3118 out + 9, outsize + 9, svg_p->restart);
3120 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3121 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3122 out + 10, outsize + 10, svg_p->restart);
3124 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3125 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3126 out + 11, outsize + 11, svg_p->restart);
3128 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3129 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3130 out + 12, outsize + 12, svg_p->restart);
3132 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3133 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3134 out + 13, outsize + 13, svg_p->restart);
3137 if (action & F_END) {
3138 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3139 spmin, spmax, out, outsize, svg_p, record_hdr);
3141 /* Free remaining structures */
3142 free_graphs(out, outsize, spmin, spmax);
3147 ***************************************************************************
3148 * Display ICMPv4 network errors statistics in SVG.
3151 * @a Activity structure with statistics.
3152 * @curr Index in array for current sample statistics.
3153 * @action Action expected from current function.
3154 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3155 * flag indicating that a restart record has been previously
3156 * found (.@restart) and time used for the X axis origin
3158 * @itv Interval of time in jiffies (only with F_MAIN action).
3159 * @record_hdr Pointer on record header of current stats sample.
3160 ***************************************************************************
3162 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3163 unsigned long long itv, struct record_header *record_hdr)
3165 struct stats_net_eicmp
3166 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3167 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3168 int group[] = {2, 2, 2, 2, 2, 2};
3169 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3170 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3171 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3172 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3173 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3174 char *g_title[] = {"ierr/s", "oerr/s",
3175 "idstunr/s", "odstunr/s",
3176 "itmex/s", "otmex/s",
3177 "iparmpb/s", "oparmpb/s",
3178 "isrcq/s", "osrcq/s",
3179 "iredir/s", "oredir/s"};
3180 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3181 static double *spmin, *spmax;
3183 static int *outsize;
3185 if (action & F_BEGIN) {
3187 * Allocate arrays that will contain the graphs data
3188 * and the min/max values.
3190 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3193 if (action & F_MAIN) {
3194 /* Check for min/max values */
3195 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3196 itv, spmin, spmax, g_fields);
3199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3200 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3201 out, outsize, svg_p->restart);
3203 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3204 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3205 out + 1, outsize + 1, svg_p->restart);
3207 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3208 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3209 out + 2, outsize + 2, svg_p->restart);
3211 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3212 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3213 out + 3, outsize + 3, svg_p->restart);
3215 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3216 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3217 out + 4, outsize + 4, svg_p->restart);
3219 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3220 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3221 out + 5, outsize + 5, svg_p->restart);
3223 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3224 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3225 out + 6, outsize + 6, svg_p->restart);
3227 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3228 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3229 out + 7, outsize + 7, svg_p->restart);
3231 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3232 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3233 out + 8, outsize + 8, svg_p->restart);
3235 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3236 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3237 out + 9, outsize + 9, svg_p->restart);
3239 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3240 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3241 out + 10, outsize + 10, svg_p->restart);
3243 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3244 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3245 out + 11, outsize + 11, svg_p->restart);
3248 if (action & F_END) {
3249 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3250 spmin, spmax, out, outsize, svg_p, record_hdr);
3252 /* Free remaining structures */
3253 free_graphs(out, outsize, spmin, spmax);
3258 ***************************************************************************
3259 * Display TCPv4 network statistics in SVG.
3262 * @a Activity structure with statistics.
3263 * @curr Index in array for current sample statistics.
3264 * @action Action expected from current function.
3265 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3266 * flag indicating that a restart record has been previously
3267 * found (.@restart) and time used for the X axis origin
3269 * @itv Interval of time in jiffies (only with F_MAIN action).
3270 * @record_hdr Pointer on record header of current stats sample.
3271 ***************************************************************************
3273 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3274 unsigned long long itv, struct record_header *record_hdr)
3276 struct stats_net_tcp
3277 *sntc = (struct stats_net_tcp *) a->buf[curr],
3278 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3279 int group[] = {2, 2};
3280 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3281 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3282 char *g_title[] = {"active/s", "passive/s",
3283 "iseg/s", "oseg/s"};
3284 int g_fields[] = {0, 1, 2, 3};
3285 static double *spmin, *spmax;
3287 static int *outsize;
3289 if (action & F_BEGIN) {
3291 * Allocate arrays that will contain the graphs data
3292 * and the min/max values.
3294 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3297 if (action & F_MAIN) {
3298 /* Check for min/max values */
3299 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3300 itv, spmin, spmax, g_fields);
3303 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3304 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3305 out, outsize, svg_p->restart);
3307 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3308 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3309 out + 1, outsize + 1, svg_p->restart);
3311 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3312 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3313 out + 2, outsize + 2, svg_p->restart);
3315 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3316 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3317 out + 3, outsize + 3, svg_p->restart);
3320 if (action & F_END) {
3321 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3322 spmin, spmax, out, outsize, svg_p, record_hdr);
3324 /* Free remaining structures */
3325 free_graphs(out, outsize, spmin, spmax);
3330 ***************************************************************************
3331 * Display TCPv4 network errors statistics in SVG.
3334 * @a Activity structure with statistics.
3335 * @curr Index in array for current sample statistics.
3336 * @action Action expected from current function.
3337 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3338 * flag indicating that a restart record has been previously
3339 * found (.@restart) and time used for the X axis origin
3341 * @itv Interval of time in jiffies (only with F_MAIN action).
3342 * @record_hdr Pointer on record header of current stats sample.
3343 ***************************************************************************
3345 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3346 unsigned long long itv, struct record_header *record_hdr)
3348 struct stats_net_etcp
3349 *snetc = (struct stats_net_etcp *) a->buf[curr],
3350 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3351 int group[] = {2, 3};
3352 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3353 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3354 char *g_title[] = {"atmptf/s", "estres/s",
3355 "retrans/s", "isegerr/s", "orsts/s"};
3356 int g_fields[] = {0, 1, 2, 3, 4};
3357 static double *spmin, *spmax;
3359 static int *outsize;
3361 if (action & F_BEGIN) {
3363 * Allocate arrays that will contain the graphs data
3364 * and the min/max values.
3366 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3369 if (action & F_MAIN) {
3370 /* Check for min/max values */
3371 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3372 itv, spmin, spmax, g_fields);
3375 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3376 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3377 out, outsize, svg_p->restart);
3379 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3380 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3381 out + 1, outsize + 1, svg_p->restart);
3383 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3384 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3385 out + 2, outsize + 2, svg_p->restart);
3387 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3388 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3389 out + 3, outsize + 3, svg_p->restart);
3391 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3392 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3393 out + 4, outsize + 4, svg_p->restart);
3396 if (action & F_END) {
3397 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3398 spmin, spmax, out, outsize, svg_p, record_hdr);
3400 /* Free remaining structures */
3401 free_graphs(out, outsize, spmin, spmax);
3406 ***************************************************************************
3407 * Display UDPv4 network statistics in SVG.
3410 * @a Activity structure with statistics.
3411 * @curr Index in array for current sample statistics.
3412 * @action Action expected from current function.
3413 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3414 * flag indicating that a restart record has been previously
3415 * found (.@restart) and time used for the X axis origin
3417 * @itv Interval of time in jiffies (only with F_MAIN action).
3418 * @record_hdr Pointer on record header of current stats sample.
3419 ***************************************************************************
3421 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3422 unsigned long long itv, struct record_header *record_hdr)
3424 struct stats_net_udp
3425 *snuc = (struct stats_net_udp *) a->buf[curr],
3426 *snup = (struct stats_net_udp *) a->buf[!curr];
3427 int group[] = {2, 2};
3428 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3429 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3430 char *g_title[] = {"idgm/s", "odgm/s",
3431 "noport/s", "idgmerr/s"};
3432 int g_fields[] = {0, 1, 2, 3};
3433 static double *spmin, *spmax;
3435 static int *outsize;
3437 if (action & F_BEGIN) {
3439 * Allocate arrays that will contain the graphs data
3440 * and the min/max values.
3442 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3445 if (action & F_MAIN) {
3446 /* Check for min/max values */
3447 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3448 itv, spmin, spmax, g_fields);
3451 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3452 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3453 out, outsize, svg_p->restart);
3455 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3456 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3457 out + 1, outsize + 1, svg_p->restart);
3459 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3460 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3461 out + 2, outsize + 2, svg_p->restart);
3463 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3464 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3465 out + 3, outsize + 3, svg_p->restart);
3468 if (action & F_END) {
3469 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3470 spmin, spmax, out, outsize, svg_p, record_hdr);
3472 /* Free remaining structures */
3473 free_graphs(out, outsize, spmin, spmax);
3478 ***************************************************************************
3479 * Display IPV6 network socket statistics in SVG.
3482 * @a Activity structure with statistics.
3483 * @curr Index in array for current sample statistics.
3484 * @action Action expected from current function.
3485 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3486 * flag indicating that a restart record has been previously
3487 * found (.@restart) and time used for the X axis origin
3489 * @itv Interval of time in jiffies (only with F_MAIN action).
3490 * @record_hdr Pointer on record header of current stats sample.
3491 ***************************************************************************
3493 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3494 unsigned long long itv, struct record_header *record_hdr)
3496 struct stats_net_sock6
3497 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3499 int g_type[] = {SVG_LINE_GRAPH};
3500 char *title[] = {"IPv6 network sockets"};
3501 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3502 int g_fields[] = {0, 1, 2, 3};
3503 static double *spmin, *spmax;
3505 static int *outsize;
3507 if (action & F_BEGIN) {
3509 * Allocate arrays that will contain the graphs data
3510 * and the min/max values.
3512 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3515 if (action & F_MAIN) {
3516 /* Check for min/max values */
3517 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3518 itv, spmin, spmax, g_fields);
3520 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3521 (unsigned long) snsc->tcp6_inuse,
3522 out, outsize, svg_p->restart);
3524 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3525 (unsigned long) snsc->udp6_inuse,
3526 out + 1, outsize + 1, svg_p->restart);
3528 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3529 (unsigned long) snsc->raw6_inuse,
3530 out + 2, outsize + 2, svg_p->restart);
3532 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3533 (unsigned long) snsc->frag6_inuse,
3534 out + 3, outsize + 3, svg_p->restart);
3537 if (action & F_END) {
3538 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3539 spmin, spmax, out, outsize, svg_p, record_hdr);
3541 /* Free remaining structures */
3542 free_graphs(out, outsize, spmin, spmax);
3547 ***************************************************************************
3548 * Display IPv6 network statistics in SVG.
3551 * @a Activity structure with statistics.
3552 * @curr Index in array for current sample statistics.
3553 * @action Action expected from current function.
3554 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3555 * flag indicating that a restart record has been previously
3556 * found (.@restart) and time used for the X axis origin
3558 * @itv Interval of time in jiffies (only with F_MAIN action).
3559 * @record_hdr Pointer on record header of current stats sample.
3560 ***************************************************************************
3562 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3563 unsigned long long itv, struct record_header *record_hdr)
3565 struct stats_net_ip6
3566 *snic = (struct stats_net_ip6 *) a->buf[curr],
3567 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3568 int group[] = {4, 2, 2, 2};
3569 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3571 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3572 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3573 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3574 "asmrq6/s", "asmok6/s",
3575 "imcpck6/s", "omcpck6/s",
3576 "fragok6/s", "fragcr6/s"};
3577 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3578 static double *spmin, *spmax;
3580 static int *outsize;
3582 if (action & F_BEGIN) {
3584 * Allocate arrays that will contain the graphs data
3585 * and the min/max values.
3587 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3590 if (action & F_MAIN) {
3591 /* Check for min/max values */
3592 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3593 itv, spmin, spmax, g_fields);
3596 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3597 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3598 out, outsize, svg_p->restart);
3600 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3601 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3602 out + 1, outsize + 1, svg_p->restart);
3604 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3605 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3606 out + 2, outsize + 2, svg_p->restart);
3608 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3609 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3610 out + 3, outsize + 3, svg_p->restart);
3612 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3613 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3614 out + 4, outsize + 4, svg_p->restart);
3616 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3617 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3618 out + 5, outsize + 5, svg_p->restart);
3620 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3621 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3622 out + 6, outsize + 6, svg_p->restart);
3624 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3625 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3626 out + 7, outsize + 7, svg_p->restart);
3628 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3629 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3630 out + 8, outsize + 8, svg_p->restart);
3632 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3633 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3634 out + 9, outsize + 9, svg_p->restart);
3637 if (action & F_END) {
3638 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3639 spmin, spmax, out, outsize, svg_p, record_hdr);
3641 /* Free remaining structures */
3642 free_graphs(out, outsize, spmin, spmax);
3647 ***************************************************************************
3648 * Display IPv6 network errors statistics in SVG.
3651 * @a Activity structure with statistics.
3652 * @curr Index in array for current sample statistics.
3653 * @action Action expected from current function.
3654 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3655 * flag indicating that a restart record has been previously
3656 * found (.@restart) and time used for the X axis origin
3658 * @itv Interval of time in jiffies (only with F_MAIN action).
3659 * @record_hdr Pointer on record header of current stats sample.
3660 ***************************************************************************
3662 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3663 unsigned long long itv, struct record_header *record_hdr)
3665 struct stats_net_eip6
3666 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3667 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3668 int group[] = {4, 2, 2, 3};
3669 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3671 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3672 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3673 "IPv6 network errors statistics (5)"};
3674 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3675 "idisc6/s", "odisc6/s",
3676 "inort6/s", "onort6/s",
3677 "asmf6/s", "fragf6/s", "itrpck6/s"};
3678 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3679 static double *spmin, *spmax;
3681 static int *outsize;
3683 if (action & F_BEGIN) {
3685 * Allocate arrays that will contain the graphs data
3686 * and the min/max values.
3688 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3691 if (action & F_MAIN) {
3692 /* Check for min/max values */
3693 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3694 itv, spmin, spmax, g_fields);
3697 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3698 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3699 out, outsize, svg_p->restart);
3701 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3702 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3703 out + 1, outsize + 1, svg_p->restart);
3705 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3706 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3707 out + 2, outsize + 2, svg_p->restart);
3709 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3710 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3711 out + 3, outsize + 3, svg_p->restart);
3713 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3714 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3715 out + 4, outsize + 4, svg_p->restart);
3717 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3718 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3719 out + 5, outsize + 5, svg_p->restart);
3721 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3722 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3723 out + 6, outsize + 6, svg_p->restart);
3725 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3726 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3727 out + 7, outsize + 7, svg_p->restart);
3729 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3730 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3731 out + 8, outsize + 8, svg_p->restart);
3733 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3734 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3735 out + 9, outsize + 9, svg_p->restart);
3737 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3738 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3739 out + 10, outsize + 10, svg_p->restart);
3742 if (action & F_END) {
3743 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3744 spmin, spmax, out, outsize, svg_p, record_hdr);
3746 /* Free remaining structures */
3747 free_graphs(out, outsize, spmin, spmax);
3752 ***************************************************************************
3753 * Display ICMPv6 network statistics in SVG.
3756 * @a Activity structure with statistics.
3757 * @curr Index in array for current sample statistics.
3758 * @action Action expected from current function.
3759 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3760 * flag indicating that a restart record has been previously
3761 * found (.@restart) and time used for the X axis origin
3763 * @itv Interval of time in jiffies (only with F_MAIN action).
3764 * @record_hdr Pointer on record header of current stats sample.
3765 ***************************************************************************
3767 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3768 unsigned long long itv, struct record_header *record_hdr)
3770 struct stats_net_icmp6
3771 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3772 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3773 int group[] = {2, 3, 5, 3, 4};
3774 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3775 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3776 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3777 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3778 "ICMPv6 network statistics (5)"};
3779 char *g_title[] = {"imsg6/s", "omsg6/s",
3780 "iech6/s", "iechr6/s", "oechr6/s",
3781 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3782 "irtsol6/s", "ortsol6/s", "irtad6/s",
3783 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3784 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3785 static double *spmin, *spmax;
3787 static int *outsize;
3789 if (action & F_BEGIN) {
3791 * Allocate arrays that will contain the graphs data
3792 * and the min/max values.
3794 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3797 if (action & F_MAIN) {
3798 /* Check for min/max values */
3799 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3800 itv, spmin, spmax, g_fields);
3803 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3804 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3805 out, outsize, svg_p->restart);
3807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3808 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3809 out + 1, outsize + 1, svg_p->restart);
3811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3812 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3813 out + 2, outsize + 2, svg_p->restart);
3815 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3816 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3817 out + 3, outsize + 3, svg_p->restart);
3819 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3820 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3821 out + 4, outsize + 4, svg_p->restart);
3823 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3824 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3825 out + 5, outsize + 5, svg_p->restart);
3827 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3828 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3829 out + 6, outsize + 6, svg_p->restart);
3831 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3832 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3833 out + 7, outsize + 7, svg_p->restart);
3835 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3836 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3837 out + 8, outsize + 8, svg_p->restart);
3839 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3840 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3841 out + 9, outsize + 9, svg_p->restart);
3843 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3844 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3845 out + 10, outsize + 10, svg_p->restart);
3847 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3848 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3849 out + 11, outsize + 11, svg_p->restart);
3851 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3852 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3853 out + 12, outsize + 12, svg_p->restart);
3855 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3856 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3857 out + 13, outsize + 13, svg_p->restart);
3859 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3860 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3861 out + 14, outsize + 14, svg_p->restart);
3863 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3864 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3865 out + 15, outsize + 15, svg_p->restart);
3867 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3868 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3869 out + 16, outsize + 16, svg_p->restart);
3872 if (action & F_END) {
3873 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3874 spmin, spmax, out, outsize, svg_p, record_hdr);
3876 /* Free remaining structures */
3877 free_graphs(out, outsize, spmin, spmax);
3882 ***************************************************************************
3883 * Display ICMPv6 network errors statistics in SVG.
3886 * @a Activity structure with statistics.
3887 * @curr Index in array for current sample statistics.
3888 * @action Action expected from current function.
3889 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3890 * flag indicating that a restart record has been previously
3891 * found (.@restart) and time used for the X axis origin
3893 * @itv Interval of time in jiffies (only with F_MAIN action).
3894 * @record_hdr Pointer on record header of current stats sample.
3895 ***************************************************************************
3897 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3898 unsigned long long itv, struct record_header *record_hdr)
3900 struct stats_net_eicmp6
3901 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3902 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3903 int group[] = {1, 2, 2, 2, 2, 2};
3904 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3905 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3906 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3907 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3908 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3909 char *g_title[] = {"ierr6/s",
3910 "idtunr6/s", "odtunr6/s",
3911 "itmex6/s", "otmex6/s",
3912 "iprmpb6/s", "oprmpb6/s",
3913 "iredir6/s", "oredir6/s",
3914 "ipck2b6/s", "opck2b6/s"};
3915 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3916 static double *spmin, *spmax;
3918 static int *outsize;
3920 if (action & F_BEGIN) {
3922 * Allocate arrays that will contain the graphs data
3923 * and the min/max values.
3925 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3928 if (action & F_MAIN) {
3929 /* Check for min/max values */
3930 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3931 itv, spmin, spmax, g_fields);
3934 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3935 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
3936 out, outsize, svg_p->restart);
3938 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3939 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
3940 out + 1, outsize + 1, svg_p->restart);
3942 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3943 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
3944 out + 2, outsize + 2, svg_p->restart);
3946 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3947 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
3948 out + 3, outsize + 3, svg_p->restart);
3950 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3951 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
3952 out + 4, outsize + 4, svg_p->restart);
3954 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3955 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
3956 out + 5, outsize + 5, svg_p->restart);
3958 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3959 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
3960 out + 6, outsize + 6, svg_p->restart);
3962 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3963 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
3964 out + 7, outsize + 7, svg_p->restart);
3966 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3967 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
3968 out + 8, outsize + 8, svg_p->restart);
3970 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3971 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
3972 out + 9, outsize + 9, svg_p->restart);
3974 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3975 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
3976 out + 10, outsize + 10, svg_p->restart);
3979 if (action & F_END) {
3980 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3981 spmin, spmax, out, outsize, svg_p, record_hdr);
3983 /* Free remaining structures */
3984 free_graphs(out, outsize, spmin, spmax);
3989 ***************************************************************************
3990 * Display UDPv6 network statistics in SVG.
3993 * @a Activity structure with statistics.
3994 * @curr Index in array for current sample statistics.
3995 * @action Action expected from current function.
3996 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3997 * flag indicating that a restart record has been previously
3998 * found (.@restart) and time used for the X axis origin
4000 * @itv Interval of time in jiffies (only with F_MAIN action).
4001 * @record_hdr Pointer on record header of current stats sample.
4002 ***************************************************************************
4004 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4005 unsigned long long itv, struct record_header *record_hdr)
4007 struct stats_net_udp6
4008 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4009 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4010 int group[] = {2, 2};
4011 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4012 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
4013 char *g_title[] = {"idgm6/s", "odgm6/s",
4014 "noport6/s", "idgmer6/s"};
4015 int g_fields[] = {0, 1, 2, 3};
4016 static double *spmin, *spmax;
4018 static int *outsize;
4020 if (action & F_BEGIN) {
4022 * Allocate arrays that will contain the graphs data
4023 * and the min/max values.
4025 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4028 if (action & F_MAIN) {
4029 /* Check for min/max values */
4030 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4031 itv, spmin, spmax, g_fields);
4034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4035 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4036 out, outsize, svg_p->restart);
4038 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4039 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4040 out + 1, outsize + 1, svg_p->restart);
4042 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4043 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4044 out + 2, outsize + 2, svg_p->restart);
4046 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4047 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4048 out + 3, outsize + 3, svg_p->restart);
4051 if (action & F_END) {
4052 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4053 spmin, spmax, out, outsize, svg_p, record_hdr);
4055 /* Free remaining structures */
4056 free_graphs(out, outsize, spmin, spmax);
4061 ***************************************************************************
4062 * Display CPU frequency statistics in SVG.
4065 * @a Activity structure with statistics.
4066 * @curr Index in array for current sample statistics.
4067 * @action Action expected from current function.
4068 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4069 * flag indicating that a restart record has been previously
4070 * found (.@restart) and time used for the X axis origin
4072 * @itv Interval of time in jiffies (unused here).
4073 * @record_hdr Pointer on record header of current stats sample.
4074 ***************************************************************************
4076 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4077 unsigned long long itv, struct record_header *record_hdr)
4079 struct stats_pwr_cpufreq *spc, *spp;
4081 int g_type[] = {SVG_LINE_GRAPH};
4082 char *title[] = {"CPU frequency"};
4083 char *g_title[] = {"MHz"};
4084 static double *spmin, *spmax;
4086 static int *outsize;
4090 if (action & F_BEGIN) {
4092 * Allocate arrays that will contain the graphs data
4093 * and the min/max values.
4095 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4098 if (action & F_MAIN) {
4100 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4102 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4103 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4105 /* Should current CPU (including CPU "all") be displayed? */
4106 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4111 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4112 ((double) spp->cpufreq) / 100,
4113 ((double) spc->cpufreq) / 100,
4114 out + i, outsize + i, svg_p->restart, svg_p->dt,
4115 spmin + i, spmax + i);
4119 if (action & F_END) {
4120 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4122 /* Should current CPU (including CPU "all") be displayed? */
4123 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4128 /* This is CPU "all" */
4129 strcpy(item_name, "all");
4132 sprintf(item_name, "%d", i - 1);
4135 draw_activity_graphs(a->g_nr, g_type,
4136 title, g_title, item_name, group,
4137 spmin + i, spmax + i, out + i, outsize + i,
4141 /* Free remaining structures */
4142 free_graphs(out, outsize, spmin, spmax);
4147 ***************************************************************************
4148 * Display fan statistics in SVG.
4151 * @a Activity structure with statistics.
4152 * @curr Index in array for current sample statistics.
4153 * @action Action expected from current function.
4154 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4155 * flag indicating that a restart record has been previously
4156 * found (.@restart) and time used for the X axis origin
4158 * @itv Interval of time in jiffies (unused here).
4159 * @record_hdr Pointer on record header of current stats sample.
4160 ***************************************************************************
4162 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4163 unsigned long long itv, struct record_header *record_hdr)
4165 struct stats_pwr_fan *spc, *spp;
4167 int g_type[] = {SVG_LINE_GRAPH};
4168 char *title[] = {"Fan speed"};
4169 char *g_title[] = {"~rpm"};
4170 static double *spmin, *spmax;
4172 static int *outsize;
4173 char item_name[MAX_SENSORS_DEV_LEN + 8];
4176 if (action & F_BEGIN) {
4178 * Allocate arrays that will contain the graphs data
4179 * and the min/max values.
4181 out = allocate_graph_lines(a->nr, &outsize, &spmin, &spmax);
4184 if (action & F_MAIN) {
4186 for (i = 0; i < a->nr; i++) {
4188 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4189 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4192 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4195 out + i, outsize + i, svg_p->restart, svg_p->dt,
4196 spmin + i, spmax + i);
4200 if (action & F_END) {
4201 for (i = 0; i < a->nr; i++) {
4203 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4205 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4206 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4208 draw_activity_graphs(a->g_nr, g_type,
4209 title, g_title, item_name, group,
4210 spmin + i, spmax + i, out + i, outsize + i,
4214 /* Free remaining structures */
4215 free_graphs(out, outsize, spmin, spmax);
4220 ***************************************************************************
4221 * Display temperature statistics in SVG.
4224 * @a Activity structure with statistics.
4225 * @curr Index in array for current sample statistics.
4226 * @action Action expected from current function.
4227 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4228 * flag indicating that a restart record has been previously
4229 * found (.@restart) and time used for the X axis origin
4231 * @itv Interval of time in jiffies (unused here).
4232 * @record_hdr Pointer on record header of current stats sample.
4233 ***************************************************************************
4235 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4236 unsigned long long itv, struct record_header *record_hdr)
4238 struct stats_pwr_temp *spc;
4239 int group[] = {1, 1};
4240 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4241 char *title[] = {"Device temperature (1)",
4242 "Device temperature (2)"};
4243 char *g_title[] = {"~degC",
4245 static double *spmin, *spmax;
4247 static int *outsize;
4248 char item_name[MAX_SENSORS_DEV_LEN + 8];
4252 if (action & F_BEGIN) {
4254 * Allocate arrays that will contain the graphs data
4255 * and the min/max values.
4257 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4260 if (action & F_MAIN) {
4261 /* For each temperature sensor */
4262 for (i = 0; i < a->nr; i++) {
4264 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4266 /* Look for min/max values */
4267 if (spc->temp < *(spmin + 2 * i)) {
4268 *(spmin + 2 * i) = spc->temp;
4270 if (spc->temp > *(spmax + 2 * i)) {
4271 *(spmax + 2 * i) = spc->temp;
4273 tval = (spc->temp_max - spc->temp_min) ?
4274 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4276 if (tval < *(spmin + 2 * i + 1)) {
4277 *(spmin + 2 * i + 1) = tval;
4279 if (tval > *(spmax + 2 * i + 1)) {
4280 *(spmax + 2 * i + 1) = tval;
4284 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4286 out + 2 * i, outsize + 2 * i, svg_p->restart);
4288 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4290 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4294 if (action & F_END) {
4295 for (i = 0; i < a->nr; i++) {
4297 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4299 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4300 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4302 draw_activity_graphs(a->g_nr, g_type,
4303 title, g_title, item_name, group,
4304 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4308 /* Free remaining structures */
4309 free_graphs(out, outsize, spmin, spmax);
4314 ***************************************************************************
4315 * Display voltage inputs statistics in SVG.
4318 * @a Activity structure with statistics.
4319 * @curr Index in array for current sample statistics.
4320 * @action Action expected from current function.
4321 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4322 * flag indicating that a restart record has been previously
4323 * found (.@restart) and time used for the X axis origin
4325 * @itv Interval of time in jiffies (only with F_MAIN action).
4326 * @record_hdr Pointer on record header of current stats sample.
4327 ***************************************************************************
4329 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4330 unsigned long long itv, struct record_header *record_hdr)
4332 struct stats_pwr_in *spc;
4333 int group[] = {1, 1};
4334 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4335 char *title[] = {"Voltage inputs (1)",
4336 "Voltage inputs (2)"};
4337 char *g_title[] = {"inV",
4339 static double *spmin, *spmax;
4341 static int *outsize;
4342 char item_name[MAX_SENSORS_DEV_LEN + 8];
4346 if (action & F_BEGIN) {
4348 * Allocate arrays that will contain the graphs data
4349 * and the min/max values.
4351 out = allocate_graph_lines(2 * a->nr, &outsize, &spmin, &spmax);
4354 if (action & F_MAIN) {
4355 /* For each temperature sensor */
4356 for (i = 0; i < a->nr; i++) {
4358 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4360 /* Look for min/max values */
4361 if (spc->in < *(spmin + 2 * i)) {
4362 *(spmin + 2 * i) = spc->in;
4364 if (spc->in > *(spmax + 2 * i)) {
4365 *(spmax + 2 * i) = spc->in;
4367 tval = (spc->in_max - spc->in_min) ?
4368 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4370 if (tval < *(spmin + 2 * i + 1)) {
4371 *(spmin + 2 * i + 1) = tval;
4373 if (tval > *(spmax + 2 * i + 1)) {
4374 *(spmax + 2 * i + 1) = tval;
4378 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4380 out + 2 * i, outsize + 2 * i, svg_p->restart);
4382 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4384 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4388 if (action & F_END) {
4389 for (i = 0; i < a->nr; i++) {
4391 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4393 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4394 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4396 draw_activity_graphs(a->g_nr, g_type,
4397 title, g_title, item_name, group,
4398 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4402 /* Free remaining structures */
4403 free_graphs(out, outsize, spmin, spmax);
4408 ***************************************************************************
4409 * Display huge pages statistics in SVG.
4412 * @a Activity structure with statistics.
4413 * @curr Index in array for current sample statistics.
4414 * @action Action expected from current function.
4415 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4416 * flag indicating that a restart record has been previously
4417 * found (.@restart) and time used for the X axis origin
4419 * @itv Interval of time in jiffies (only with F_MAIN action).
4420 * @record_hdr Pointer on record header of current stats sample.
4421 ***************************************************************************
4423 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4424 unsigned long long itv, struct record_header *record_hdr)
4427 *smc = (struct stats_huge *) a->buf[curr];
4428 int group[] = {2, 1};
4429 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4430 char *title[] = {"Huge pages utilization (1)",
4431 "Huge pages utilization (2)"};
4432 char *g_title[] = {"~kbhugfree", "~kbhugused",
4434 int g_fields[] = {0};
4435 unsigned int local_types_nr[] = {0, 1, 0};
4436 static double *spmin, *spmax;
4438 static int *outsize;
4441 if (action & F_BEGIN) {
4443 * Allocate arrays that will contain the graphs data
4444 * and the min/max values.
4446 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4449 if (action & F_MAIN) {
4450 /* Check for min/max values */
4451 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4452 itv, spmin, spmax, g_fields);
4454 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4455 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4457 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4458 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4460 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4461 if (tval < *(spmin + 2)) {
4462 *(spmin + 2) = tval;
4464 if (tval > *(spmax + 2)) {
4465 *(spmax + 2) = tval;
4469 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4470 (unsigned long) smc->frhkb,
4471 out, outsize, svg_p->restart);
4473 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4474 (unsigned long) smc->tlhkb - smc->frhkb,
4475 out + 1, outsize + 1, svg_p->restart);
4477 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4479 out + 2, outsize + 2, svg_p->dt);
4482 if (action & F_END) {
4483 draw_activity_graphs(a->g_nr, g_type,
4484 title, g_title, NULL, group,
4485 spmin, spmax, out, outsize, svg_p, record_hdr);
4487 /* Free remaining structures */
4488 free_graphs(out, outsize, spmin, spmax);
4493 ***************************************************************************
4494 * Display filesystem statistics in SVG.
4497 * @a Activity structure with statistics.
4498 * @curr Index in array for current sample statistics.
4499 * @action Action expected from current function.
4500 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4501 * flag indicating that a restart record has been previously
4502 * found (.@restart) and time used for the X axis origin
4504 * @itv Interval of time in jiffies (unused here).
4505 * @record_hdr Pointer on record header of current stats sample.
4506 ***************************************************************************
4508 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4509 unsigned long long itv, struct record_header *record_hdr)
4511 struct stats_filesystem *sfc, *sfp;
4512 int group[] = {2, 2, 2, 1};
4513 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4514 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4515 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4516 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4517 char *g_title[] = {"~MBfsfree", "~MBfsused",
4518 "%ufsused", "%fsused",
4519 "Ifree/1000", "Iused/1000",
4521 static double *spmin, *spmax;
4523 static int *outsize;
4524 char *item_name = NULL;
4526 int i, k, pos, restart;
4528 if (action & F_BEGIN) {
4530 * Allocate arrays (#0..6) that will contain the graphs data
4531 * and the min/max values.
4532 * Also allocate two additional arrays (#7..8) for each filesystem:
4533 * out + 7 will contain the filesystem name,
4534 * out + 8 will contain the mount point.
4536 out = allocate_graph_lines(9 * a->nr, &outsize, &spmin, &spmax);
4539 if (action & F_MAIN) {
4540 /* For each filesystem structure */
4541 for (i = 0; i < a->nr; i++) {
4542 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4545 /* Size of filesystem is zero: We are at the end of the list */
4548 /* Look for corresponding graph */
4549 for (k = 0; k < a->nr; k++) {
4550 item_name = *(out + k * 9 + 7);
4551 if (!strcmp(sfc->fs_name, item_name))
4557 /* Graph not found: Look for first free entry */
4558 for (k = 0; k < a->nr; k++) {
4559 item_name = *(out + k * 9 + 7);
4560 if (!strcmp(item_name, ""))
4564 /* No free graph entry: Graph for this item won't be drawn */
4570 if (!item_name[0]) {
4571 /* Save filesystem name and mount point (if not already done) */
4572 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4573 item_name[CHUNKSIZE - 1] = '\0';
4574 item_name = *(out + pos + 8);
4575 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4576 item_name[CHUNKSIZE - 1] = '\0';
4580 for (k = 0; k < a->nr; k++) {
4581 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4582 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4583 /* Filesystem found in previous sample */
4584 restart = svg_p->restart;
4588 /* Check for min/max values */
4590 /* Compute fsfree min/max values */
4591 tval = (double) sfc->f_bfree;
4592 if (tval > *(spmax + pos)) {
4593 *(spmax + pos) = tval;
4595 if (tval < *(spmin + pos)) {
4596 *(spmin + pos) = tval;
4598 /* Compute fsused min/max values */
4599 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4600 if (tval > *(spmax + pos + 1)) {
4601 *(spmax + pos + 1) = tval;
4603 if (tval < *(spmin + pos + 1)) {
4604 *(spmin + pos + 1) = tval;
4606 /* Compute %ufsused min/max values */
4607 tval = sfc->f_blocks ?
4608 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4609 if (tval > *(spmax + pos + 2)) {
4610 *(spmax + pos + 2) = tval;
4612 if (tval < *(spmin + pos + 2)) {
4613 *(spmin + pos + 2) = tval;
4615 /* Compute %fsused min/max values */
4616 tval = sfc->f_blocks ?
4617 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4618 if (tval > *(spmax + pos + 3)) {
4619 *(spmax + pos + 3) = tval;
4621 if (tval < *(spmin + pos + 3)) {
4622 *(spmin + pos + 3) = tval;
4624 /* Compute Ifree min/max values */
4625 tval = (double) sfc->f_ffree;
4626 if (tval > *(spmax + pos + 4)) {
4627 *(spmax + pos + 4) = tval;
4629 if (tval < *(spmin + pos + 4)) {
4630 *(spmin + pos + 4) = tval;
4632 /* Compute Iused min/max values */
4633 tval = (double) (sfc->f_files - sfc->f_ffree);
4634 if (tval > *(spmax + pos + 5)) {
4635 *(spmax + pos + 5) = tval;
4637 if (tval < *(spmin + pos + 5)) {
4638 *(spmin + pos + 5) = tval;
4640 /* Compute %Iused min/max values */
4641 tval = sfc->f_files ?
4642 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4643 if (tval > *(spmax + pos + 6)) {
4644 *(spmax + pos + 6) = tval;
4646 if (tval < *(spmin + pos + 6)) {
4647 *(spmin + pos + 6) = tval;
4651 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4652 (double) sfc->f_bfree / 1024 / 1024,
4653 out + pos, outsize + pos, restart);
4655 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4656 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4657 out + pos + 1, outsize + pos + 1, restart);
4659 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4662 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4663 out + pos + 2, outsize + pos + 2, svg_p->dt);
4665 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4668 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4669 out + pos + 3, outsize + pos + 3, svg_p->dt);
4671 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4672 ((double) sfc->f_ffree) / 1000,
4673 out + pos + 4, outsize + pos + 4, restart);
4675 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4676 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4677 out + pos + 5, outsize + pos + 5, restart);
4679 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4682 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4683 out + pos + 6, outsize + pos + 6, svg_p->dt);
4687 if (action & F_END) {
4689 for (i = 0; i < a->nr; i++) {
4691 /* Check if there is something to display */
4696 /* Conversion B -> MB and inodes/1000 */
4697 for (k = 0; k < 2; k++) {
4698 *(spmin + pos + k) /= (1024 * 1024);
4699 *(spmax + pos + k) /= (1024 * 1024);
4700 *(spmin + pos + 4 + k) /= 1000;
4701 *(spmax + pos + 4 + k) /= 1000;
4704 if (DISPLAY_MOUNT(a->opt_flags)) {
4705 item_name = *(out + pos + 8);
4708 item_name = *(out + pos + 7);
4711 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4712 spmin + pos, spmax + pos, out + pos, outsize + pos,
4716 /* Free remaining structures */
4717 free_graphs(out, outsize, spmin, spmax);
4722 ***************************************************************************
4723 * Display Fibre Channel HBA statistics in SVG.
4726 * @a Activity structure with statistics.
4727 * @curr Index in array for current sample statistics.
4728 * @action Action expected from current function.
4729 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4730 * flag indicating that a restart record has been previously
4731 * found (.@restart) and time used for the X axis origin
4733 * @itv Interval of time in jiffies (only with F_MAIN action).
4734 * @record_hdr Pointer on record header of current stats sample.
4735 ***************************************************************************
4737 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4738 unsigned long long itv, struct record_header *record_hdr)
4740 struct stats_fchost *sfcc, *sfcp;
4741 int group[] = {2, 2};
4742 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4743 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4744 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4745 "fch_rxw/s", "fch_txw/s"};
4746 int g_fields[] = {0, 1, 2, 3};
4747 static double *spmin, *spmax;
4749 static int *outsize;
4753 if (action & F_BEGIN) {
4755 * Allocate arrays (#0..3) that will contain the graphs data
4756 * and the min/max values.
4757 * Also allocate one additional array (#4) that will contain
4760 out = allocate_graph_lines(4 * a->nr, &outsize, &spmin, &spmax);
4763 if (action & F_MAIN) {
4764 /* For each FC HBA */
4765 for (i = 0; i < a->nr; i++) {
4767 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4768 if (!sfcc->fchost_name[0])
4769 /* We are at the end of the list */
4772 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + i * a->msize);
4775 item_name = *(out + pos + 4);
4776 if (!item_name[0]) {
4777 /* Save FC HBA name */
4778 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4779 item_name[CHUNKSIZE - 1] = '\0';
4782 /* Look for min/max values */
4783 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4784 itv, spmin + pos, spmax + pos, g_fields);
4787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4788 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4789 out + pos, outsize + pos, svg_p->restart);
4791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4792 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4793 out + pos + 1, outsize + pos + 1, svg_p->restart);
4795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4796 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4797 out + pos + 2, outsize + pos + 2, svg_p->restart);
4799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4800 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4801 out + pos + 3, outsize + pos + 3, svg_p->restart);
4805 if (action & F_END) {
4806 for (i = 0; i < a->nr; i++) {
4808 /* Check if there is something to display */
4813 item_name = *(out + pos + 4);
4814 draw_activity_graphs(a->g_nr, g_type,
4815 title, g_title, item_name, group,
4816 spmin + pos, spmax + pos, out + pos, outsize + pos,
4820 /* Free remaining structures */
4821 free_graphs(out, outsize, spmin, spmax);
4826 ***************************************************************************
4827 * Display softnet statistics in SVG.
4830 * @a Activity structure with statistics.
4831 * @curr Index in array for current sample statistics.
4832 * @action Action expected from current function.
4833 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4834 * flag indicating that a restart record has been previously
4835 * found (.@restart) and time used for the X axis origin
4837 * @itv Interval of time in jiffies (only with F_MAIN action).
4838 * @record_hdr Pointer on record header of current stats sample.
4839 ***************************************************************************
4841 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4842 unsigned long long itv, struct record_header *record_hdr)
4844 struct stats_softnet *ssnc, *ssnp;
4845 int group[] = {2, 3};
4846 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4847 char *title[] = {"Software-based network processing statistics (1)",
4848 "Software-based network processing statistics (2)"};
4849 char *g_title[] = {"total/s", "dropd/s",
4850 "squeezd/s", "rx_rps/s", "flw_lim/s"};
4851 int g_fields[] = {0, 1, 2, 3, 4};
4852 static double *spmin, *spmax;
4854 static int *outsize;
4858 if (action & F_BEGIN) {
4860 * Allocate arrays that will contain the graphs data
4861 * and the min/max values.
4863 out = allocate_graph_lines(5 * a->nr, &outsize, &spmin, &spmax);
4866 if (action & F_MAIN) {
4868 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4870 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
4871 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
4873 /* Should current CPU (including CPU "all") be displayed? */
4874 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4880 /* Check for min/max values */
4881 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
4882 itv, spmin + pos, spmax + pos, g_fields);
4885 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4886 S_VALUE(ssnp->processed, ssnc->processed, itv),
4887 out + pos, outsize + pos, svg_p->restart);
4889 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4890 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
4891 out + pos + 1, outsize + pos + 1, svg_p->restart);
4893 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4894 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
4895 out + pos + 2, outsize + pos + 2, svg_p->restart);
4897 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4898 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
4899 out + pos + 3, outsize + pos + 3, svg_p->restart);
4901 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4902 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
4903 out + pos + 4, outsize + pos + 4, svg_p->restart);
4907 if (action & F_END) {
4908 for (i = 0; (i < a->nr) && (i < a->bitmap->b_size + 1); i++) {
4910 /* Should current CPU (including CPU "all") be displayed? */
4911 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4918 /* This is CPU "all" */
4919 strcpy(item_name, "all");
4922 sprintf(item_name, "%d", i - 1);
4925 draw_activity_graphs(a->g_nr, g_type,
4926 title, g_title, item_name, group,
4927 spmin + pos, spmax + pos, out + pos, outsize + pos,
4931 /* Free remaining structures */
4932 free_graphs(out, outsize, spmin, spmax);