2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016-2018 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 ***************************************************************************
30 #include "svg_stats.h"
35 #define _(string) gettext(string)
37 #define _(string) (string)
40 extern unsigned int flags;
41 extern struct sa_dlist *st_iface_list;
42 extern struct sa_dlist *st_dev_list;
43 extern struct sa_dlist *st_fs_list;
44 extern int dlst_iface_idx;
45 extern int dlst_dev_idx;
46 extern int dlst_fs_idx;
48 unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
49 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
50 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
51 0xcc3300, 0x50040f, 0xffffbf, 0x193d55};
52 #define SVG_COLORS_IDX_MASK 0x0f
55 ***************************************************************************
56 * Compare the values of a statistics sample with the max and min values
57 * already found in previous samples for this same activity. If some new
58 * min or max values are found, then save them.
59 * Assume values cannot be negative.
60 * The structure containing the statistics sample is composed of @llu_nr
61 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
62 * followed by @u_nr unsigned int fields.
65 * @types_nr Number of fields whose type is "long long", "long" and "int"
66 * composing the structure.
67 * @cs Pointer on current sample statistics structure.
68 * @ps Pointer on previous sample statistics structure (may be NULL).
69 * @itv Interval of time in 1/100th of a second.
70 * @spmin Array containing min values already found for this activity.
71 * @spmax Array containing max values already found for this activity.
72 * @g_fields Index in spmin/spmax arrays where extrema values for each
73 * activity metric will be saved. As a consequence spmin/spmax
74 * arrays may contain values in a different order than that of
75 * the fields in the statistics structure.
78 * @spmin Array containg the possible new min values for current activity.
79 * @spmax Array containg the possible new max values for current activity.
80 ***************************************************************************
82 void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
83 double *spmin, double *spmax, int g_fields[])
85 unsigned long long *lluc, *llup;
86 unsigned long *luc, *lup;
87 unsigned int *uc, *up;
91 /* Compare unsigned long long fields */
92 lluc = (unsigned long long *) cs;
93 llup = (unsigned long long *) ps;
94 for (i = 0; i < types_nr[0]; i++, m++) {
96 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
100 * If no pointer on previous sample has been given
101 * then the value is not a per-second one.
103 val = (double) *lluc;
105 if (val < *(spmin + g_fields[m])) {
106 *(spmin + g_fields[m]) = val;
108 if (val > *(spmax + g_fields[m])) {
109 *(spmax + g_fields[m]) = val;
111 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
113 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
117 /* Compare unsigned long fields */
118 luc = (unsigned long *) lluc;
119 lup = (unsigned long *) llup;
120 for (i = 0; i < types_nr[1]; i++, m++) {
122 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
127 if (val < *(spmin + g_fields[m])) {
128 *(spmin + g_fields[m]) = val;
130 if (val > *(spmax + g_fields[m])) {
131 *(spmax + g_fields[m]) = val;
133 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
135 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
139 /* Compare unsigned int fields */
140 uc = (unsigned int *) luc;
141 up = (unsigned int *) lup;
142 for (i = 0; i < types_nr[2]; i++, m++) {
144 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
149 if (val < *(spmin + g_fields[m])) {
150 *(spmin + g_fields[m]) = val;
152 if (val > *(spmax + g_fields[m])) {
153 *(spmax + g_fields[m]) = val;
155 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
157 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
163 ***************************************************************************
164 * Find the min and max values of all the graphs that will be drawn in the
165 * same view. The graphs have their own min and max values in
166 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
169 * @pos Position in array for the first graph extrema value.
170 * @n Number of graphs to scan.
171 * @spmin Array containing min values for graphs.
172 * @spmax Array containing max values for graphs.
175 * @gmin Global min value found.
176 * @gmax Global max value found.
177 ***************************************************************************
179 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
180 double *gmin, double *gmax)
184 *gmin = *(spmin + pos);
185 *gmax = *(spmax + pos);
187 for (i = 1; i < n; i++) {
188 if (*(spmin + pos + i) < *gmin) {
189 *gmin = *(spmin + pos + i);
191 if (*(spmax + pos + i) > *gmax) {
192 *gmax = *(spmax + pos + i);
198 ***************************************************************************
199 * Allocate arrays used to save graphs data, min and max values.
200 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
201 * array is returned. This is equivalent to "char data[][n]" where each
202 * element is of indeterminate size and will contain the graph data (eg.
203 * << path d="M12,14 L13,16..." ... >>.
204 * The size of element data[i] is given by outsize[i].
205 * Also allocate an array to save min values (equivalent to "double spmin[n]")
206 * and an array for max values (equivalent to "double spmax[n]").
209 * @n Number of graphs to draw for current activity.
212 * @outsize Array that will contain the sizes of each element in array
213 * of chars. Equivalent to "int outsize[n]" with
214 * outsize[n] = sizeof(data[][n]).
215 * @spmin Array that will contain min values for current activity.
216 * @spmax Array that will contain max values for current activity.
219 * Pointer on array of arrays of chars that will contain the graphs data.
221 * NB: @min and @max arrays contain values in the same order as the fields
222 * in the statistics structure.
223 ***************************************************************************
225 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
232 * Allocate an array of pointers. Each of these pointers will
233 * be an array of chars.
235 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
239 /* Allocate array that will contain the size of each array of chars */
240 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
244 /* Allocate array that will contain the min value of each graph */
245 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
249 /* Allocate array that will contain the max value of each graph */
250 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
254 /* Allocate arrays of chars that will contain graphs data */
255 for (i = 0; i < n; i++) {
256 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
261 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
262 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
263 *(*spmin + i) = DBL_MAX; /* Init min and max values */
264 *(*spmax + i) = -DBL_MAX;
271 ***************************************************************************
272 * Reallocate all the arrays used to save graphs data, min and max values.
273 * The new size is the double of the original one.
276 * @n Number of slots currently allocated.
277 * @out Current pointer on arrays containing the graphs data.
278 * @outsize Current pointer on array containing the size of each element
280 * @spmin Current pointer on array containing min values.
281 * @spmax Current pointer on array containing max values.
284 * @out New pointer on arrays containing the graphs data.
285 * @outsize New pointer on array containing the size of each element
287 * @spmin New pointer on array containing min values.
288 * @spmax New pointer on array containing max values.
289 ***************************************************************************
291 void reallocate_all_graph_lines(int n, char ***out, int **outsize,
292 double **spmin, double **spmax)
297 /* Reallocate all the arrays */
298 SREALLOC(*out, char *, n * sizeof(char *) * 2);
299 SREALLOC(*outsize, int, n * sizeof(int) * 2);
300 SREALLOC(*spmin, double, n * sizeof(double) * 2);
301 SREALLOC(*spmax, double, n * sizeof(double) * 2);
303 /* Allocate arrays of chars that will contain graphs data for the newly allocated slots */
304 for (i = 0; i < n; i++) {
305 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
309 *(*out + n + i) = out_p;
311 *(*outsize + n + i) = CHUNKSIZE;
312 *(*spmin + n + i) = DBL_MAX;
313 *(*spmax + n + i) = -DBL_MAX;
318 ***************************************************************************
319 * Save SVG code for current graph.
322 * @data SVG code to append to current graph definition.
323 * @out Pointer on array of chars for current graph definition.
324 * @outsize Size of array of chars for current graph definition.
327 * @out Pointer on array of chars for current graph definition that
328 * has been updated with the addition of current sample data.
329 * @outsize Array that containing the (possibly new) sizes of each
330 * element in array of chars.
331 ***************************************************************************
333 void save_svg_data(char *data, char **out, int *outsize)
339 /* Determine space left in array */
340 len = *outsize - strlen(out_p) - 1;
341 if (strlen(data) >= len) {
343 * If current array of chars doesn't have enough space left
344 * then reallocate it with CHUNKSIZE more bytes.
346 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
348 *outsize += CHUNKSIZE;
351 strncat(out_p, data, len);
355 ***************************************************************************
356 * Update line graph definition by appending current X,Y coordinates.
359 * @timetag Timestamp in seconds since the epoch for current sample
360 * stats. Will be used as X coordinate.
361 * @value Value of current sample metric. Will be used as Y coordinate.
362 * @out Pointer on array of chars for current graph definition.
363 * @outsize Size of array of chars for current graph definition.
364 * @restart Set to TRUE if a RESTART record has been read since the last
368 * @out Pointer on array of chars for current graph definition that
369 * has been updated with the addition of current sample data.
370 * @outsize Array that containing the (possibly new) sizes of each
371 * element in array of chars.
372 ***************************************************************************
374 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
379 /* Prepare additional graph definition data */
380 snprintf(data, 128, " %c%llu,%.2f", restart ? 'M' : 'L', timetag, value);
383 save_svg_data(data, out, outsize);
387 ***************************************************************************
388 * Update line graph definition by appending current X,Y coordinates. Use
389 * (unsigned long) integer values here.
392 * @timetag Timestamp in seconds since the epoch for current sample
393 * stats. Will be used as X coordinate.
394 * @value Value of current sample metric. Will be used as Y coordinate.
395 * @out Pointer on array of chars for current graph definition.
396 * @outsize Size of array of chars for current graph definition.
397 * @restart Set to TRUE if a RESTART record has been read since the last
401 * @out Pointer on array of chars for current graph definition that
402 * has been updated with the addition of current sample data.
403 * @outsize Array that containing the (possibly new) sizes of each
404 * element in array of chars.
405 ***************************************************************************
407 void lniappend(unsigned long long timetag, unsigned long long value, char **out,
408 int *outsize, int restart)
412 /* Prepare additional graph definition data */
413 snprintf(data, 128, " %c%llu,%llu", restart ? 'M' : 'L', timetag, value);
416 save_svg_data(data, out, outsize);
420 ***************************************************************************
421 * Update bar graph definition by adding a new rectangle.
424 * @timetag Timestamp in seconds since the epoch for current sample
425 * stats. Will be used as X coordinate.
426 * @value Value of current sample metric. Will be used as rectangle
428 * @offset Offset for Y coordinate.
429 * @out Pointer on array of chars for current graph definition.
430 * @outsize Size of array of chars for current graph definition.
431 * @dt Interval of time in seconds between current and previous
435 * @out Pointer on array of chars for current graph definition that
436 * has been updated with the addition of current sample data.
437 * @outsize Array that containing the (possibly new) sizes of each
438 * element in array of chars.
439 ***************************************************************************
441 void brappend(unsigned long long timetag, double offset, double value, char **out,
442 int *outsize, unsigned long long dt)
446 /* Prepare additional graph definition data */
447 if ((value == 0.0) || (dt == 0))
448 /* Don't draw a flat rectangle! */
451 snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
452 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
455 save_svg_data(data, out, outsize);
460 ***************************************************************************
461 * Update CPU graph and min/max values for each metric.
464 * @timetag Timestamp in seconds since the epoch for current sample
465 * stats. Will be used as X coordinate.
466 * @offset Offset for Y coordinate.
467 * @value Value of current CPU metric. Will be used as rectangle
469 * @out Pointer on array of chars for current graph definition.
470 * @outsize Size of array of chars for current graph definition.
471 * @dt Interval of time in seconds between current and previous
473 * @spmin Min value already found for this CPU metric.
474 * @spmax Max value already found for this CPU metric.
477 * @offset New offset value, to use to draw next rectangle
478 * @out Pointer on array of chars for current graph definition that
479 * has been updated with the addition of current sample data.
480 * @outsize Array that containing the (possibly new) sizes of each
481 * element in array of chars.
482 ***************************************************************************
484 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
485 int *outsize, unsigned long long dt, double *spmin, double *spmax)
487 /* Save min and max values */
488 if (value < *spmin) {
491 if (value > *spmax) {
494 /* Prepare additional graph definition data */
495 brappend(timetag, *offset, value, out, outsize, dt);
501 ***************************************************************************
502 * Update rectangular graph and min/max values.
505 * @timetag Timestamp in seconds since the epoch for current sample
506 * stats. Will be used as X coordinate.
507 * @p_value Metric value for previous sample
508 * @value Metric value for current sample.
509 * @out Pointer on array of chars for current graph definition.
510 * @outsize Size of array of chars for current graph definition.
511 * @restart Set to TRUE if a RESTART record has been read since the last
513 * @dt Interval of time in seconds between current and previous
515 * @spmin Min value already found for this metric.
516 * @spmax Max value already found for this metric.
519 * @out Pointer on array of chars for current graph definition that
520 * has been updated with the addition of current sample data.
521 * @outsize Array that containing the (possibly new) sizes of each
522 * element in array of chars.
523 * @spmin Min value for this metric.
524 * @spmax Max value for this metric.
525 ***************************************************************************
527 void recappend(unsigned long long timetag, double p_value, double value, char **out,
528 int *outsize, int restart, unsigned long long dt,
529 double *spmin, double *spmax)
531 char data[128], data1[128], data2[128];
533 /* Save min and max values */
534 if (value < *spmin) {
537 if (value > *spmax) {
540 /* Prepare additional graph definition data */
542 snprintf(data1, 128, " M%llu,%.2f", timetag - dt, p_value);
545 if (p_value != value) {
546 snprintf(data2, 128, " L%llu,%.2f", timetag, value);
549 snprintf(data, 128, "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
550 p_value != value ? data2 : "");
553 save_svg_data(data, out, outsize);
557 ***************************************************************************
558 * Calculate 10 raised to the power of n.
561 * @n Power number to use.
564 * 10 raised to the power of n.
565 ***************************************************************************
567 unsigned int pwr10(int n)
572 for (i = 0; i < n; i++) {
580 ***************************************************************************
581 * Autoscale graphs of a given view.
584 * @asf_nr (Maximum) number of autoscale factors.
585 * @group Number of graphs in current view.
586 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
587 * @pos Position in array for the first graph in view.
588 * @gmax Global max value for all graphs in view.
589 * @spmax Array containing max values for graphs.
592 * @asfactor Autoscale factors (one for each graph).
593 ***************************************************************************
595 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
596 double gmax, double *spmax)
601 for (j = 0; j < asf_nr; j++) {
602 /* Init autoscale factors */
606 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
608 for (j = 0; (j < group) && (j < asf_nr); j++) {
609 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
612 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
613 if (strlen(val) > 0) {
614 asfactor[j] = pwr10(strlen(val) - 1);
621 ***************************************************************************
622 * Display background grid (horizontal lines) and corresponding graduations.
625 * @ypos Gap between two horizontal lines.
626 * @yfactor Scaling factor on Y axis.
627 * @lmax Max value for current view.
628 * @dp Number of decimal places for graduations.
629 ***************************************************************************
631 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
637 /* Display horizontal lines (except on X axis) */
639 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
640 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
641 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
645 * Display graduations.
646 * Use same rounded value for graduation numbers as for grid lines
647 * to make sure they are properly aligned.
649 sprintf(stmp, "%.2f", ypos * j);
650 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
651 "text-anchor: end\">%.*f.</text>\n",
652 (long) (atof(stmp) * yfactor), dp, ypos * j);
655 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
659 ***************************************************************************
660 * Display background grid (vertical lines) and corresponding graduations.
663 * @xpos Gap between two vertical lines.
664 * @xfactor Scaling factor on X axis.
665 * @v_gridnr Default number of vertical lines to display. The actual
666 * number may vary between this value and 2 times this value.
667 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
668 ***************************************************************************
670 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
672 struct record_header stamp;
674 char cur_time[TIMESTAMP_LEN];
677 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
680 * What really matters to know when we should stop drawing vertical lines
681 * is the time end. v_gridnr is only informative and used to calculate
682 * the gap between two lines.
684 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
686 /* Display vertical lines */
687 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
688 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
689 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
690 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
691 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
693 * Display graduations.
694 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
695 * In this case, we should rather display the exact time instead of only the hour.
697 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
698 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
699 "text-anchor: start\">%2d:00</text>\n",
700 (long) (xpos * j * xfactor) - 15, rectime.tm_hour);
703 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
704 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
705 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
707 stamp.ust_time += xpos;
710 if (!PRINT_LOCAL_TIME(flags)) {
711 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
712 "text-anchor: end\">UTC</text>\n");
717 ***************************************************************************
718 * Calculate the value on the Y axis between two horizontal lines that will
719 * make the graph background grid.
722 * @lmax Max value reached for this graph.
725 * @dp Number of decimal places for Y graduations.
728 * Value between two horizontal lines.
729 ***************************************************************************
731 double ygrid(double lmax, int *dp)
742 n = (long) (lmax / SVG_H_GRIDNR);
745 return (lmax / SVG_H_GRIDNR);
747 snprintf(val, 32, "%ld", n);
754 return ((double) (((long) (n / e)) * e));
758 ***************************************************************************
759 * Calculate the value on the X axis between two vertical lines that will
760 * make the graph background grid.
763 * @timestart First data timestamp (X coordinate of the first data point).
764 * @timeend Last data timestamp (X coordinate of the last data point).
765 * @v_gridnr Number of vertical lines to display. Its value is normally
766 * SVG_V_GRIDNR, except when option "oneday" is used, in which
767 * case it is set to 12.
770 * Value between two vertical lines.
771 ***************************************************************************
773 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
775 if ((timeend - timestart) <= v_gridnr)
778 return ((timeend - timestart) / v_gridnr);
782 ***************************************************************************
783 * Free global graphs structures.
786 * @out Pointer on array of chars for each graph definition.
787 * @outsize Size of array of chars for each graph definition.
788 * @spmin Array containing min values for graphs.
789 * @spmax Array containing max values for graphs.
790 ***************************************************************************
792 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
809 ***************************************************************************
810 * Skip current view where all graphs have only zero values. This function
811 * is called when option "skipempty" has been used, or when "No data" have
812 * been found for current view.
815 * @out Pointer on array of chars for each graph definition.
816 * @pos Position of current view in the array of graphs definitions.
817 * @group Number of graphs in current view.
820 * @pos Position of next view in the array of graphs definitions.
821 ***************************************************************************
823 void skip_current_view(char **out, int *pos, int group)
828 for (j = 0; j < group; j++) {
829 out_p = *(out + *pos + j);
831 /* Even if not displayed, current graph data have to be freed */
839 ***************************************************************************
840 * Display all graphs for current activity.
843 * @g_nr Number of views to display.
844 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
845 * @title Titles for each set of graphs.
846 * @g_title Titles for each graph.
847 * @item_name Item (network interface, etc.) name.
848 * @group Indicate how graphs are grouped together to make sets.
849 * @spmin Array containing min values for graphs.
850 * @spmax Array containing max values for graphs.
851 * @out Pointer on array of chars for each graph definition.
852 * @outsize Size of array of chars for each graph definition.
853 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
854 * time for the first sample of stats (.@ust_time_first), and
855 * times used as start and end values on the X axis
856 * (.@ust_time_ref and .@ust_time_end).
857 * @record_hdr Pointer on record header of current stats sample.
858 * @skip_void Set to <> 0 if graphs with no data should be skipped.
859 * This is typicallly used to not display CPU offline on the
861 ***************************************************************************
863 void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
864 int group[], double *spmin, double *spmax, char **out, int *outsize,
865 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void)
868 int i, j, dp, pos = 0, views_nr = 0;
869 int v_gridnr, xv, yv;
870 unsigned int asfactor[16];
872 double lmax, xfactor, yfactor, ypos, gmin, gmax;
873 char val[32], cur_date[TIMESTAMP_LEN];
875 /* Translate to proper position for current activity */
876 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
878 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
880 /* For each view which is part of current activity */
881 for (i = 0; i < g_nr; i++) {
883 /* Get global min and max value for current view */
884 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
886 /* Don't display empty views if requested */
887 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
888 skip_current_view(out, &pos, group[i]);
891 /* Skip void graphs */
892 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
895 /* Increment number of views actually displayed */
898 /* Compute top left position of view */
899 if (PACK_VIEWS(flags)) {
900 xv = (views_nr - 1) * SVG_T_XSIZE;
905 yv = (views_nr - 1) * SVG_T_YSIZE;
908 /* Graph background */
909 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
910 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
913 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
914 xv, 20 + yv, title[i]);
916 printf(" [%s]", item_name);
919 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
920 "(Min, Max values)</tspan>\n</text>\n",
921 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
924 * At least two samples are needed.
925 * And a min and max value should have been found.
927 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
928 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
930 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
931 xv, yv + SVG_M_YSIZE);
932 skip_current_view(out, &pos, group[i]);
937 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
938 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
939 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
940 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
942 /* Autoscaling graphs if needed */
943 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
946 for (j = 0; j < group[i]; j++) {
947 /* Set dp to TRUE (1) if current metric is based on integer values */
948 dp = (g_title[pos + j][0] == '~');
949 snprintf(val, 32, "x%u ", asfactor[j]);
950 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
951 "%s %s(%.*f, %.*f)</text>\n",
952 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
953 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
954 asfactor[j] == 1 ? "" : val,
955 !dp * 2, *(spmin + pos + j) * asfactor[j],
956 !dp * 2, *(spmax + pos + j) * asfactor[j]);
959 if (DISPLAY_INFO(flags)) {
960 /* Display additional info (hostname, date) */
961 printf("<text x=\"%d\" y=\"%d\" "
962 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
964 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
965 svg_p->file_hdr->sa_nodename);
967 /* Get report date */
968 set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
969 cur_date, sizeof(cur_date));
970 printf("<tspan x=\"%d\" y=\"%d\" "
971 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
972 "%s</tspan>\n</text>\n",
973 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
977 /* Translate to proper position for current graph within current activity */
978 printf("<g transform=\"translate(%d,%d)\">\n",
979 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
982 if (g_type[i] == SVG_LINE_GRAPH) {
983 /* For line graphs */
985 /* If all values are zero then set current max value to 1 */
991 /* Max value cannot be too small, else Y graduations will be meaningless */
992 if (lmax < SVG_H_GRIDNR * 0.01) {
993 lmax = SVG_H_GRIDNR * 0.01;
995 ypos = ygrid(lmax, &dp);
998 /* For bar graphs (used for %values) */
999 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
1000 dp = 0; /* No decimals */
1002 /* Max should be always 100% except for percentage values greater than 100% */
1010 yfactor = (double) -SVG_G_YSIZE / lmax;
1012 /* Display horizontal lines and graduations */
1013 display_hgrid(ypos, yfactor, lmax, dp);
1015 /* Set number of vertical lines to 12 when option "oneday" is used */
1016 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1018 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1019 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1021 /* Display vertical lines and graduations */
1022 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1024 /* Draw current graphs set */
1025 for (j = 0; j < group[i]; j++) {
1026 out_p = *(out + pos + j);
1027 if (g_type[i] == SVG_LINE_GRAPH) {
1029 printf("<path id=\"g%dp%d\" d=\"%s\" "
1030 "style=\"vector-effect: non-scaling-stroke; "
1031 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1032 "transform=\"scale(%f,%f)\"/>\n",
1033 svg_p->graph_no, pos + j, out_p,
1034 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
1036 yfactor * asfactor[j]);
1038 else if (*out_p) { /* Ignore flat bars */
1040 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1041 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1042 printf("%s\n", out_p);
1052 /* For next row of views */
1053 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1057 ***************************************************************************
1058 * Display CPU statistics in SVG.
1061 * @a Activity structure with statistics.
1062 * @curr Index in array for current sample statistics.
1063 * @action Action expected from current function.
1064 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1065 * flag indicating that a restart record has been previously
1066 * found (.@restart), and time used for the X axis origin
1068 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1070 * @record_hdr Pointer on record header of current stats sample.
1071 ***************************************************************************
1073 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1074 unsigned long long itv, struct record_header *record_hdr)
1076 struct stats_cpu *scc, *scp;
1077 unsigned long long deltot_jiffies = 1;
1078 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1081 int g_type[] = {SVG_BAR_GRAPH};
1082 char *title[] = {"CPU load"};
1083 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1084 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1085 static double *spmin, *spmax;
1087 static int *outsize;
1092 if (action & F_BEGIN) {
1094 * Allocate arrays that will contain the graphs data
1095 * and the min/max values.
1097 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
1100 if (action & F_MAIN) {
1102 /* @nr[curr] cannot normally be greater than @nr_ini */
1103 if (a->nr[curr] > a->nr_ini) {
1104 a->nr_ini = a->nr[curr];
1108 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1109 * and look for offline CPU.
1111 if (a->nr_ini > 1) {
1112 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1113 flags, offline_cpu_bitmap);
1117 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1119 /* Should current CPU (including CPU "all") be displayed? */
1120 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1121 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1122 /* Don't display CPU */
1125 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1126 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1132 /* This is CPU "all" */
1133 if (a->nr_ini == 1) {
1135 * This is a UP machine. In this case
1136 * interval has still not been calculated.
1138 deltot_jiffies = get_per_cpu_interval(scc, scp);
1140 if (!deltot_jiffies) {
1141 /* CPU "all" cannot be tickless */
1147 * Recalculate interval for current proc.
1148 * If result is 0 then current CPU is a tickless one.
1150 deltot_jiffies = get_per_cpu_interval(scc, scp);
1152 if (!deltot_jiffies) { /* Current CPU is tickless */
1154 val = 100.0; /* Tickless CPU: %idle = 100% */
1156 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1159 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1163 /* Check min/max values for %user, etc. */
1164 for (k = 0; k < j; k++) {
1165 if (0.0 < *(spmin + pos + k)) {
1166 *(spmin + pos + k) = 0.0;
1168 if (0.0 > *(spmax + pos + k)) {
1169 *(spmax + pos + k) = 0.0;
1174 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1176 out + pos + j, outsize + pos + j, svg_p->dt,
1177 spmin + pos + j, spmax + pos + j);
1182 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1184 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1185 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1186 out + pos, outsize + pos, svg_p->dt,
1187 spmin + pos, spmax + pos);
1191 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1193 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1195 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1196 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1197 out + pos, outsize + pos, svg_p->dt,
1198 spmin + pos, spmax + pos);
1201 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1203 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1204 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1205 out + pos + 1, outsize + pos + 1, svg_p->dt,
1206 spmin + pos + 1, spmax + pos + 1);
1210 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1212 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1214 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1215 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1216 out + pos + 1, outsize + pos + 1, svg_p->dt,
1217 spmin + pos + 1, spmax + pos + 1);
1220 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1222 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1224 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1225 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1227 out + pos + 2, outsize + pos + 2, svg_p->dt,
1228 spmin + pos + 2, spmax + pos + 2);
1232 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1233 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1234 out + pos + 2, outsize + pos + 2, svg_p->dt,
1235 spmin + pos + 2, spmax + pos + 2);
1239 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1240 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1241 out + pos + 3, outsize + pos + 3, svg_p->dt,
1242 spmin + pos + 3, spmax + pos + 3);
1244 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1245 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1246 out + pos + 4, outsize + pos + 4, svg_p->dt,
1247 spmin + pos + 4, spmax + pos + 4);
1249 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1251 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1252 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1253 out + pos + 5, outsize + pos + 5, svg_p->dt,
1254 spmin + pos + 5, spmax + pos + 5);
1256 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1257 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1258 out + pos + 6, outsize + pos + 6, svg_p->dt,
1259 spmin + pos + 6, spmax + pos + 6);
1261 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1262 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1263 out + pos + 7, outsize + pos + 7, svg_p->dt,
1264 spmin + pos + 7, spmax + pos + 7);
1266 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1267 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1268 out + pos + 8, outsize + pos + 8, svg_p->dt,
1269 spmin + pos + 8, spmax + pos + 8);
1278 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1280 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1281 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1282 out + pos + j, outsize + pos + j, svg_p->dt,
1283 spmin + pos + j, spmax + pos + j);
1287 if (action & F_END) {
1288 if (DISPLAY_IDLE(flags)) {
1289 /* Include additional %idle field */
1294 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
1296 /* Should current CPU (including CPU "all") be displayed? */
1297 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1303 /* This is CPU "all" */
1304 strcpy(item_name, "all");
1307 sprintf(item_name, "%d", i - 1);
1310 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1311 draw_activity_graphs(a->g_nr, g_type,
1312 title, g_title1, item_name, group1,
1313 spmin + pos, spmax + pos, out + pos, outsize + pos,
1314 svg_p, record_hdr, i);
1317 draw_activity_graphs(a->g_nr, g_type,
1318 title, g_title2, item_name, group2,
1319 spmin + pos, spmax + pos, out + pos, outsize + pos,
1320 svg_p, record_hdr, i);
1324 /* Free remaining structures */
1325 free_graphs(out, outsize, spmin, spmax);
1330 ***************************************************************************
1331 * Display task creation and context switch statistics in SVG.
1334 * @a Activity structure with statistics.
1335 * @curr Index in array for current sample statistics.
1336 * @action Action expected from current function.
1337 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1338 * flag indicating that a restart record has been previously
1339 * found (.@restart) and time used for the X axis origin
1341 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1342 * @record_hdr Pointer on record header of current stats sample.
1343 ***************************************************************************
1345 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1346 unsigned long long itv, struct record_header *record_hdr)
1349 *spc = (struct stats_pcsw *) a->buf[curr],
1350 *spp = (struct stats_pcsw *) a->buf[!curr];
1351 int group[] = {1, 1};
1352 int g_fields[] = {1, 0};
1353 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1354 char *title[] = {"Task creation", "Switching activity"};
1355 char *g_title[] = {"proc/s",
1357 static double *spmin, *spmax;
1359 static int *outsize;
1361 if (action & F_BEGIN) {
1363 * Allocate arrays that will contain the graphs data
1364 * and the min/max values.
1366 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1369 if (action & F_MAIN) {
1370 /* Check for min/max values */
1371 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1372 itv, spmin, spmax, g_fields);
1374 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1375 S_VALUE(spp->processes, spc->processes, itv),
1376 out, outsize, svg_p->restart);
1378 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1379 S_VALUE(spp->context_switch, spc->context_switch, itv),
1380 out + 1, outsize + 1, svg_p->restart);
1383 if (action & F_END) {
1384 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1385 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1387 /* Free remaining structures */
1388 free_graphs(out, outsize, spmin, spmax);
1393 ***************************************************************************
1394 * Display swap statistics in SVG.
1397 * @a Activity structure with statistics.
1398 * @curr Index in array for current sample statistics.
1399 * @action Action expected from current function.
1400 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1401 * flag indicating that a restart record has been previously
1402 * found (.@restart) and time used for the X axis origin
1404 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1405 * @record_hdr Pointer on record header of current stats sample.
1406 ***************************************************************************
1408 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1409 unsigned long long itv, struct record_header *record_hdr)
1412 *ssc = (struct stats_swap *) a->buf[curr],
1413 *ssp = (struct stats_swap *) a->buf[!curr];
1415 int g_type[] = {SVG_LINE_GRAPH};
1416 char *title[] = {"Swap activity"};
1417 char *g_title[] = {"pswpin/s", "pswpout/s" };
1418 int g_fields[] = {0, 1};
1419 static double *spmin, *spmax;
1421 static int *outsize;
1423 if (action & F_BEGIN) {
1425 * Allocate arrays that will contain the graphs data
1426 * and the min/max values.
1428 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1431 if (action & F_MAIN) {
1432 /* Check for min/max values */
1433 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1434 itv, spmin, spmax, g_fields);
1436 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1437 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1438 out, outsize, svg_p->restart);
1440 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1441 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1442 out + 1, outsize + 1, svg_p->restart);
1445 if (action & F_END) {
1446 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1447 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1449 /* Free remaining structures */
1450 free_graphs(out, outsize, spmin, spmax);
1455 ***************************************************************************
1456 * Display paging statistics in SVG.
1459 * @a Activity structure with statistics.
1460 * @curr Index in array for current sample statistics.
1461 * @action Action expected from current function.
1462 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1463 * flag indicating that a restart record has been previously
1464 * found (.@restart) and time used for the X axis origin
1466 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1467 * @record_hdr Pointer on record header of current stats sample.
1468 ***************************************************************************
1470 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1471 unsigned long long itv, struct record_header *record_hdr)
1474 *spc = (struct stats_paging *) a->buf[curr],
1475 *spp = (struct stats_paging *) a->buf[!curr];
1476 int group[] = {2, 2, 4};
1477 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1478 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1479 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1480 "fault/s", "majflt/s",
1481 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1482 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1483 static double *spmin, *spmax;
1485 static int *outsize;
1487 if (action & F_BEGIN) {
1489 * Allocate arrays that will contain the graphs data
1490 * and the min/max values.
1492 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1495 if (action & F_MAIN) {
1496 /* Check for min/max values */
1497 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1498 itv, spmin, spmax, g_fields);
1500 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1501 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1502 out, outsize, svg_p->restart);
1504 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1505 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1506 out + 1, outsize + 1, svg_p->restart);
1508 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1509 S_VALUE(spp->pgfault, spc->pgfault, itv),
1510 out + 2, outsize + 2, svg_p->restart);
1512 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1513 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1514 out + 3, outsize + 3, svg_p->restart);
1516 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1517 S_VALUE(spp->pgfree, spc->pgfree, itv),
1518 out + 4, outsize + 4, svg_p->restart);
1520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1521 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1522 out + 5, outsize + 5, svg_p->restart);
1524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1525 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1526 out + 6, outsize + 6, svg_p->restart);
1528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1529 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1530 out + 7, outsize + 7, svg_p->restart);
1533 if (action & F_END) {
1534 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1535 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1537 /* Free remaining structures */
1538 free_graphs(out, outsize, spmin, spmax);
1543 ***************************************************************************
1544 * Display I/O and transfer rate statistics in SVG.
1547 * @a Activity structure with statistics.
1548 * @curr Index in array for current sample statistics.
1549 * @action Action expected from current function.
1550 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1551 * flag indicating that a restart record has been previously
1552 * found (.@restart) and time used for the X axis origin
1554 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1555 * @record_hdr Pointer on record header of current stats sample.
1556 ***************************************************************************
1558 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1559 unsigned long long itv, struct record_header *record_hdr)
1562 *sic = (struct stats_io *) a->buf[curr],
1563 *sip = (struct stats_io *) a->buf[!curr];
1564 int group[] = {3, 2};
1565 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1566 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1567 char *g_title[] = {"tps", "rtps", "wtps",
1568 "bread/s", "bwrtn/s"};
1569 int g_fields[] = {0, 1, 2, 3, 4};
1570 static double *spmin, *spmax;
1572 static int *outsize;
1574 if (action & F_BEGIN) {
1576 * Allocate arrays that will contain the graphs data
1577 * and the min/max values.
1579 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1582 if (action & F_MAIN) {
1583 /* Check for min/max values */
1584 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1585 itv, spmin, spmax, g_fields);
1588 * If we get negative values, this is probably because
1589 * one or more devices/filesystems have been unmounted.
1590 * We display 0.0 in this case though we should rather tell
1591 * the user that the value cannot be calculated here.
1594 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1595 sic->dk_drive < sip->dk_drive ? 0.0 :
1596 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1597 out, outsize, svg_p->restart);
1599 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1600 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1601 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1602 out + 1, outsize + 1, svg_p->restart);
1604 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1605 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1606 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1607 out + 2, outsize + 2, svg_p->restart);
1609 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1610 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1611 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1612 out + 3, outsize + 3, svg_p->restart);
1614 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1615 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1616 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1617 out + 4, outsize + 4, svg_p->restart);
1620 if (action & F_END) {
1621 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1622 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1624 /* Free remaining structures */
1625 free_graphs(out, outsize, spmin, spmax);
1630 ***************************************************************************
1631 * Display memory statistics in SVG.
1634 * @a Activity structure with statistics.
1635 * @curr Index in array for current sample statistics.
1636 * @action Action expected from current function.
1637 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1638 * flag indicating that a restart record has been previously
1639 * found (.@restart) and time used for the X axis origin
1641 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1642 * @record_hdr Pointer on record header of current stats sample.
1643 ***************************************************************************
1645 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1646 unsigned long long itv, struct record_header *record_hdr)
1649 *smc = (struct stats_memory *) a->buf[curr];
1650 int group1[] = {3, 1, 3, 1, 3, 5};
1651 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1652 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1653 int group2[] = {3, 1, 1};
1654 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1655 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1656 "Memory utilization (3)", "Memory utilization (4)",
1657 "Memory utilization (5)", "Memory utilization (6)"};
1658 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1659 "Swap utilization (3)"};
1660 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1661 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1662 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1664 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1666 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1667 static double *spmin, *spmax;
1669 static int *outsize;
1672 unsigned long long nousedmem;
1674 if (action & F_BEGIN) {
1676 * Allocate arrays that will contain the graphs data
1677 * and the min/max values.
1679 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1682 if (action & F_MAIN) {
1683 /* Check for min/max values */
1684 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1685 itv, spmin, spmax, g_fields);
1686 /* Compute %memused min/max values */
1687 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1688 if (nousedmem > smc->tlmkb) {
1689 nousedmem = smc->tlmkb;
1691 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1692 if (tval > *(spmax + 3)) {
1693 *(spmax + 3) = tval;
1695 if (tval < *(spmin + 3)) {
1696 *(spmin + 3) = tval;
1698 /* Compute %commit min/max values */
1699 tval = (smc->tlmkb + smc->tlskb) ?
1700 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1701 if (tval > *(spmax + 7)) {
1702 *(spmax + 7) = tval;
1704 if (tval < *(spmin + 7)) {
1705 *(spmin + 7) = tval;
1707 /* Compute %swpused min/max values */
1709 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1710 if (tval > *(spmax + 19)) {
1711 *(spmax + 19) = tval;
1713 if (tval < *(spmin + 19)) {
1714 *(spmin + 19) = tval;
1716 /* Compute %swpcad min/max values */
1717 tval = (smc->tlskb - smc->frskb) ?
1718 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1719 if (tval > *(spmax + 20)) {
1720 *(spmax + 20) = tval;
1722 if (tval < *(spmin + 20)) {
1723 *(spmin + 20) = tval;
1725 /* Compute memused min/max values in MB */
1726 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1727 if (tval > *(spmax + 2)) {
1728 *(spmax + 2) = tval;
1730 if (tval < *(spmin + 2)) {
1731 *(spmin + 2) = tval;
1733 /* Compute swpused min/max values in MB */
1734 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1735 if (tval > *(spmax + 17)) {
1736 *(spmax + 17) = tval;
1738 if (tval < *(spmin + 17)) {
1739 *(spmin + 17) = tval;
1743 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1744 ((double) smc->frmkb) / 1024,
1745 out, outsize, svg_p->restart);
1747 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1748 ((double) (smc->tlmkb - nousedmem)) / 1024,
1749 out + 2, outsize + 2, svg_p->restart);
1751 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1752 ((double) smc->availablekb) / 1024,
1753 out + 1, outsize + 1, svg_p->restart);
1755 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1756 ((double) smc->bufkb) / 1024,
1757 out + 4, outsize + 4, svg_p->restart);
1759 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1760 ((double) smc->camkb) / 1024,
1761 out + 5, outsize + 5, svg_p->restart);
1763 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1764 ((double) smc->frskb) / 1024,
1765 out + 16, outsize + 16, svg_p->restart);
1767 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1768 ((double) (smc->tlskb - smc->frskb)) / 1024,
1769 out + 17, outsize + 17, svg_p->restart);
1771 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1772 ((double) smc->caskb) / 1024,
1773 out + 18, outsize + 18, svg_p->restart);
1775 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1776 ((double) smc->comkb) / 1024,
1777 out + 6, outsize + 6, svg_p->restart);
1779 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1780 ((double) smc->activekb) / 1024,
1781 out + 8, outsize + 8, svg_p->restart);
1783 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1784 ((double) smc->inactkb) / 1024,
1785 out + 9, outsize + 9, svg_p->restart);
1787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1788 ((double) smc->dirtykb) / 1024,
1789 out + 10, outsize + 10, svg_p->restart);
1791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1792 ((double) smc->anonpgkb) / 1024,
1793 out + 11, outsize + 11, svg_p->restart);
1795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1796 ((double) smc->slabkb) / 1024,
1797 out + 12, outsize + 12, svg_p->restart);
1799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1800 ((double) smc->kstackkb) / 1024,
1801 out + 13, outsize + 13, svg_p->restart);
1803 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1804 ((double) smc->pgtblkb) / 1024,
1805 out + 14, outsize + 14, svg_p->restart);
1807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1808 ((double) smc->vmusedkb) / 1024,
1809 out + 15, outsize + 15, svg_p->restart);
1811 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1814 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1815 out + 3, outsize + 3, svg_p->dt);
1817 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1819 (smc->tlmkb + smc->tlskb) ?
1820 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1821 out + 7, outsize + 7, svg_p->dt);
1823 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1826 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1827 out + 19, outsize + 19, svg_p->dt);
1829 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1831 (smc->tlskb - smc->frskb) ?
1832 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1833 out + 20, outsize + 20, svg_p->dt);
1836 if (action & F_END) {
1838 /* Conversion kB -> MB */
1839 for (i = 0; i < 17; i++) {
1840 *(spmin + g_fields[i]) /= 1024;
1841 *(spmax + g_fields[i]) /= 1024;
1844 if (DISPLAY_MEMORY(a->opt_flags)) {
1845 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1846 g_type1, title1, g_title1, NULL, group1,
1847 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1850 if (DISPLAY_SWAP(a->opt_flags)) {
1851 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1852 spmin + 16, spmax + 16, out + 16, outsize + 16,
1853 svg_p, record_hdr, FALSE);
1856 /* Free remaining structures */
1857 free_graphs(out, outsize, spmin, spmax);
1862 ***************************************************************************
1863 * Display kernel tables statistics in SVG.
1866 * @a Activity structure with statistics.
1867 * @curr Index in array for current sample statistics.
1868 * @action Action expected from current function.
1869 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1870 * flag indicating that a restart record has been previously
1871 * found (.@restart) and time used for the X axis origin
1873 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1874 * @record_hdr Pointer on record header of current stats sample.
1875 ***************************************************************************
1877 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1878 unsigned long long itv, struct record_header *record_hdr)
1880 struct stats_ktables
1881 *skc = (struct stats_ktables *) a->buf[curr];
1882 int group[] = {3, 1};
1883 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1884 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1885 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1887 int g_fields[] = {1, 2, 0, 3};
1888 static double *spmin, *spmax;
1890 static int *outsize;
1892 if (action & F_BEGIN) {
1894 * Allocate arrays that will contain the graphs data
1895 * and the min/max values.
1897 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1900 if (action & F_MAIN) {
1901 /* Check for min/max values */
1902 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1903 itv, spmin, spmax, g_fields);
1905 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1906 (unsigned long long) skc->dentry_stat,
1907 out, outsize, svg_p->restart);
1909 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1910 (unsigned long long) skc->file_used,
1911 out + 1, outsize + 1, svg_p->restart);
1913 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1914 (unsigned long long) skc->inode_used,
1915 out + 2, outsize + 2, svg_p->restart);
1917 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1918 (unsigned long long) skc->pty_nr,
1919 out + 3, outsize + 3, svg_p->restart);
1922 if (action & F_END) {
1923 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1924 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1926 /* Free remaining structures */
1927 free_graphs(out, outsize, spmin, spmax);
1932 ***************************************************************************
1933 * Display queue and load statistics in SVG.
1936 * @a Activity structure with statistics.
1937 * @curr Index in array for current sample statistics.
1938 * @action Action expected from current function.
1939 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1940 * flag indicating that a restart record has been previously
1941 * found (.@restart) and time used for the X axis origin
1943 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1944 * @record_hdr Pointer on record header of current stats sample.
1945 ***************************************************************************
1947 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1948 unsigned long long itv, struct record_header *record_hdr)
1951 *sqc = (struct stats_queue *) a->buf[curr];
1952 int group[] = {2, 1, 3};
1953 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1954 char *title[] = {"Queue length", "Task list", "Load average"};
1955 char *g_title[] = {"~runq-sz", "~blocked",
1957 "ldavg-1", "ldavg-5", "ldavg-15"};
1958 int g_fields[] = {0, 1, 2, 3, 4, 5};
1959 static double *spmin, *spmax;
1961 static int *outsize;
1963 if (action & F_BEGIN) {
1965 * Allocate arrays that will contain the graphs data
1966 * and the min/max values.
1968 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1971 if (action & F_MAIN) {
1972 /* Check for min/max values */
1973 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1974 itv, spmin, spmax, g_fields);
1976 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1977 (unsigned long long) sqc->nr_running,
1978 out, outsize, svg_p->restart);
1980 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1981 (unsigned long long) sqc->procs_blocked,
1982 out + 1, outsize + 1, svg_p->restart);
1984 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1985 (unsigned long long) sqc->nr_threads,
1986 out + 2, outsize + 2, svg_p->restart);
1988 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1989 (double) sqc->load_avg_1 / 100,
1990 out + 3, outsize + 3, svg_p->restart);
1992 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1993 (double) sqc->load_avg_5 / 100,
1994 out + 4, outsize + 4, svg_p->restart);
1996 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1997 (double) sqc->load_avg_15 / 100,
1998 out + 5, outsize + 5, svg_p->restart);
2001 if (action & F_END) {
2002 /* Fix min/max values for load average */
2003 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2004 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2005 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2007 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2008 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2010 /* Free remaining structures */
2011 free_graphs(out, outsize, spmin, spmax);
2016 ***************************************************************************
2017 * Display disk statistics in SVG.
2020 * @a Activity structure with statistics.
2021 * @curr Index in array for current sample statistics.
2022 * @action Action expected from current function.
2023 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2024 * flag indicating that a restart record has been previously
2025 * found (.@restart) and time used for the X axis origin
2027 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2028 * @record_hdr Pointer on record header of current stats sample.
2029 ***************************************************************************
2031 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2032 unsigned long long itv, struct record_header *record_hdr)
2034 struct stats_disk *sdc, *sdp, sdpzero;
2035 struct ext_disk_stats xds;
2036 int group[] = {1, 2, 2, 2, 1};
2037 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2038 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2039 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
2040 "Disk statistics (3)", "Disk statistics (4)",
2041 "Disk statistics (5)"};
2042 char *g_title[] = {"tps",
2044 "areq-sz", "aqu-sz",
2047 int g_fields[] = {0, 1, 2};
2048 unsigned int local_types_nr[] = {1, 0, 0};
2049 static double *spmin, *spmax;
2051 static int *outsize;
2053 double rkB, wkB, aqusz;
2054 int i, j, k, pos, restart, *unregistered;
2056 if (action & F_BEGIN) {
2058 * Allocate arrays (#0..7) that will contain the graphs data
2059 * and the min/max values.
2060 * Also allocate one additional array (#8) for each disk device:
2061 * spmax + 8 will contain the device major number,
2062 * spmin + 8 will contain the device minor number,
2063 * outsize + 8 will contain a positive value (TRUE) if the device
2064 * has either still not been registered, or has been unregistered.
2066 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2069 if (action & F_MAIN) {
2070 memset(&sdpzero, 0, STATS_DISK_SIZE);
2071 restart = svg_p->restart;
2073 * Mark previously registered devices as now
2074 * possibly unregistered for all graphs.
2076 for (k = 0; k < svg_p->nr_max; k++) {
2077 unregistered = outsize + k * 9 + 8;
2078 if (*unregistered == FALSE) {
2079 *unregistered = MAYBE;
2083 /* For each device structure */
2084 for (i = 0; i < a->nr[curr]; i++) {
2085 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2087 /* Get device name */
2088 item_name = get_sa_devname(sdc->major, sdc->minor, flags);
2091 /* A list of devices has been entered on the command line */
2092 if (!search_sa_dlist(st_dev_list, dlst_dev_idx, item_name))
2093 /* Device not found */
2097 /* Look for corresponding graph */
2098 for (k = 0; k < svg_p->nr_max; k++) {
2099 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2100 (sdc->minor == *(spmin + k * 9 + 8)))
2104 if (k == svg_p->nr_max) {
2105 /* Graph not found: Look for first free entry */
2106 for (k = 0; k < svg_p->nr_max; k++) {
2107 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2110 if (k == svg_p->nr_max) {
2111 /* No free graph entry: Extend all buffers */
2112 reallocate_all_graph_lines(svg_p->nr_max,
2113 &out, &outsize, &spmin, &spmax);
2118 unregistered = outsize + pos + 8;
2121 * If current device was marked as previously unregistered,
2122 * then set restart variable to TRUE so that the graph will be
2123 * discontinuous, and mark it as now registered.
2125 if (*unregistered == TRUE) {
2128 *unregistered = FALSE;
2130 if (*(spmax + pos + 8) == -DBL_MAX) {
2131 /* Save device major and minor numbers (if not already done) */
2132 *(spmax + pos + 8) = sdc->major;
2133 *(spmin + pos + 8) = sdc->minor;
2136 j = check_disk_reg(a, curr, !curr, i);
2138 /* This is a newly registered interface. Previous stats are zero */
2142 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2145 /* Check for min/max values */
2146 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2147 itv, spmin + pos, spmax + pos, g_fields);
2149 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2150 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2151 if (rkB < *(spmin + pos + 1)) {
2152 *(spmin + pos + 1) = rkB;
2154 if (rkB > *(spmax + pos + 1)) {
2155 *(spmax + pos + 1) = rkB;
2157 if (wkB < *(spmin + pos + 2)) {
2158 *(spmin + pos + 2) = wkB;
2160 if (wkB > *(spmax + pos + 2)) {
2161 *(spmax + pos + 2) = wkB;
2164 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2165 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2166 *(spmin + pos + 3) = xds.arqsz / 2;
2168 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2169 *(spmax + pos + 3) = xds.arqsz / 2;
2171 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2172 if (aqusz < *(spmin + pos + 4)) {
2173 *(spmin + pos + 4) = aqusz;
2175 if (aqusz > *(spmax + pos + 4)) {
2176 *(spmax + pos + 4) = aqusz;
2178 if (xds.await < *(spmin + pos + 5)) {
2179 *(spmin + pos + 5) = xds.await;
2181 if (xds.await > *(spmax + pos + 5)) {
2182 *(spmax + pos + 5) = xds.await;
2184 if (xds.svctm < *(spmin + pos + 6)) {
2185 *(spmin + pos + 6) = xds.svctm;
2187 if (xds.svctm > *(spmax + pos + 6)) {
2188 *(spmax + pos + 6) = xds.svctm;
2190 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2191 *(spmin + pos + 7) = xds.util / 10.0;
2193 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2194 *(spmax + pos + 7) = xds.util / 10.0;
2198 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2199 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2200 out + pos, outsize + pos, restart);
2202 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2203 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2204 out + pos + 1, outsize + pos + 1, restart);
2206 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2207 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2208 out + pos + 2, outsize + pos + 2, restart);
2210 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2212 out + pos + 3, outsize + pos + 3, restart);
2214 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2216 out + pos + 4, outsize + pos + 4, restart);
2218 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2220 out + pos + 5, outsize + pos + 5, restart);
2222 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2224 out + pos + 6, outsize + pos + 6, restart);
2226 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2227 0.0, xds.util / 10.0,
2228 out + pos + 7, outsize + pos + 7, svg_p->dt);
2231 /* Mark devices not seen here as now unregistered */
2232 for (k = 0; k < svg_p->nr_max; k++) {
2233 unregistered = outsize + k * 9 + 8;
2234 if (*unregistered != FALSE) {
2235 *unregistered = TRUE;
2240 if (action & F_END) {
2241 for (i = 0; i < svg_p->nr_max; i++) {
2242 /* Check if there is something to display */
2247 /* Get device name */
2248 item_name = get_sa_devname(*(spmax + pos + 8), *(spmin + pos + 8), flags);
2250 draw_activity_graphs(a->g_nr, g_type,
2251 title, g_title, item_name, group,
2252 spmin + pos, spmax + pos, out + pos, outsize + pos,
2253 svg_p, record_hdr, FALSE);
2256 /* Free remaining structures */
2257 free_graphs(out, outsize, spmin, spmax);
2262 ***************************************************************************
2263 * Display network interfaces statistics in SVG.
2266 * @a Activity structure with statistics.
2267 * @curr Index in array for current sample statistics.
2268 * @action Action expected from current function.
2269 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2270 * flag indicating that a restart record has been previously
2271 * found (.@restart) and time used for the X axis origin
2273 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2274 * @record_hdr Pointer on record header of current stats sample.
2275 ***************************************************************************
2277 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2278 unsigned long long itv, struct record_header *record_hdr)
2280 struct stats_net_dev *sndc, *sndp, sndzero;
2281 int group[] = {2, 2, 3, 1};
2282 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2284 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2285 "Network statistics (3)", "Network statistics (4)"};
2286 char *g_title[] = {"rxpck/s", "txpck/s",
2288 "rxcmp/s", "txcmp/s", "rxmcst/s",
2290 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2291 unsigned int local_types_nr[] = {7, 0, 0};
2292 static double *spmin, *spmax;
2294 static int *outsize;
2296 double rxkb, txkb, ifutil;
2297 int i, j, k, pos, restart, *unregistered;
2299 if (action & F_BEGIN) {
2301 * Allocate arrays (#0..7) that will contain the graphs data
2302 * and the min/max values.
2303 * Also allocate one additional array (#8) for each interface:
2304 * out + 8 will contain the interface name,
2305 * outsize + 8 will contain a positive value (TRUE) if the interface
2306 * has either still not been registered, or has been unregistered.
2308 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2311 if (action & F_MAIN) {
2312 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2313 restart = svg_p->restart;
2315 * Mark previously registered interfaces as now
2316 * possibly unregistered for all graphs.
2318 for (k = 0; k < svg_p->nr_max; k++) {
2319 unregistered = outsize + k * 9 + 8;
2320 if (*unregistered == FALSE) {
2321 *unregistered = MAYBE;
2325 /* For each network interfaces structure */
2326 for (i = 0; i < a->nr[curr]; i++) {
2327 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2329 if (dlst_iface_idx) {
2330 /* A list of devices has been entered on the command line */
2331 if (!search_sa_dlist(st_iface_list, dlst_iface_idx, sndc->interface))
2332 /* Device not found */
2336 /* Look for corresponding graph */
2337 for (k = 0; k < svg_p->nr_max; k++) {
2338 item_name = *(out + k * 9 + 8);
2339 if (!strcmp(sndc->interface, item_name))
2343 if (k == svg_p->nr_max) {
2344 /* Graph not found: Look for first free entry */
2345 for (k = 0; k < svg_p->nr_max; k++) {
2346 item_name = *(out + k * 9 + 8);
2347 if (!strcmp(item_name, ""))
2350 if (k == svg_p->nr_max) {
2351 /* No free graph entry: Extend all buffers */
2352 reallocate_all_graph_lines(svg_p->nr_max,
2353 &out, &outsize, &spmin, &spmax);
2359 unregistered = outsize + pos + 8;
2361 j = check_net_dev_reg(a, curr, !curr, i);
2363 /* This is a newly registered interface. Previous stats are zero */
2367 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2371 * If current interface was marked as previously unregistered,
2372 * then set restart variable to TRUE so that the graph will be
2373 * discontinuous, and mark it as now registered.
2375 if (*unregistered == TRUE) {
2378 *unregistered = FALSE;
2380 if (!item_name[0]) {
2381 /* Save network interface name (if not already done) */
2382 strncpy(item_name, sndc->interface, CHUNKSIZE);
2383 item_name[CHUNKSIZE - 1] = '\0';
2386 /* Check for min/max values */
2387 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2388 itv, spmin + pos, spmax + pos, g_fields);
2390 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2391 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2392 ifutil = compute_ifutil(sndc, rxkb, txkb);
2393 if (ifutil < *(spmin + pos + 7)) {
2394 *(spmin + pos + 7) = ifutil;
2396 if (ifutil > *(spmax + pos + 7)) {
2397 *(spmax + pos + 7) = ifutil;
2401 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2402 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2403 out + pos, outsize + pos, restart);
2405 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2406 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2407 out + pos + 1, outsize + pos + 1, restart);
2409 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2411 out + pos + 2, outsize + pos + 2, restart);
2413 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2415 out + pos + 3, outsize + pos + 3, restart);
2417 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2418 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2419 out + pos + 4, outsize + pos + 4, restart);
2421 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2422 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2423 out + pos + 5, outsize + pos + 5, restart);
2425 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2426 S_VALUE(sndp->multicast, sndc->multicast, itv),
2427 out + pos + 6, outsize + pos + 6, restart);
2429 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2431 out + pos + 7, outsize + pos + 7, svg_p->dt);
2434 /* Mark interfaces not seen here as now unregistered */
2435 for (k = 0; k < svg_p->nr_max; k++) {
2436 unregistered = outsize + k * 9 + 8;
2437 if (*unregistered != FALSE) {
2438 *unregistered = TRUE;
2443 if (action & F_END) {
2444 for (i = 0; i < svg_p->nr_max; i++) {
2446 * Check if there is something to display.
2447 * Don't test sndc->interface because maybe the network
2448 * interface has been registered later.
2454 /* Recalculate min and max values in kB, not in B */
2455 *(spmin + pos + 2) /= 1024;
2456 *(spmax + pos + 2) /= 1024;
2457 *(spmin + pos + 3) /= 1024;
2458 *(spmax + pos + 3) /= 1024;
2460 item_name = *(out + pos + 8);
2461 draw_activity_graphs(a->g_nr, g_type,
2462 title, g_title, item_name, group,
2463 spmin + pos, spmax + pos, out + pos, outsize + pos,
2464 svg_p, record_hdr, FALSE);
2467 /* Free remaining structures */
2468 free_graphs(out, outsize, spmin, spmax);
2473 ***************************************************************************
2474 * Display network interface errors statistics in SVG.
2477 * @a Activity structure with statistics.
2478 * @curr Index in array for current sample statistics.
2479 * @action Action expected from current function.
2480 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2481 * flag indicating that a restart record has been previously
2482 * found (.@restart) and time used for the X axis origin
2484 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2485 * @record_hdr Pointer on record header of current stats sample.
2486 ***************************************************************************
2488 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2489 unsigned long long itv, struct record_header *record_hdr)
2491 struct stats_net_edev *snedc, *snedp, snedzero;
2492 int group[] = {2, 2, 2, 3};
2493 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2495 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2496 "Network errors statistics (3)", "Network errors statistics (4)"};
2497 char *g_title[] = {"rxerr/s", "txerr/s",
2498 "rxdrop/s", "txdrop/s",
2499 "rxfifo/s", "txfifo/s",
2500 "coll/s", "txcarr/s", "rxfram/s"};
2501 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2502 static double *spmin, *spmax;
2504 static int *outsize;
2506 int i, j, k, pos, restart, *unregistered;
2508 if (action & F_BEGIN) {
2510 * Allocate arrays (#0..8) that will contain the graphs data
2511 * and the min/max values.
2512 * Also allocate one additional array (#9) for each interface:
2513 * out + 9 will contain the interface name,
2514 * outsize + 9 will contain a positive value (TRUE) if the interface
2515 * has either still not been registered, or has been unregistered.
2517 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
2520 if (action & F_MAIN) {
2521 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2522 restart = svg_p->restart;
2524 * Mark previously registered interfaces as now
2525 * possibly unregistered for all graphs.
2527 for (k = 0; k < svg_p->nr_max; k++) {
2528 unregistered = outsize + k * 10 + 9;
2529 if (*unregistered == FALSE) {
2530 *unregistered = MAYBE;
2534 /* For each network interfaces structure */
2535 for (i = 0; i < a->nr[curr]; i++) {
2536 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2537 if (!strcmp(snedc->interface, ""))
2538 /* Empty structure: This is the end of the list */
2541 if (dlst_iface_idx) {
2542 /* A list of devices has been entered on the command line */
2543 if (!search_sa_dlist(st_iface_list, dlst_iface_idx, snedc->interface))
2544 /* Device not found */
2548 /* Look for corresponding graph */
2549 for (k = 0; k < svg_p->nr_max; k++) {
2550 item_name = *(out + k * 10 + 9);
2551 if (!strcmp(snedc->interface, item_name))
2555 if (k == svg_p->nr_max) {
2556 /* Graph not found: Look for first free entry */
2557 for (k = 0; k < svg_p->nr_max; k++) {
2558 item_name = *(out + k * 10 + 9);
2559 if (!strcmp(item_name, ""))
2562 if (k == svg_p->nr_max) {
2563 /* No free graph entry: Extend all buffers */
2564 reallocate_all_graph_lines(svg_p->nr_max,
2565 &out, &outsize, &spmin, &spmax);
2571 unregistered = outsize + pos + 9;
2573 j = check_net_edev_reg(a, curr, !curr, i);
2575 /* This is a newly registered interface. Previous stats are zero */
2579 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2583 * If current interface was marked as previously unregistered,
2584 * then set restart variable to TRUE so that the graph will be
2585 * discontinuous, and mark it as now registered.
2587 if (*unregistered == TRUE) {
2590 *unregistered = FALSE;
2592 if (!item_name[0]) {
2593 /* Save network interface name (if not already done) */
2594 strncpy(item_name, snedc->interface, CHUNKSIZE);
2595 item_name[CHUNKSIZE - 1] = '\0';
2598 /* Check for min/max values */
2599 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2600 itv, spmin + pos, spmax + pos, g_fields);
2603 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2604 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2605 out + pos, outsize + pos, restart);
2607 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2608 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2609 out + pos + 1, outsize + pos + 1, restart);
2611 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2612 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2613 out + pos + 2, outsize + pos + 2, restart);
2615 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2616 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2617 out + pos + 3, outsize + pos + 3, restart);
2619 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2620 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2621 out + pos + 4, outsize + pos + 4, restart);
2623 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2624 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2625 out + pos + 5, outsize + pos + 5, restart);
2627 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2628 S_VALUE(snedp->collisions, snedc->collisions, itv),
2629 out + pos + 6, outsize + pos + 6, restart);
2631 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2632 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2633 out + pos + 7, outsize + pos + 7, restart);
2635 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2636 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2637 out + pos + 8, outsize + pos + 8, restart);
2640 /* Mark interfaces not seen here as now unregistered */
2641 for (k = 0; k < svg_p->nr_max; k++) {
2642 unregistered = outsize + k * 10 + 9;
2643 if (*unregistered != FALSE) {
2644 *unregistered = TRUE;
2649 if (action & F_END) {
2650 for (i = 0; i < svg_p->nr_max; i++) {
2652 * Check if there is something to display.
2653 * Don't test snedc->interface because maybe the network
2654 * interface has been registered later.
2660 item_name = *(out + pos + 9);
2661 draw_activity_graphs(a->g_nr, g_type,
2662 title, g_title, item_name, group,
2663 spmin + pos, spmax + pos, out + pos, outsize + pos,
2664 svg_p, record_hdr, FALSE);
2667 /* Free remaining structures */
2668 free_graphs(out, outsize, spmin, spmax);
2673 ***************************************************************************
2674 * Display NFS client statistics in SVG.
2677 * @a Activity structure with statistics.
2678 * @curr Index in array for current sample statistics.
2679 * @action Action expected from current function.
2680 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2681 * flag indicating that a restart record has been previously
2682 * found (.@restart) and time used for the X axis origin
2684 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2685 * @record_hdr Pointer on record header of current stats sample.
2686 ***************************************************************************
2688 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2689 unsigned long long itv, struct record_header *record_hdr)
2691 struct stats_net_nfs
2692 *snnc = (struct stats_net_nfs *) a->buf[curr],
2693 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2694 int group[] = {2, 2, 2};
2695 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2696 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2697 "NFS client statistics (3)"};
2698 char *g_title[] = {"call/s", "retrans/s",
2699 "read/s", "write/s",
2700 "access/s", "getatt/s"};
2701 int g_fields[] = {0, 1, 2, 3, 4, 5};
2702 static double *spmin, *spmax;
2704 static int *outsize;
2706 if (action & F_BEGIN) {
2708 * Allocate arrays that will contain the graphs data
2709 * and the min/max values.
2711 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2714 if (action & F_MAIN) {
2715 /* Check for min/max values */
2716 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2717 itv, spmin, spmax, g_fields);
2720 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2721 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2722 out, outsize, svg_p->restart);
2724 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2725 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2726 out + 1, outsize + 1, svg_p->restart);
2728 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2729 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2730 out + 2, outsize + 2, svg_p->restart);
2732 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2733 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2734 out + 3, outsize + 3, svg_p->restart);
2736 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2737 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2738 out + 4, outsize + 4, svg_p->restart);
2740 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2741 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2742 out + 5, outsize + 5, svg_p->restart);
2745 if (action & F_END) {
2746 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2747 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2749 /* Free remaining structures */
2750 free_graphs(out, outsize, spmin, spmax);
2755 ***************************************************************************
2756 * Display NFS server statistics in SVG.
2759 * @a Activity structure with statistics.
2760 * @curr Index in array for current sample statistics.
2761 * @action Action expected from current function.
2762 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2763 * flag indicating that a restart record has been previously
2764 * found (.@restart) and time used for the X axis origin
2766 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2767 * @record_hdr Pointer on record header of current stats sample.
2768 ***************************************************************************
2770 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2771 unsigned long long itv, struct record_header *record_hdr)
2773 struct stats_net_nfsd
2774 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2775 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2776 int group[] = {2, 3, 2, 2, 2};
2777 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2778 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2779 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2780 "NFS server statistics (3)", "NFS server statistics (4)",
2781 "NFS server statistics (5)"};
2782 char *g_title[] = {"scall/s", "badcall/s",
2783 "packet/s", "udp/s", "tcp/s",
2785 "sread/s", "swrite/s",
2786 "saccess/s", "sgetatt/s"};
2787 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2788 static double *spmin, *spmax;
2790 static int *outsize;
2792 if (action & F_BEGIN) {
2794 * Allocate arrays that will contain the graphs data
2795 * and the min/max values.
2797 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2800 if (action & F_MAIN) {
2801 /* Check for min/max values */
2802 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2803 itv, spmin, spmax, g_fields);
2806 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2807 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2808 out, outsize, svg_p->restart);
2810 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2811 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2812 out + 1, outsize + 1, svg_p->restart);
2814 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2815 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2816 out + 2, outsize + 2, svg_p->restart);
2818 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2819 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2820 out + 3, outsize + 3, svg_p->restart);
2822 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2823 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2824 out + 4, outsize + 4, svg_p->restart);
2826 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2827 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2828 out + 5, outsize + 5, svg_p->restart);
2830 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2831 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2832 out + 6, outsize + 6, svg_p->restart);
2834 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2835 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2836 out + 7, outsize + 7, svg_p->restart);
2838 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2839 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2840 out + 8, outsize + 8, svg_p->restart);
2842 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2843 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2844 out + 9, outsize + 9, svg_p->restart);
2846 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2847 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2848 out + 10, outsize + 10, svg_p->restart);
2851 if (action & F_END) {
2852 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2853 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2855 /* Free remaining structures */
2856 free_graphs(out, outsize, spmin, spmax);
2861 ***************************************************************************
2862 * Display network socket statistics in SVG.
2865 * @a Activity structure with statistics.
2866 * @curr Index in array for current sample statistics.
2867 * @action Action expected from current function.
2868 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2869 * flag indicating that a restart record has been previously
2870 * found (.@restart) and time used for the X axis origin
2872 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2873 * @record_hdr Pointer on record header of current stats sample.
2874 ***************************************************************************
2876 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2877 unsigned long long itv, struct record_header *record_hdr)
2879 struct stats_net_sock
2880 *snsc = (struct stats_net_sock *) a->buf[curr];
2881 int group[] = {1, 5};
2882 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2883 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2884 char *g_title[] = {"~totsck",
2885 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2886 int g_fields[] = {0, 1, 5, 2, 3, 4};
2887 static double *spmin, *spmax;
2889 static int *outsize;
2891 if (action & F_BEGIN) {
2893 * Allocate arrays that will contain the graphs data
2894 * and the min/max values.
2896 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2899 if (action & F_MAIN) {
2900 /* Check for min/max values */
2901 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2902 itv, spmin, spmax, g_fields);
2904 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2905 (unsigned long long) snsc->sock_inuse,
2906 out, outsize, svg_p->restart);
2908 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2909 (unsigned long long) snsc->tcp_inuse,
2910 out + 1, outsize + 1, svg_p->restart);
2912 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2913 (unsigned long long) snsc->udp_inuse,
2914 out + 2, outsize + 2, svg_p->restart);
2916 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2917 (unsigned long long) snsc->raw_inuse,
2918 out + 3, outsize + 3, svg_p->restart);
2920 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2921 (unsigned long long) snsc->frag_inuse,
2922 out + 4, outsize + 4, svg_p->restart);
2924 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2925 (unsigned long long) snsc->tcp_tw,
2926 out + 5, outsize + 5, svg_p->restart);
2929 if (action & F_END) {
2930 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2931 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2933 /* Free remaining structures */
2934 free_graphs(out, outsize, spmin, spmax);
2939 ***************************************************************************
2940 * Display IPv4 network statistics in SVG.
2943 * @a Activity structure with statistics.
2944 * @curr Index in array for current sample statistics.
2945 * @action Action expected from current function.
2946 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2947 * flag indicating that a restart record has been previously
2948 * found (.@restart) and time used for the X axis origin
2950 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2951 * @record_hdr Pointer on record header of current stats sample.
2952 ***************************************************************************
2954 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2955 unsigned long long itv, struct record_header *record_hdr)
2958 *snic = (struct stats_net_ip *) a->buf[curr],
2959 *snip = (struct stats_net_ip *) a->buf[!curr];
2960 int group[] = {4, 2, 2};
2961 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2962 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2963 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2964 "asmrq/s", "asmok/s",
2965 "fragok/s", "fragcrt/s"};
2966 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2967 static double *spmin, *spmax;
2969 static int *outsize;
2971 if (action & F_BEGIN) {
2973 * Allocate arrays that will contain the graphs data
2974 * and the min/max values.
2976 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2979 if (action & F_MAIN) {
2980 /* Check for min/max values */
2981 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2982 itv, spmin, spmax, g_fields);
2985 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2986 S_VALUE(snip->InReceives, snic->InReceives, itv),
2987 out, outsize, svg_p->restart);
2989 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2990 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2991 out + 1, outsize + 1, svg_p->restart);
2993 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2994 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2995 out + 2, outsize + 2, svg_p->restart);
2997 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2998 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2999 out + 3, outsize + 3, svg_p->restart);
3001 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3002 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3003 out + 4, outsize + 4, svg_p->restart);
3005 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3006 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3007 out + 5, outsize + 5, svg_p->restart);
3009 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3010 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3011 out + 6, outsize + 6, svg_p->restart);
3013 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3014 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3015 out + 7, outsize + 7, svg_p->restart);
3018 if (action & F_END) {
3019 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3020 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3022 /* Free remaining structures */
3023 free_graphs(out, outsize, spmin, spmax);
3028 ***************************************************************************
3029 * Display IPv4 network errors statistics in SVG.
3032 * @a Activity structure with statistics.
3033 * @curr Index in array for current sample statistics.
3034 * @action Action expected from current function.
3035 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3036 * flag indicating that a restart record has been previously
3037 * found (.@restart) and time used for the X axis origin
3039 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3040 * @record_hdr Pointer on record header of current stats sample.
3041 ***************************************************************************
3043 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3044 unsigned long long itv, struct record_header *record_hdr)
3046 struct stats_net_eip
3047 *sneic = (struct stats_net_eip *) a->buf[curr],
3048 *sneip = (struct stats_net_eip *) a->buf[!curr];
3049 int group[] = {3, 2, 3};
3050 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3051 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
3052 "IPv4 network errors statistics (3)"};
3053 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3054 "idisc/s", "odisc/s",
3055 "onort/s", "asmf/s", "fragf/s"};
3056 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3057 static double *spmin, *spmax;
3059 static int *outsize;
3061 if (action & F_BEGIN) {
3063 * Allocate arrays that will contain the graphs data
3064 * and the min/max values.
3066 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3069 if (action & F_MAIN) {
3070 /* Check for min/max values */
3071 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3072 itv, spmin, spmax, g_fields);
3075 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3076 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3077 out, outsize, svg_p->restart);
3079 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3080 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3081 out + 1, outsize + 1, svg_p->restart);
3083 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3084 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3085 out + 2, outsize + 2, svg_p->restart);
3087 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3088 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3089 out + 3, outsize + 3, svg_p->restart);
3091 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3092 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3093 out + 4, outsize + 4, svg_p->restart);
3095 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3096 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3097 out + 5, outsize + 5, svg_p->restart);
3099 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3100 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3101 out + 6, outsize + 6, svg_p->restart);
3103 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3104 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3105 out + 7, outsize + 7, svg_p->restart);
3108 if (action & F_END) {
3109 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3110 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3112 /* Free remaining structures */
3113 free_graphs(out, outsize, spmin, spmax);
3118 ***************************************************************************
3119 * Display ICMPv4 network statistics in SVG.
3122 * @a Activity structure with statistics.
3123 * @curr Index in array for current sample statistics.
3124 * @action Action expected from current function.
3125 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3126 * flag indicating that a restart record has been previously
3127 * found (.@restart) and time used for the X axis origin
3129 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3130 * @record_hdr Pointer on record header of current stats sample.
3131 ***************************************************************************
3133 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3134 unsigned long long itv, struct record_header *record_hdr)
3136 struct stats_net_icmp
3137 *snic = (struct stats_net_icmp *) a->buf[curr],
3138 *snip = (struct stats_net_icmp *) a->buf[!curr];
3139 int group[] = {2, 4, 4, 4};
3140 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3142 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3143 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3144 char *g_title[] = {"imsg/s", "omsg/s",
3145 "iech/s", "iechr/s", "oech/s", "oechr/s",
3146 "itm/s", "itmr/s", "otm/s", "otmr/s",
3147 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3148 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3149 static double *spmin, *spmax;
3151 static int *outsize;
3153 if (action & F_BEGIN) {
3155 * Allocate arrays that will contain the graphs data
3156 * and the min/max values.
3158 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3161 if (action & F_MAIN) {
3162 /* Check for min/max values */
3163 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3164 itv, spmin, spmax, g_fields);
3167 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3168 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3169 out, outsize, svg_p->restart);
3171 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3172 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3173 out + 1, outsize + 1, svg_p->restart);
3175 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3176 S_VALUE(snip->InEchos, snic->InEchos, itv),
3177 out + 2, outsize + 2, svg_p->restart);
3179 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3180 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3181 out + 3, outsize + 3, svg_p->restart);
3183 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3184 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3185 out + 4, outsize + 4, svg_p->restart);
3187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3188 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3189 out + 5, outsize + 5, svg_p->restart);
3191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3192 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3193 out + 6, outsize + 6, svg_p->restart);
3195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3196 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3197 out + 7, outsize + 7, svg_p->restart);
3199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3200 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3201 out + 8, outsize + 8, svg_p->restart);
3203 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3204 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3205 out + 9, outsize + 9, svg_p->restart);
3207 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3208 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3209 out + 10, outsize + 10, svg_p->restart);
3211 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3212 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3213 out + 11, outsize + 11, svg_p->restart);
3215 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3216 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3217 out + 12, outsize + 12, svg_p->restart);
3219 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3220 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3221 out + 13, outsize + 13, svg_p->restart);
3224 if (action & F_END) {
3225 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3226 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3228 /* Free remaining structures */
3229 free_graphs(out, outsize, spmin, spmax);
3234 ***************************************************************************
3235 * Display ICMPv4 network errors statistics in SVG.
3238 * @a Activity structure with statistics.
3239 * @curr Index in array for current sample statistics.
3240 * @action Action expected from current function.
3241 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3242 * flag indicating that a restart record has been previously
3243 * found (.@restart) and time used for the X axis origin
3245 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3246 * @record_hdr Pointer on record header of current stats sample.
3247 ***************************************************************************
3249 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3250 unsigned long long itv, struct record_header *record_hdr)
3252 struct stats_net_eicmp
3253 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3254 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3255 int group[] = {2, 2, 2, 2, 2, 2};
3256 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3257 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3258 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3259 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3260 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3261 char *g_title[] = {"ierr/s", "oerr/s",
3262 "idstunr/s", "odstunr/s",
3263 "itmex/s", "otmex/s",
3264 "iparmpb/s", "oparmpb/s",
3265 "isrcq/s", "osrcq/s",
3266 "iredir/s", "oredir/s"};
3267 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3268 static double *spmin, *spmax;
3270 static int *outsize;
3272 if (action & F_BEGIN) {
3274 * Allocate arrays that will contain the graphs data
3275 * and the min/max values.
3277 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3280 if (action & F_MAIN) {
3281 /* Check for min/max values */
3282 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3283 itv, spmin, spmax, g_fields);
3286 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3287 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3288 out, outsize, svg_p->restart);
3290 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3291 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3292 out + 1, outsize + 1, svg_p->restart);
3294 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3295 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3296 out + 2, outsize + 2, svg_p->restart);
3298 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3299 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3300 out + 3, outsize + 3, svg_p->restart);
3302 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3303 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3304 out + 4, outsize + 4, svg_p->restart);
3306 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3307 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3308 out + 5, outsize + 5, svg_p->restart);
3310 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3311 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3312 out + 6, outsize + 6, svg_p->restart);
3314 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3315 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3316 out + 7, outsize + 7, svg_p->restart);
3318 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3319 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3320 out + 8, outsize + 8, svg_p->restart);
3322 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3323 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3324 out + 9, outsize + 9, svg_p->restart);
3326 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3327 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3328 out + 10, outsize + 10, svg_p->restart);
3330 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3331 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3332 out + 11, outsize + 11, svg_p->restart);
3335 if (action & F_END) {
3336 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3337 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3339 /* Free remaining structures */
3340 free_graphs(out, outsize, spmin, spmax);
3345 ***************************************************************************
3346 * Display TCPv4 network statistics in SVG.
3349 * @a Activity structure with statistics.
3350 * @curr Index in array for current sample statistics.
3351 * @action Action expected from current function.
3352 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3353 * flag indicating that a restart record has been previously
3354 * found (.@restart) and time used for the X axis origin
3356 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3357 * @record_hdr Pointer on record header of current stats sample.
3358 ***************************************************************************
3360 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3361 unsigned long long itv, struct record_header *record_hdr)
3363 struct stats_net_tcp
3364 *sntc = (struct stats_net_tcp *) a->buf[curr],
3365 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3366 int group[] = {2, 2};
3367 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3368 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3369 char *g_title[] = {"active/s", "passive/s",
3370 "iseg/s", "oseg/s"};
3371 int g_fields[] = {0, 1, 2, 3};
3372 static double *spmin, *spmax;
3374 static int *outsize;
3376 if (action & F_BEGIN) {
3378 * Allocate arrays that will contain the graphs data
3379 * and the min/max values.
3381 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3384 if (action & F_MAIN) {
3385 /* Check for min/max values */
3386 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3387 itv, spmin, spmax, g_fields);
3390 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3391 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3392 out, outsize, svg_p->restart);
3394 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3395 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3396 out + 1, outsize + 1, svg_p->restart);
3398 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3399 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3400 out + 2, outsize + 2, svg_p->restart);
3402 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3403 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3404 out + 3, outsize + 3, svg_p->restart);
3407 if (action & F_END) {
3408 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3409 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3411 /* Free remaining structures */
3412 free_graphs(out, outsize, spmin, spmax);
3417 ***************************************************************************
3418 * Display TCPv4 network errors statistics in SVG.
3421 * @a Activity structure with statistics.
3422 * @curr Index in array for current sample statistics.
3423 * @action Action expected from current function.
3424 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3425 * flag indicating that a restart record has been previously
3426 * found (.@restart) and time used for the X axis origin
3428 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3429 * @record_hdr Pointer on record header of current stats sample.
3430 ***************************************************************************
3432 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3433 unsigned long long itv, struct record_header *record_hdr)
3435 struct stats_net_etcp
3436 *snetc = (struct stats_net_etcp *) a->buf[curr],
3437 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3438 int group[] = {2, 3};
3439 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3440 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3441 char *g_title[] = {"atmptf/s", "estres/s",
3442 "retrans/s", "isegerr/s", "orsts/s"};
3443 int g_fields[] = {0, 1, 2, 3, 4};
3444 static double *spmin, *spmax;
3446 static int *outsize;
3448 if (action & F_BEGIN) {
3450 * Allocate arrays that will contain the graphs data
3451 * and the min/max values.
3453 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3456 if (action & F_MAIN) {
3457 /* Check for min/max values */
3458 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3459 itv, spmin, spmax, g_fields);
3462 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3463 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3464 out, outsize, svg_p->restart);
3466 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3467 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3468 out + 1, outsize + 1, svg_p->restart);
3470 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3471 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3472 out + 2, outsize + 2, svg_p->restart);
3474 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3475 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3476 out + 3, outsize + 3, svg_p->restart);
3478 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3479 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3480 out + 4, outsize + 4, svg_p->restart);
3483 if (action & F_END) {
3484 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3485 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3487 /* Free remaining structures */
3488 free_graphs(out, outsize, spmin, spmax);
3493 ***************************************************************************
3494 * Display UDPv4 network statistics in SVG.
3497 * @a Activity structure with statistics.
3498 * @curr Index in array for current sample statistics.
3499 * @action Action expected from current function.
3500 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3501 * flag indicating that a restart record has been previously
3502 * found (.@restart) and time used for the X axis origin
3504 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3505 * @record_hdr Pointer on record header of current stats sample.
3506 ***************************************************************************
3508 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3509 unsigned long long itv, struct record_header *record_hdr)
3511 struct stats_net_udp
3512 *snuc = (struct stats_net_udp *) a->buf[curr],
3513 *snup = (struct stats_net_udp *) a->buf[!curr];
3514 int group[] = {2, 2};
3515 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3516 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3517 char *g_title[] = {"idgm/s", "odgm/s",
3518 "noport/s", "idgmerr/s"};
3519 int g_fields[] = {0, 1, 2, 3};
3520 static double *spmin, *spmax;
3522 static int *outsize;
3524 if (action & F_BEGIN) {
3526 * Allocate arrays that will contain the graphs data
3527 * and the min/max values.
3529 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3532 if (action & F_MAIN) {
3533 /* Check for min/max values */
3534 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3535 itv, spmin, spmax, g_fields);
3538 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3539 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3540 out, outsize, svg_p->restart);
3542 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3543 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3544 out + 1, outsize + 1, svg_p->restart);
3546 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3547 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3548 out + 2, outsize + 2, svg_p->restart);
3550 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3551 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3552 out + 3, outsize + 3, svg_p->restart);
3555 if (action & F_END) {
3556 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3557 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3559 /* Free remaining structures */
3560 free_graphs(out, outsize, spmin, spmax);
3565 ***************************************************************************
3566 * Display IPV6 network socket statistics in SVG.
3569 * @a Activity structure with statistics.
3570 * @curr Index in array for current sample statistics.
3571 * @action Action expected from current function.
3572 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3573 * flag indicating that a restart record has been previously
3574 * found (.@restart) and time used for the X axis origin
3576 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3577 * @record_hdr Pointer on record header of current stats sample.
3578 ***************************************************************************
3580 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3581 unsigned long long itv, struct record_header *record_hdr)
3583 struct stats_net_sock6
3584 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3586 int g_type[] = {SVG_LINE_GRAPH};
3587 char *title[] = {"IPv6 network sockets"};
3588 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3589 int g_fields[] = {0, 1, 2, 3};
3590 static double *spmin, *spmax;
3592 static int *outsize;
3594 if (action & F_BEGIN) {
3596 * Allocate arrays that will contain the graphs data
3597 * and the min/max values.
3599 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3602 if (action & F_MAIN) {
3603 /* Check for min/max values */
3604 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3605 itv, spmin, spmax, g_fields);
3607 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3608 (unsigned long long) snsc->tcp6_inuse,
3609 out, outsize, svg_p->restart);
3611 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3612 (unsigned long long) snsc->udp6_inuse,
3613 out + 1, outsize + 1, svg_p->restart);
3615 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3616 (unsigned long long) snsc->raw6_inuse,
3617 out + 2, outsize + 2, svg_p->restart);
3619 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3620 (unsigned long long) snsc->frag6_inuse,
3621 out + 3, outsize + 3, svg_p->restart);
3624 if (action & F_END) {
3625 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3626 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3628 /* Free remaining structures */
3629 free_graphs(out, outsize, spmin, spmax);
3634 ***************************************************************************
3635 * Display IPv6 network statistics in SVG.
3638 * @a Activity structure with statistics.
3639 * @curr Index in array for current sample statistics.
3640 * @action Action expected from current function.
3641 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3642 * flag indicating that a restart record has been previously
3643 * found (.@restart) and time used for the X axis origin
3645 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3646 * @record_hdr Pointer on record header of current stats sample.
3647 ***************************************************************************
3649 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3650 unsigned long long itv, struct record_header *record_hdr)
3652 struct stats_net_ip6
3653 *snic = (struct stats_net_ip6 *) a->buf[curr],
3654 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3655 int group[] = {4, 2, 2, 2};
3656 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3658 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3659 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3660 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3661 "asmrq6/s", "asmok6/s",
3662 "imcpck6/s", "omcpck6/s",
3663 "fragok6/s", "fragcr6/s"};
3664 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3665 static double *spmin, *spmax;
3667 static int *outsize;
3669 if (action & F_BEGIN) {
3671 * Allocate arrays that will contain the graphs data
3672 * and the min/max values.
3674 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3677 if (action & F_MAIN) {
3678 /* Check for min/max values */
3679 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3680 itv, spmin, spmax, g_fields);
3683 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3684 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3685 out, outsize, svg_p->restart);
3687 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3688 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3689 out + 1, outsize + 1, svg_p->restart);
3691 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3692 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3693 out + 2, outsize + 2, svg_p->restart);
3695 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3696 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3697 out + 3, outsize + 3, svg_p->restart);
3699 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3700 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3701 out + 4, outsize + 4, svg_p->restart);
3703 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3704 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3705 out + 5, outsize + 5, svg_p->restart);
3707 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3708 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3709 out + 6, outsize + 6, svg_p->restart);
3711 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3712 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3713 out + 7, outsize + 7, svg_p->restart);
3715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3716 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3717 out + 8, outsize + 8, svg_p->restart);
3719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3720 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3721 out + 9, outsize + 9, svg_p->restart);
3724 if (action & F_END) {
3725 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3726 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3728 /* Free remaining structures */
3729 free_graphs(out, outsize, spmin, spmax);
3734 ***************************************************************************
3735 * Display IPv6 network errors statistics in SVG.
3738 * @a Activity structure with statistics.
3739 * @curr Index in array for current sample statistics.
3740 * @action Action expected from current function.
3741 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3742 * flag indicating that a restart record has been previously
3743 * found (.@restart) and time used for the X axis origin
3745 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3746 * @record_hdr Pointer on record header of current stats sample.
3747 ***************************************************************************
3749 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3750 unsigned long long itv, struct record_header *record_hdr)
3752 struct stats_net_eip6
3753 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3754 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3755 int group[] = {4, 2, 2, 3};
3756 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3758 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3759 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3760 "IPv6 network errors statistics (5)"};
3761 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3762 "idisc6/s", "odisc6/s",
3763 "inort6/s", "onort6/s",
3764 "asmf6/s", "fragf6/s", "itrpck6/s"};
3765 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3766 static double *spmin, *spmax;
3768 static int *outsize;
3770 if (action & F_BEGIN) {
3772 * Allocate arrays that will contain the graphs data
3773 * and the min/max values.
3775 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3778 if (action & F_MAIN) {
3779 /* Check for min/max values */
3780 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3781 itv, spmin, spmax, g_fields);
3784 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3785 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3786 out, outsize, svg_p->restart);
3788 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3789 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3790 out + 1, outsize + 1, svg_p->restart);
3792 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3793 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3794 out + 2, outsize + 2, svg_p->restart);
3796 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3797 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3798 out + 3, outsize + 3, svg_p->restart);
3800 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3801 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3802 out + 4, outsize + 4, svg_p->restart);
3804 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3805 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3806 out + 5, outsize + 5, svg_p->restart);
3808 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3809 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3810 out + 6, outsize + 6, svg_p->restart);
3812 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3813 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3814 out + 7, outsize + 7, svg_p->restart);
3816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3817 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3818 out + 8, outsize + 8, svg_p->restart);
3820 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3821 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3822 out + 9, outsize + 9, svg_p->restart);
3824 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3825 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3826 out + 10, outsize + 10, svg_p->restart);
3829 if (action & F_END) {
3830 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3831 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3833 /* Free remaining structures */
3834 free_graphs(out, outsize, spmin, spmax);
3839 ***************************************************************************
3840 * Display ICMPv6 network statistics in SVG.
3843 * @a Activity structure with statistics.
3844 * @curr Index in array for current sample statistics.
3845 * @action Action expected from current function.
3846 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3847 * flag indicating that a restart record has been previously
3848 * found (.@restart) and time used for the X axis origin
3850 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3851 * @record_hdr Pointer on record header of current stats sample.
3852 ***************************************************************************
3854 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3855 unsigned long long itv, struct record_header *record_hdr)
3857 struct stats_net_icmp6
3858 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3859 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3860 int group[] = {2, 3, 5, 3, 4};
3861 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3862 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3863 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3864 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3865 "ICMPv6 network statistics (5)"};
3866 char *g_title[] = {"imsg6/s", "omsg6/s",
3867 "iech6/s", "iechr6/s", "oechr6/s",
3868 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3869 "irtsol6/s", "ortsol6/s", "irtad6/s",
3870 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3871 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3872 static double *spmin, *spmax;
3874 static int *outsize;
3876 if (action & F_BEGIN) {
3878 * Allocate arrays that will contain the graphs data
3879 * and the min/max values.
3881 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3884 if (action & F_MAIN) {
3885 /* Check for min/max values */
3886 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3887 itv, spmin, spmax, g_fields);
3890 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3891 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3892 out, outsize, svg_p->restart);
3894 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3895 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3896 out + 1, outsize + 1, svg_p->restart);
3898 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3899 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3900 out + 2, outsize + 2, svg_p->restart);
3902 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3903 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3904 out + 3, outsize + 3, svg_p->restart);
3906 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3907 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3908 out + 4, outsize + 4, svg_p->restart);
3910 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3911 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3912 out + 5, outsize + 5, svg_p->restart);
3914 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3915 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3916 out + 6, outsize + 6, svg_p->restart);
3918 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3919 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3920 out + 7, outsize + 7, svg_p->restart);
3922 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3923 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3924 out + 8, outsize + 8, svg_p->restart);
3926 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3927 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3928 out + 9, outsize + 9, svg_p->restart);
3930 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3931 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3932 out + 10, outsize + 10, svg_p->restart);
3934 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3935 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3936 out + 11, outsize + 11, svg_p->restart);
3938 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3939 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3940 out + 12, outsize + 12, svg_p->restart);
3942 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3943 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3944 out + 13, outsize + 13, svg_p->restart);
3946 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3947 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3948 out + 14, outsize + 14, svg_p->restart);
3950 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3951 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3952 out + 15, outsize + 15, svg_p->restart);
3954 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3955 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3956 out + 16, outsize + 16, svg_p->restart);
3959 if (action & F_END) {
3960 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3961 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3963 /* Free remaining structures */
3964 free_graphs(out, outsize, spmin, spmax);
3969 ***************************************************************************
3970 * Display ICMPv6 network errors statistics in SVG.
3973 * @a Activity structure with statistics.
3974 * @curr Index in array for current sample statistics.
3975 * @action Action expected from current function.
3976 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3977 * flag indicating that a restart record has been previously
3978 * found (.@restart) and time used for the X axis origin
3980 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3981 * @record_hdr Pointer on record header of current stats sample.
3982 ***************************************************************************
3984 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3985 unsigned long long itv, struct record_header *record_hdr)
3987 struct stats_net_eicmp6
3988 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3989 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3990 int group[] = {1, 2, 2, 2, 2, 2};
3991 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3992 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3993 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3994 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3995 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3996 char *g_title[] = {"ierr6/s",
3997 "idtunr6/s", "odtunr6/s",
3998 "itmex6/s", "otmex6/s",
3999 "iprmpb6/s", "oprmpb6/s",
4000 "iredir6/s", "oredir6/s",
4001 "ipck2b6/s", "opck2b6/s"};
4002 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4003 static double *spmin, *spmax;
4005 static int *outsize;
4007 if (action & F_BEGIN) {
4009 * Allocate arrays that will contain the graphs data
4010 * and the min/max values.
4012 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4015 if (action & F_MAIN) {
4016 /* Check for min/max values */
4017 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4018 itv, spmin, spmax, g_fields);
4021 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4022 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4023 out, outsize, svg_p->restart);
4025 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4026 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4027 out + 1, outsize + 1, svg_p->restart);
4029 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4030 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4031 out + 2, outsize + 2, svg_p->restart);
4033 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4034 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4035 out + 3, outsize + 3, svg_p->restart);
4037 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4038 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4039 out + 4, outsize + 4, svg_p->restart);
4041 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4042 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4043 out + 5, outsize + 5, svg_p->restart);
4045 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4046 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4047 out + 6, outsize + 6, svg_p->restart);
4049 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4050 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4051 out + 7, outsize + 7, svg_p->restart);
4053 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4054 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4055 out + 8, outsize + 8, svg_p->restart);
4057 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4058 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4059 out + 9, outsize + 9, svg_p->restart);
4061 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4062 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4063 out + 10, outsize + 10, svg_p->restart);
4066 if (action & F_END) {
4067 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4068 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4070 /* Free remaining structures */
4071 free_graphs(out, outsize, spmin, spmax);
4076 ***************************************************************************
4077 * Display UDPv6 network statistics in SVG.
4080 * @a Activity structure with statistics.
4081 * @curr Index in array for current sample statistics.
4082 * @action Action expected from current function.
4083 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4084 * flag indicating that a restart record has been previously
4085 * found (.@restart) and time used for the X axis origin
4087 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4088 * @record_hdr Pointer on record header of current stats sample.
4089 ***************************************************************************
4091 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4092 unsigned long long itv, struct record_header *record_hdr)
4094 struct stats_net_udp6
4095 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4096 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4097 int group[] = {2, 2};
4098 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4099 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
4100 char *g_title[] = {"idgm6/s", "odgm6/s",
4101 "noport6/s", "idgmer6/s"};
4102 int g_fields[] = {0, 1, 2, 3};
4103 static double *spmin, *spmax;
4105 static int *outsize;
4107 if (action & F_BEGIN) {
4109 * Allocate arrays that will contain the graphs data
4110 * and the min/max values.
4112 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4115 if (action & F_MAIN) {
4116 /* Check for min/max values */
4117 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4118 itv, spmin, spmax, g_fields);
4121 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4122 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4123 out, outsize, svg_p->restart);
4125 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4126 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4127 out + 1, outsize + 1, svg_p->restart);
4129 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4130 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4131 out + 2, outsize + 2, svg_p->restart);
4133 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4134 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4135 out + 3, outsize + 3, svg_p->restart);
4138 if (action & F_END) {
4139 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4140 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4142 /* Free remaining structures */
4143 free_graphs(out, outsize, spmin, spmax);
4148 ***************************************************************************
4149 * Display CPU frequency statistics in SVG.
4152 * @a Activity structure with statistics.
4153 * @curr Index in array for current sample statistics.
4154 * @action Action expected from current function.
4155 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4156 * flag indicating that a restart record has been previously
4157 * found (.@restart) and time used for the X axis origin
4159 * @itv Interval of time in 1/100th of a second (unused here).
4160 * @record_hdr Pointer on record header of current stats sample.
4161 ***************************************************************************
4163 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4164 unsigned long long itv, struct record_header *record_hdr)
4166 struct stats_pwr_cpufreq *spc, *spp;
4168 int g_type[] = {SVG_LINE_GRAPH};
4169 char *title[] = {"CPU frequency"};
4170 char *g_title[] = {"MHz"};
4171 static double *spmin, *spmax;
4173 static int *outsize;
4177 if (action & F_BEGIN) {
4179 * Allocate arrays that will contain the graphs data
4180 * and the min/max values.
4182 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4185 if (action & F_MAIN) {
4187 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4189 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4190 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4192 /* Should current CPU (including CPU "all") be displayed? */
4193 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4198 * Note: Don't skip offline CPU here as it is needed
4199 * to make the graph go though 0.
4203 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4204 ((double) spp->cpufreq) / 100,
4205 ((double) spc->cpufreq) / 100,
4206 out + i, outsize + i, svg_p->restart, svg_p->dt,
4207 spmin + i, spmax + i);
4211 if (action & F_END) {
4212 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
4214 /* Should current CPU (including CPU "all") be displayed? */
4215 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4220 /* This is CPU "all" */
4221 strcpy(item_name, "all");
4225 * If the maximum frequency reached by the CPU is 0, then
4226 * the CPU has been offline on the whole period.
4227 * => Don't display it.
4229 if (*(spmax + i) == 0)
4232 sprintf(item_name, "%d", i - 1);
4235 draw_activity_graphs(a->g_nr, g_type,
4236 title, g_title, item_name, group,
4237 spmin + i, spmax + i, out + i, outsize + i,
4238 svg_p, record_hdr, i);
4241 /* Free remaining structures */
4242 free_graphs(out, outsize, spmin, spmax);
4247 ***************************************************************************
4248 * Display fan statistics in SVG.
4251 * @a Activity structure with statistics.
4252 * @curr Index in array for current sample statistics.
4253 * @action Action expected from current function.
4254 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4255 * flag indicating that a restart record has been previously
4256 * found (.@restart) and time used for the X axis origin
4258 * @itv Interval of time in 1/100th of a second (unused here).
4259 * @record_hdr Pointer on record header of current stats sample.
4260 ***************************************************************************
4262 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4263 unsigned long long itv, struct record_header *record_hdr)
4265 struct stats_pwr_fan *spc, *spp;
4267 int g_type[] = {SVG_LINE_GRAPH};
4268 char *title[] = {"Fan speed"};
4269 char *g_title[] = {"~rpm"};
4270 static double *spmin, *spmax;
4272 static int *outsize;
4273 char item_name[MAX_SENSORS_DEV_LEN + 8];
4276 if (action & F_BEGIN) {
4278 * Allocate arrays that will contain the graphs data
4279 * and the min/max values.
4281 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4284 if (action & F_MAIN) {
4286 for (i = 0; i < a->nr[curr]; i++) {
4288 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4289 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4292 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4295 out + i, outsize + i, svg_p->restart, svg_p->dt,
4296 spmin + i, spmax + i);
4300 if (action & F_END) {
4301 for (i = 0; i < svg_p->nr_max; i++) {
4303 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4305 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4306 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4308 draw_activity_graphs(a->g_nr, g_type,
4309 title, g_title, item_name, group,
4310 spmin + i, spmax + i, out + i, outsize + i,
4311 svg_p, record_hdr, FALSE);
4314 /* Free remaining structures */
4315 free_graphs(out, outsize, spmin, spmax);
4320 ***************************************************************************
4321 * Display temperature statistics in SVG.
4324 * @a Activity structure with statistics.
4325 * @curr Index in array for current sample statistics.
4326 * @action Action expected from current function.
4327 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4328 * flag indicating that a restart record has been previously
4329 * found (.@restart) and time used for the X axis origin
4331 * @itv Interval of time in 1/100th of a second (unused here).
4332 * @record_hdr Pointer on record header of current stats sample.
4333 ***************************************************************************
4335 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4336 unsigned long long itv, struct record_header *record_hdr)
4338 struct stats_pwr_temp *spc;
4339 int group[] = {1, 1};
4340 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4341 char *title[] = {"Device temperature (1)",
4342 "Device temperature (2)"};
4343 char *g_title[] = {"~degC",
4345 static double *spmin, *spmax;
4347 static int *outsize;
4348 char item_name[MAX_SENSORS_DEV_LEN + 8];
4352 if (action & F_BEGIN) {
4354 * Allocate arrays that will contain the graphs data
4355 * and the min/max values.
4357 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4360 if (action & F_MAIN) {
4361 /* For each temperature sensor */
4362 for (i = 0; i < a->nr[curr]; i++) {
4364 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4366 /* Look for min/max values */
4367 if (spc->temp < *(spmin + 2 * i)) {
4368 *(spmin + 2 * i) = spc->temp;
4370 if (spc->temp > *(spmax + 2 * i)) {
4371 *(spmax + 2 * i) = spc->temp;
4373 tval = (spc->temp_max - spc->temp_min) ?
4374 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4376 if (tval < *(spmin + 2 * i + 1)) {
4377 *(spmin + 2 * i + 1) = tval;
4379 if (tval > *(spmax + 2 * i + 1)) {
4380 *(spmax + 2 * i + 1) = tval;
4384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4386 out + 2 * i, outsize + 2 * i, svg_p->restart);
4388 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4390 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4394 if (action & F_END) {
4395 for (i = 0; i < svg_p->nr_max; i++) {
4397 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4399 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4400 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4402 draw_activity_graphs(a->g_nr, g_type,
4403 title, g_title, item_name, group,
4404 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4405 svg_p, record_hdr, FALSE);
4408 /* Free remaining structures */
4409 free_graphs(out, outsize, spmin, spmax);
4414 ***************************************************************************
4415 * Display voltage inputs statistics in SVG.
4418 * @a Activity structure with statistics.
4419 * @curr Index in array for current sample statistics.
4420 * @action Action expected from current function.
4421 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4422 * flag indicating that a restart record has been previously
4423 * found (.@restart) and time used for the X axis origin
4425 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4426 * @record_hdr Pointer on record header of current stats sample.
4427 ***************************************************************************
4429 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4430 unsigned long long itv, struct record_header *record_hdr)
4432 struct stats_pwr_in *spc;
4433 int group[] = {1, 1};
4434 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4435 char *title[] = {"Voltage inputs (1)",
4436 "Voltage inputs (2)"};
4437 char *g_title[] = {"inV",
4439 static double *spmin, *spmax;
4441 static int *outsize;
4442 char item_name[MAX_SENSORS_DEV_LEN + 8];
4446 if (action & F_BEGIN) {
4448 * Allocate arrays that will contain the graphs data
4449 * and the min/max values.
4451 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4454 if (action & F_MAIN) {
4455 /* For each voltage input sensor */
4456 for (i = 0; i < a->nr[curr]; i++) {
4458 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4460 /* Look for min/max values */
4461 if (spc->in < *(spmin + 2 * i)) {
4462 *(spmin + 2 * i) = spc->in;
4464 if (spc->in > *(spmax + 2 * i)) {
4465 *(spmax + 2 * i) = spc->in;
4467 tval = (spc->in_max - spc->in_min) ?
4468 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4470 if (tval < *(spmin + 2 * i + 1)) {
4471 *(spmin + 2 * i + 1) = tval;
4473 if (tval > *(spmax + 2 * i + 1)) {
4474 *(spmax + 2 * i + 1) = tval;
4478 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4480 out + 2 * i, outsize + 2 * i, svg_p->restart);
4482 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4484 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4488 if (action & F_END) {
4489 for (i = 0; i < svg_p->nr_max; i++) {
4491 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4493 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4494 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4496 draw_activity_graphs(a->g_nr, g_type,
4497 title, g_title, item_name, group,
4498 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4499 svg_p, record_hdr, FALSE);
4502 /* Free remaining structures */
4503 free_graphs(out, outsize, spmin, spmax);
4508 ***************************************************************************
4509 * Display huge pages statistics in SVG.
4512 * @a Activity structure with statistics.
4513 * @curr Index in array for current sample statistics.
4514 * @action Action expected from current function.
4515 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4516 * flag indicating that a restart record has been previously
4517 * found (.@restart) and time used for the X axis origin
4519 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4520 * @record_hdr Pointer on record header of current stats sample.
4521 ***************************************************************************
4523 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4524 unsigned long long itv, struct record_header *record_hdr)
4527 *smc = (struct stats_huge *) a->buf[curr];
4528 int group[] = {2, 1};
4529 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4530 char *title[] = {"Huge pages utilization (1)",
4531 "Huge pages utilization (2)"};
4532 char *g_title[] = {"~kbhugfree", "~kbhugused",
4534 int g_fields[] = {0};
4535 unsigned int local_types_nr[] = {0, 1, 0};
4536 static double *spmin, *spmax;
4538 static int *outsize;
4541 if (action & F_BEGIN) {
4543 * Allocate arrays that will contain the graphs data
4544 * and the min/max values.
4546 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4549 if (action & F_MAIN) {
4550 /* Check for min/max values */
4551 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4552 itv, spmin, spmax, g_fields);
4554 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4555 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4557 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4558 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4560 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4561 if (tval < *(spmin + 2)) {
4562 *(spmin + 2) = tval;
4564 if (tval > *(spmax + 2)) {
4565 *(spmax + 2) = tval;
4569 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4570 (unsigned long long) smc->frhkb,
4571 out, outsize, svg_p->restart);
4573 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4574 (unsigned long long) smc->tlhkb - smc->frhkb,
4575 out + 1, outsize + 1, svg_p->restart);
4577 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4579 out + 2, outsize + 2, svg_p->dt);
4582 if (action & F_END) {
4583 draw_activity_graphs(a->g_nr, g_type,
4584 title, g_title, NULL, group,
4585 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4587 /* Free remaining structures */
4588 free_graphs(out, outsize, spmin, spmax);
4593 ***************************************************************************
4594 * Display filesystem statistics in SVG.
4597 * @a Activity structure with statistics.
4598 * @curr Index in array for current sample statistics.
4599 * @action Action expected from current function.
4600 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4601 * flag indicating that a restart record has been previously
4602 * found (.@restart) and time used for the X axis origin
4604 * @itv Interval of time in 1/100th of a second (unused here).
4605 * @record_hdr Pointer on record header of current stats sample.
4606 ***************************************************************************
4608 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4609 unsigned long long itv, struct record_header *record_hdr)
4611 struct stats_filesystem *sfc, *sfp;
4612 int group[] = {2, 2, 2, 1};
4613 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4614 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4615 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4616 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4617 char *g_title[] = {"~MBfsfree", "~MBfsused",
4618 "%ufsused", "%fsused",
4619 "Ifree/1000", "Iused/1000",
4621 static double *spmin, *spmax;
4623 static int *outsize;
4624 char *item_name = NULL;
4626 int i, k, pos, restart;
4628 if (action & F_BEGIN) {
4630 * Allocate arrays (#0..6) that will contain the graphs data
4631 * and the min/max values.
4632 * Also allocate two additional arrays (#7..8) for each filesystem:
4633 * out + 7 will contain the filesystem name,
4634 * out + 8 will contain the mount point.
4636 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
4639 if (action & F_MAIN) {
4640 /* For each filesystem structure */
4641 for (i = 0; i < a->nr[curr]; i++) {
4642 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4645 /* A list of devices has been entered on the command line */
4646 if (!search_sa_dlist(st_fs_list, dlst_fs_idx,
4647 DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name))
4648 /* Device not found */
4652 /* Look for corresponding graph */
4653 for (k = 0; k < svg_p->nr_max; k++) {
4654 item_name = *(out + k * 9 + 7);
4655 if (!strcmp(sfc->fs_name, item_name))
4660 if (k == svg_p->nr_max) {
4661 /* Graph not found: Look for first free entry */
4662 for (k = 0; k < svg_p->nr_max; k++) {
4663 item_name = *(out + k * 9 + 7);
4664 if (!strcmp(item_name, ""))
4667 if (k == svg_p->nr_max) {
4668 /* No free graph entry: Extend all buffers */
4669 reallocate_all_graph_lines(svg_p->nr_max,
4670 &out, &outsize, &spmin, &spmax);
4677 if (!item_name[0]) {
4678 /* Save filesystem name and mount point (if not already done) */
4679 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4680 item_name[CHUNKSIZE - 1] = '\0';
4681 item_name = *(out + pos + 8);
4682 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4683 item_name[CHUNKSIZE - 1] = '\0';
4687 for (k = 0; k < a->nr[!curr]; k++) {
4688 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4689 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4690 /* Filesystem found in previous sample */
4691 restart = svg_p->restart;
4695 /* Check for min/max values */
4697 /* Compute fsfree min/max values */
4698 tval = (double) sfc->f_bfree;
4699 if (tval > *(spmax + pos)) {
4700 *(spmax + pos) = tval;
4702 if (tval < *(spmin + pos)) {
4703 *(spmin + pos) = tval;
4705 /* Compute fsused min/max values */
4706 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4707 if (tval > *(spmax + pos + 1)) {
4708 *(spmax + pos + 1) = tval;
4710 if (tval < *(spmin + pos + 1)) {
4711 *(spmin + pos + 1) = tval;
4713 /* Compute %ufsused min/max values */
4714 tval = sfc->f_blocks ?
4715 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4716 if (tval > *(spmax + pos + 2)) {
4717 *(spmax + pos + 2) = tval;
4719 if (tval < *(spmin + pos + 2)) {
4720 *(spmin + pos + 2) = tval;
4722 /* Compute %fsused min/max values */
4723 tval = sfc->f_blocks ?
4724 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4725 if (tval > *(spmax + pos + 3)) {
4726 *(spmax + pos + 3) = tval;
4728 if (tval < *(spmin + pos + 3)) {
4729 *(spmin + pos + 3) = tval;
4731 /* Compute Ifree min/max values */
4732 tval = (double) sfc->f_ffree;
4733 if (tval > *(spmax + pos + 4)) {
4734 *(spmax + pos + 4) = tval;
4736 if (tval < *(spmin + pos + 4)) {
4737 *(spmin + pos + 4) = tval;
4739 /* Compute Iused min/max values */
4740 tval = (double) (sfc->f_files - sfc->f_ffree);
4741 if (tval > *(spmax + pos + 5)) {
4742 *(spmax + pos + 5) = tval;
4744 if (tval < *(spmin + pos + 5)) {
4745 *(spmin + pos + 5) = tval;
4747 /* Compute %Iused min/max values */
4748 tval = sfc->f_files ?
4749 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4750 if (tval > *(spmax + pos + 6)) {
4751 *(spmax + pos + 6) = tval;
4753 if (tval < *(spmin + pos + 6)) {
4754 *(spmin + pos + 6) = tval;
4758 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4759 (double) sfc->f_bfree / 1024 / 1024,
4760 out + pos, outsize + pos, restart);
4762 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4763 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4764 out + pos + 1, outsize + pos + 1, restart);
4766 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4769 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4770 out + pos + 2, outsize + pos + 2, svg_p->dt);
4772 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4775 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4776 out + pos + 3, outsize + pos + 3, svg_p->dt);
4778 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4779 ((double) sfc->f_ffree) / 1000,
4780 out + pos + 4, outsize + pos + 4, restart);
4782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4783 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4784 out + pos + 5, outsize + pos + 5, restart);
4786 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4789 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4790 out + pos + 6, outsize + pos + 6, svg_p->dt);
4794 if (action & F_END) {
4796 for (i = 0; i < svg_p->nr_max; i++) {
4798 /* Check if there is something to display */
4803 /* Conversion B -> MB and inodes/1000 */
4804 for (k = 0; k < 2; k++) {
4805 *(spmin + pos + k) /= (1024 * 1024);
4806 *(spmax + pos + k) /= (1024 * 1024);
4807 *(spmin + pos + 4 + k) /= 1000;
4808 *(spmax + pos + 4 + k) /= 1000;
4811 if (DISPLAY_MOUNT(a->opt_flags)) {
4812 item_name = *(out + pos + 8);
4815 item_name = *(out + pos + 7);
4818 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4819 spmin + pos, spmax + pos, out + pos, outsize + pos,
4820 svg_p, record_hdr, FALSE);
4823 /* Free remaining structures */
4824 free_graphs(out, outsize, spmin, spmax);
4829 ***************************************************************************
4830 * Display Fibre Channel HBA statistics in SVG.
4833 * @a Activity structure with statistics.
4834 * @curr Index in array for current sample statistics.
4835 * @action Action expected from current function.
4836 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4837 * flag indicating that a restart record has been previously
4838 * found (.@restart) and time used for the X axis origin
4840 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4841 * @record_hdr Pointer on record header of current stats sample.
4842 ***************************************************************************
4844 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4845 unsigned long long itv, struct record_header *record_hdr)
4847 struct stats_fchost *sfcc, *sfcp;
4848 int group[] = {2, 2};
4849 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4850 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4851 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4852 "fch_rxw/s", "fch_txw/s"};
4853 int g_fields[] = {0, 1, 2, 3};
4854 static double *spmin, *spmax;
4856 static int *outsize;
4858 int i, j, j0, k, found, pos, restart, *unregistered;
4860 if (action & F_BEGIN) {
4862 * Allocate arrays (#0..3) that will contain the graphs data
4863 * and the min/max values.
4864 * Also allocate one additional array (#4) that will contain
4865 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4866 * has either still not been registered, or has been unregistered
4869 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
4872 if (action & F_MAIN) {
4873 restart = svg_p->restart;
4875 * Mark previously registered interfaces as now
4876 * possibly unregistered for all graphs.
4878 for (k = 0; k < svg_p->nr_max; k++) {
4879 unregistered = outsize + k * 5 + 4;
4880 if (*unregistered == FALSE) {
4881 *unregistered = MAYBE;
4885 /* For each FC HBA */
4886 for (i = 0; i < a->nr[curr]; i++) {
4890 if (a->nr[!curr] > 0) {
4891 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4893 /* Look for corresponding graph */
4894 for (k = 0; k < svg_p->nr_max; k++) {
4895 item_name = *(out + k * 5 + 4);
4896 if (!strcmp(sfcc->fchost_name, item_name))
4900 if (k == svg_p->nr_max) {
4901 /* Graph not found: Look for first free entry */
4902 for (k = 0; k < svg_p->nr_max; k++) {
4903 item_name = *(out + k * 5 + 4);
4904 if (!strcmp(item_name, ""))
4907 if (k == svg_p->nr_max) {
4908 /* No free graph entry: Extend all buffers */
4909 reallocate_all_graph_lines(svg_p->nr_max,
4910 &out, &outsize, &spmin, &spmax);
4916 unregistered = outsize + pos + 4;
4918 /* Look for corresponding structure in previous iteration */
4921 if (j >= a->nr[!curr]) {
4922 j = a->nr[!curr] - 1;
4928 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4929 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4933 if (++j >= a->nr[!curr]) {
4944 * If current interface was marked as previously unregistered,
4945 * then set restart variable to TRUE so that the graph will be
4946 * discontinuous, and mark it as now registered.
4948 if (*unregistered == TRUE) {
4951 *unregistered = FALSE;
4953 item_name = *(out + pos + 4);
4954 if (!item_name[0]) {
4955 /* Save FC HBA name */
4956 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4957 item_name[CHUNKSIZE - 1] = '\0';
4960 /* Look for min/max values */
4961 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4962 itv, spmin + pos, spmax + pos, g_fields);
4965 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4966 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4967 out + pos, outsize + pos, restart);
4969 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4970 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4971 out + pos + 1, outsize + pos + 1, restart);
4973 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4974 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4975 out + pos + 2, outsize + pos + 2, restart);
4977 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4978 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4979 out + pos + 3, outsize + pos + 3, restart);
4982 /* Mark interfaces not seen here as now unregistered */
4983 for (k = 0; k < svg_p->nr_max; k++) {
4984 unregistered = outsize + k * 5 + 4;
4985 if (*unregistered != FALSE) {
4986 *unregistered = TRUE;
4991 if (action & F_END) {
4992 for (i = 0; i < svg_p->nr_max; i++) {
4994 /* Check if there is something to display */
4999 item_name = *(out + pos + 4);
5000 draw_activity_graphs(a->g_nr, g_type,
5001 title, g_title, item_name, group,
5002 spmin + pos, spmax + pos, out + pos, outsize + pos,
5003 svg_p, record_hdr, FALSE);
5006 /* Free remaining structures */
5007 free_graphs(out, outsize, spmin, spmax);
5012 ***************************************************************************
5013 * Display softnet statistics in SVG.
5016 * @a Activity structure with statistics.
5017 * @curr Index in array for current sample statistics.
5018 * @action Action expected from current function.
5019 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5020 * flag indicating that a restart record has been previously
5021 * found (.@restart) and time used for the X axis origin
5023 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5024 * @record_hdr Pointer on record header of current stats sample.
5025 ***************************************************************************
5027 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5028 unsigned long long itv, struct record_header *record_hdr)
5030 struct stats_softnet *ssnc, *ssnp;
5031 int group[] = {2, 3};
5032 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5033 char *title[] = {"Software-based network processing statistics (1)",
5034 "Software-based network processing statistics (2)"};
5035 char *g_title[] = {"total/s", "dropd/s",
5036 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5037 int g_fields[] = {0, 1, 2, 3, 4};
5038 static double *spmin, *spmax;
5040 static int *outsize;
5042 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5045 if (action & F_BEGIN) {
5047 * Allocate arrays that will contain the graphs data
5048 * and the min/max values.
5050 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
5053 if (action & F_MAIN) {
5054 /* @nr[curr] cannot normally be greater than @nr_ini */
5055 if (a->nr[curr] > a->nr_ini) {
5056 a->nr_ini = a->nr[curr];
5059 /* Compute statistics for CPU "all" */
5060 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5063 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5065 /* Should current CPU (including CPU "all") be displayed? */
5066 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
5067 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
5071 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5072 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5076 /* Check for min/max values */
5077 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5078 itv, spmin + pos, spmax + pos, g_fields);
5081 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5082 S_VALUE(ssnp->processed, ssnc->processed, itv),
5083 out + pos, outsize + pos, svg_p->restart);
5085 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5086 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5087 out + pos + 1, outsize + pos + 1, svg_p->restart);
5089 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5090 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5091 out + pos + 2, outsize + pos + 2, svg_p->restart);
5093 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5094 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5095 out + pos + 3, outsize + pos + 3, svg_p->restart);
5097 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5098 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5099 out + pos + 4, outsize + pos + 4, svg_p->restart);
5103 if (action & F_END) {
5104 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
5106 /* Should current CPU (including CPU "all") be displayed? */
5107 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5114 /* This is CPU "all" */
5115 strcpy(item_name, "all");
5118 sprintf(item_name, "%d", i - 1);
5121 draw_activity_graphs(a->g_nr, g_type,
5122 title, g_title, item_name, group,
5123 spmin + pos, spmax + pos, out + pos, outsize + pos,
5124 svg_p, record_hdr, FALSE);
5127 /* Free remaining structures */
5128 free_graphs(out, outsize, spmin, spmax);