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;
42 unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
43 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
44 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
45 0xcc3300, 0x50040f, 0xffffbf, 0x193d55};
46 #define SVG_COLORS_IDX_MASK 0x0f
49 ***************************************************************************
50 * Compare the values of a statistics sample with the max and min values
51 * already found in previous samples for this same activity. If some new
52 * min or max values are found, then save them.
53 * Assume values cannot be negative.
54 * The structure containing the statistics sample is composed of @llu_nr
55 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
56 * followed by @u_nr unsigned int fields.
59 * @types_nr Number of fields whose type is "long long", "long" and "int"
60 * composing the structure.
61 * @cs Pointer on current sample statistics structure.
62 * @ps Pointer on previous sample statistics structure (may be NULL).
63 * @itv Interval of time in 1/100th of a second.
64 * @spmin Array containing min values already found for this activity.
65 * @spmax Array containing max values already found for this activity.
66 * @g_fields Index in spmin/spmax arrays where extrema values for each
67 * activity metric will be saved. As a consequence spmin/spmax
68 * arrays may contain values in a different order than that of
69 * the fields in the statistics structure.
72 * @spmin Array containg the possible new min values for current activity.
73 * @spmax Array containg the possible new max values for current activity.
74 ***************************************************************************
76 void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
77 double *spmin, double *spmax, int g_fields[])
79 unsigned long long *lluc, *llup;
80 unsigned long *luc, *lup;
81 unsigned int *uc, *up;
85 /* Compare unsigned long long fields */
86 lluc = (unsigned long long *) cs;
87 llup = (unsigned long long *) ps;
88 for (i = 0; i < types_nr[0]; i++, m++) {
90 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
94 * If no pointer on previous sample has been given
95 * then the value is not a per-second one.
99 if (val < *(spmin + g_fields[m])) {
100 *(spmin + g_fields[m]) = val;
102 if (val > *(spmax + g_fields[m])) {
103 *(spmax + g_fields[m]) = val;
105 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
107 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
111 /* Compare unsigned long fields */
112 luc = (unsigned long *) lluc;
113 lup = (unsigned long *) llup;
114 for (i = 0; i < types_nr[1]; i++, m++) {
116 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
121 if (val < *(spmin + g_fields[m])) {
122 *(spmin + g_fields[m]) = val;
124 if (val > *(spmax + g_fields[m])) {
125 *(spmax + g_fields[m]) = val;
127 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
129 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
133 /* Compare unsigned int fields */
134 uc = (unsigned int *) luc;
135 up = (unsigned int *) lup;
136 for (i = 0; i < types_nr[2]; i++, m++) {
138 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
143 if (val < *(spmin + g_fields[m])) {
144 *(spmin + g_fields[m]) = val;
146 if (val > *(spmax + g_fields[m])) {
147 *(spmax + g_fields[m]) = val;
149 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
151 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
157 ***************************************************************************
158 * Find the min and max values of all the graphs that will be drawn in the
159 * same view. The graphs have their own min and max values in
160 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
163 * @pos Position in array for the first graph extrema value.
164 * @n Number of graphs to scan.
165 * @spmin Array containing min values for graphs.
166 * @spmax Array containing max values for graphs.
169 * @gmin Global min value found.
170 * @gmax Global max value found.
171 ***************************************************************************
173 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
174 double *gmin, double *gmax)
178 *gmin = *(spmin + pos);
179 *gmax = *(spmax + pos);
181 for (i = 1; i < n; i++) {
182 if (*(spmin + pos + i) < *gmin) {
183 *gmin = *(spmin + pos + i);
185 if (*(spmax + pos + i) > *gmax) {
186 *gmax = *(spmax + pos + i);
192 ***************************************************************************
193 * Allocate arrays used to save graphs data, min and max values.
194 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
195 * array is returned. This is equivalent to "char data[][n]" where each
196 * element is of indeterminate size and will contain the graph data (eg.
197 * << path d="M12,14 L13,16..." ... >>.
198 * The size of element data[i] is given by outsize[i].
199 * Also allocate an array to save min values (equivalent to "double spmin[n]")
200 * and an array for max values (equivalent to "double spmax[n]").
203 * @n Number of graphs to draw for current activity.
206 * @outsize Array that will contain the sizes of each element in array
207 * of chars. Equivalent to "int outsize[n]" with
208 * outsize[n] = sizeof(data[][n]).
209 * @spmin Array that will contain min values for current activity.
210 * @spmax Array that will contain max values for current activity.
213 * Pointer on array of arrays of chars that will contain the graphs data.
215 * NB: @min and @max arrays contain values in the same order as the fields
216 * in the statistics structure.
217 ***************************************************************************
219 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
226 * Allocate an array of pointers. Each of these pointers will
227 * be an array of chars.
229 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
233 /* Allocate array that will contain the size of each array of chars */
234 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
238 /* Allocate array that will contain the min value of each graph */
239 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
243 /* Allocate array that will contain the max value of each graph */
244 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
248 /* Allocate arrays of chars that will contain graphs data */
249 for (i = 0; i < n; i++) {
250 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
255 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
256 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
257 *(*spmin + i) = DBL_MAX; /* Init min and max values */
258 *(*spmax + i) = -DBL_MAX;
265 ***************************************************************************
266 * Save SVG code for current graph.
269 * @data SVG code to append to current graph definition.
270 * @out Pointer on array of chars for current graph definition.
271 * @outsize Size of array of chars for current graph definition.
274 * @out Pointer on array of chars for current graph definition that
275 * has been updated with the addition of current sample data.
276 * @outsize Array that containing the (possibly new) sizes of each
277 * element in array of chars.
278 ***************************************************************************
280 void save_svg_data(char *data, char **out, int *outsize)
286 /* Determine space left in array */
287 len = *outsize - strlen(out_p) - 1;
288 if (strlen(data) >= len) {
290 * If current array of chars doesn't have enough space left
291 * then reallocate it with CHUNKSIZE more bytes.
293 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
295 *outsize += CHUNKSIZE;
298 strncat(out_p, data, len);
302 ***************************************************************************
303 * Update line graph definition by appending current X,Y coordinates.
306 * @timetag Timestamp in seconds since the epoch for current sample
307 * stats. Will be used as X coordinate.
308 * @value Value of current sample metric. Will be used as Y coordinate.
309 * @out Pointer on array of chars for current graph definition.
310 * @outsize Size of array of chars for current graph definition.
311 * @restart Set to TRUE if a RESTART record has been read since the last
315 * @out Pointer on array of chars for current graph definition that
316 * has been updated with the addition of current sample data.
317 * @outsize Array that containing the (possibly new) sizes of each
318 * element in array of chars.
319 ***************************************************************************
321 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
326 /* Prepare additional graph definition data */
327 snprintf(data, 128, " %c%llu,%.2f", restart ? 'M' : 'L', timetag, value);
330 save_svg_data(data, out, outsize);
334 ***************************************************************************
335 * Update line graph definition by appending current X,Y coordinates. Use
336 * (unsigned long) integer values here.
339 * @timetag Timestamp in seconds since the epoch for current sample
340 * stats. Will be used as X coordinate.
341 * @value Value of current sample metric. Will be used as Y coordinate.
342 * @out Pointer on array of chars for current graph definition.
343 * @outsize Size of array of chars for current graph definition.
344 * @restart Set to TRUE if a RESTART record has been read since the last
348 * @out Pointer on array of chars for current graph definition that
349 * has been updated with the addition of current sample data.
350 * @outsize Array that containing the (possibly new) sizes of each
351 * element in array of chars.
352 ***************************************************************************
354 void lniappend(unsigned long long timetag, unsigned long long value, char **out,
355 int *outsize, int restart)
359 /* Prepare additional graph definition data */
360 snprintf(data, 128, " %c%llu,%llu", restart ? 'M' : 'L', timetag, value);
363 save_svg_data(data, out, outsize);
367 ***************************************************************************
368 * Update bar graph definition by adding a new rectangle.
371 * @timetag Timestamp in seconds since the epoch for current sample
372 * stats. Will be used as X coordinate.
373 * @value Value of current sample metric. Will be used as rectangle
375 * @offset Offset for Y coordinate.
376 * @out Pointer on array of chars for current graph definition.
377 * @outsize Size of array of chars for current graph definition.
378 * @dt Interval of time in seconds between current and previous
382 * @out Pointer on array of chars for current graph definition that
383 * has been updated with the addition of current sample data.
384 * @outsize Array that containing the (possibly new) sizes of each
385 * element in array of chars.
386 ***************************************************************************
388 void brappend(unsigned long long timetag, double offset, double value, char **out,
389 int *outsize, unsigned long long dt)
393 /* Prepare additional graph definition data */
394 if ((value == 0.0) || (dt == 0))
395 /* Don't draw a flat rectangle! */
398 snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
399 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
402 save_svg_data(data, out, outsize);
407 ***************************************************************************
408 * Update CPU graph and min/max values for each metric.
411 * @timetag Timestamp in seconds since the epoch for current sample
412 * stats. Will be used as X coordinate.
413 * @offset Offset for Y coordinate.
414 * @value Value of current CPU metric. Will be used as rectangle
416 * @out Pointer on array of chars for current graph definition.
417 * @outsize Size of array of chars for current graph definition.
418 * @dt Interval of time in seconds between current and previous
420 * @spmin Min value already found for this CPU metric.
421 * @spmax Max value already found for this CPU metric.
424 * @offset New offset value, to use to draw next rectangle
425 * @out Pointer on array of chars for current graph definition that
426 * has been updated with the addition of current sample data.
427 * @outsize Array that containing the (possibly new) sizes of each
428 * element in array of chars.
429 ***************************************************************************
431 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
432 int *outsize, unsigned long long dt, double *spmin, double *spmax)
434 /* Save min and max values */
435 if (value < *spmin) {
438 if (value > *spmax) {
441 /* Prepare additional graph definition data */
442 brappend(timetag, *offset, value, out, outsize, dt);
448 ***************************************************************************
449 * Update rectangular graph and min/max values.
452 * @timetag Timestamp in seconds since the epoch for current sample
453 * stats. Will be used as X coordinate.
454 * @p_value Metric value for previous sample
455 * @value Metric value for current sample.
456 * @out Pointer on array of chars for current graph definition.
457 * @outsize Size of array of chars for current graph definition.
458 * @restart Set to TRUE if a RESTART record has been read since the last
460 * @dt Interval of time in seconds between current and previous
462 * @spmin Min value already found for this metric.
463 * @spmax Max value already found for this metric.
466 * @out Pointer on array of chars for current graph definition that
467 * has been updated with the addition of current sample data.
468 * @outsize Array that containing the (possibly new) sizes of each
469 * element in array of chars.
470 * @spmin Min value for this metric.
471 * @spmax Max value for this metric.
472 ***************************************************************************
474 void recappend(unsigned long long timetag, double p_value, double value, char **out,
475 int *outsize, int restart, unsigned long long dt,
476 double *spmin, double *spmax)
478 char data[512], data1[128], data2[128];
480 /* Save min and max values */
481 if (value < *spmin) {
484 if (value > *spmax) {
487 /* Prepare additional graph definition data */
489 snprintf(data1, sizeof(data1), " M%llu,%.2f", timetag - dt, p_value);
490 data1[sizeof(data1) - 1] = '\0';
492 if (p_value != value) {
493 snprintf(data2, sizeof(data2), " L%llu,%.2f", timetag, value);
494 data2[sizeof(data2) - 1] = '\0';
496 snprintf(data, sizeof(data), "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
497 p_value != value ? data2 : "");
498 data[sizeof(data) - 1] = '\0';
500 save_svg_data(data, out, outsize);
504 ***************************************************************************
505 * Calculate 10 raised to the power of n.
508 * @n Power number to use.
511 * 10 raised to the power of n.
512 ***************************************************************************
514 unsigned int pwr10(int n)
519 for (i = 0; i < n; i++) {
527 ***************************************************************************
528 * Autoscale graphs of a given view.
531 * @asf_nr (Maximum) number of autoscale factors.
532 * @group Number of graphs in current view.
533 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
534 * @pos Position in array for the first graph in view.
535 * @gmax Global max value for all graphs in view.
536 * @spmax Array containing max values for graphs.
539 * @asfactor Autoscale factors (one for each graph).
540 ***************************************************************************
542 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
543 double gmax, double *spmax)
548 for (j = 0; j < asf_nr; j++) {
549 /* Init autoscale factors */
553 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
555 for (j = 0; (j < group) && (j < asf_nr); j++) {
556 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
559 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
560 if (strlen(val) > 0) {
561 asfactor[j] = pwr10(strlen(val) - 1);
568 ***************************************************************************
569 * Display background grid (horizontal lines) and corresponding graduations.
572 * @ypos Gap between two horizontal lines.
573 * @yfactor Scaling factor on Y axis.
574 * @lmax Max value for current view.
575 * @dp Number of decimal places for graduations.
576 ***************************************************************************
578 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
584 /* Display horizontal lines (except on X axis) */
586 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
587 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
588 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
592 * Display graduations.
593 * Use same rounded value for graduation numbers as for grid lines
594 * to make sure they are properly aligned.
596 sprintf(stmp, "%.2f", ypos * j);
597 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
598 "text-anchor: end\">%.*f.</text>\n",
599 (long) (atof(stmp) * yfactor), dp, ypos * j);
602 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
606 ***************************************************************************
607 * Display background grid (vertical lines) and corresponding graduations.
610 * @xpos Gap between two vertical lines.
611 * @xfactor Scaling factor on X axis.
612 * @v_gridnr Default number of vertical lines to display. The actual
613 * number may vary between this value and 2 times this value.
614 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
615 ***************************************************************************
617 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
619 struct record_header stamp;
621 char cur_time[TIMESTAMP_LEN];
624 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
627 * What really matters to know when we should stop drawing vertical lines
628 * is the time end. v_gridnr is only informative and used to calculate
629 * the gap between two lines.
631 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
633 /* Display vertical lines */
634 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
635 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
636 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
637 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
638 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
640 * Display graduations.
641 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
642 * In this case, we should rather display the exact time instead of only the hour.
644 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
645 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
646 "text-anchor: start\">%2d:00</text>\n",
647 (long) (xpos * j * xfactor) - 15, rectime.tm_hour);
650 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
651 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
652 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
654 stamp.ust_time += xpos;
657 if (!PRINT_LOCAL_TIME(flags)) {
658 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
659 "text-anchor: end\">UTC</text>\n");
664 ***************************************************************************
665 * Calculate the value on the Y axis between two horizontal lines that will
666 * make the graph background grid.
669 * @lmax Max value reached for this graph.
672 * @dp Number of decimal places for Y graduations.
675 * Value between two horizontal lines.
676 ***************************************************************************
678 double ygrid(double lmax, int *dp)
689 n = (long) (lmax / SVG_H_GRIDNR);
692 return (lmax / SVG_H_GRIDNR);
694 snprintf(val, 32, "%ld", n);
701 return ((double) (((long) (n / e)) * e));
705 ***************************************************************************
706 * Calculate the value on the X axis between two vertical lines that will
707 * make the graph background grid.
710 * @timestart First data timestamp (X coordinate of the first data point).
711 * @timeend Last data timestamp (X coordinate of the last data point).
712 * @v_gridnr Number of vertical lines to display. Its value is normally
713 * SVG_V_GRIDNR, except when option "oneday" is used, in which
714 * case it is set to 12.
717 * Value between two vertical lines.
718 ***************************************************************************
720 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
722 if ((timeend - timestart) <= v_gridnr)
725 return ((timeend - timestart) / v_gridnr);
729 ***************************************************************************
730 * Free global graphs structures.
733 * @out Pointer on array of chars for each graph definition.
734 * @outsize Size of array of chars for each graph definition.
735 * @spmin Array containing min values for graphs.
736 * @spmax Array containing max values for graphs.
737 ***************************************************************************
739 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
756 ***************************************************************************
757 * Skip current view where all graphs have only zero values. This function
758 * is called when option "skipempty" has been used, or when "No data" have
759 * been found for current view.
762 * @out Pointer on array of chars for each graph definition.
763 * @pos Position of current view in the array of graphs definitions.
764 * @group Number of graphs in current view.
767 * @pos Position of next view in the array of graphs definitions.
768 ***************************************************************************
770 void skip_current_view(char **out, int *pos, int group)
775 for (j = 0; j < group; j++) {
776 out_p = *(out + *pos + j);
778 /* Even if not displayed, current graph data have to be freed */
786 ***************************************************************************
787 * Display all graphs for current activity.
790 * @g_nr Number of views to display.
791 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
792 * @title Titles for each set of graphs.
793 * @g_title Titles for each graph.
794 * @item_name Item (network interface, etc.) name.
795 * @group Indicate how graphs are grouped together to make sets.
796 * @spmin Array containing min values for graphs.
797 * @spmax Array containing max values for graphs.
798 * @out Pointer on array of chars for each graph definition.
799 * @outsize Size of array of chars for each graph definition.
800 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
801 * time for the first sample of stats (.@ust_time_first), and
802 * times used as start and end values on the X axis
803 * (.@ust_time_ref and .@ust_time_end).
804 * @record_hdr Pointer on record header of current stats sample.
805 * @skip_void Set to <> 0 if graphs with no data should be skipped.
806 * This is typicallly used to not display CPU offline on the
808 * @id Current activity id.
809 * @xid Current activity extra id number.
812 * TRUE if at least one graph has been displayed.
813 ***************************************************************************
815 int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
816 int group[], double *spmin, double *spmax, char **out, int *outsize,
817 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
818 unsigned int id, unsigned int xid)
821 int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE;
822 int v_gridnr, xv, yv;
823 unsigned int asfactor[16];
825 double lmax, xfactor, yfactor, ypos, gmin, gmax;
826 char val[32], cur_date[TIMESTAMP_LEN];
828 /* For each view which is part of current activity */
829 for (i = 0; i < g_nr; i++) {
831 /* Get global min and max value for current view */
832 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
834 /* Don't display empty views if requested */
835 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
836 skip_current_view(out, &pos, group[i]);
839 /* Skip void graphs */
840 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
844 /* Translate to proper position for current activity */
845 printf("<g id=\"g%d-%d\" transform=\"translate(0,%d)\">\n",
848 SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
849 SVG_T_YSIZE * svg_p->graph_no);
853 /* Increment number of views actually displayed */
856 /* Compute top left position of view */
857 if (PACK_VIEWS(flags)) {
858 xv = (views_nr - 1) * SVG_T_XSIZE;
863 yv = (views_nr - 1) * SVG_T_YSIZE;
866 /* Graph background */
867 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
868 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
871 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
872 xv, 20 + yv, title[i]);
874 printf(" [%s]", item_name);
877 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
878 "(Min, Max values)</tspan>\n</text>\n",
879 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
882 * At least two samples are needed.
883 * And a min and max value should have been found.
885 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
886 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
888 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
889 xv, yv + SVG_M_YSIZE);
890 skip_current_view(out, &pos, group[i]);
895 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
896 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
897 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
898 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
900 /* Autoscaling graphs if needed */
901 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
904 for (j = 0; j < group[i]; j++) {
905 /* Set dp to TRUE (1) if current metric is based on integer values */
906 dp = (g_title[pos + j][0] == '~');
907 snprintf(val, 32, "x%u ", asfactor[j]);
908 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
909 "%s %s(%.*f, %.*f)</text>\n",
910 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
911 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
912 asfactor[j] == 1 ? "" : val,
913 !dp * 2, *(spmin + pos + j) * asfactor[j],
914 !dp * 2, *(spmax + pos + j) * asfactor[j]);
917 if (DISPLAY_INFO(flags)) {
918 /* Display additional info (hostname, date) */
919 printf("<text x=\"%d\" y=\"%d\" "
920 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
922 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
923 svg_p->file_hdr->sa_nodename);
925 /* Get report date */
926 set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
927 cur_date, sizeof(cur_date));
928 printf("<tspan x=\"%d\" y=\"%d\" "
929 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
930 "%s</tspan>\n</text>\n",
931 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
935 /* Translate to proper position for current graph within current activity */
936 printf("<g transform=\"translate(%d,%d)\">\n",
937 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
940 if (g_type[i] == SVG_LINE_GRAPH) {
941 /* For line graphs */
943 /* If all values are zero then set current max value to 1 */
949 /* Max value cannot be too small, else Y graduations will be meaningless */
950 if (lmax < SVG_H_GRIDNR * 0.01) {
951 lmax = SVG_H_GRIDNR * 0.01;
953 ypos = ygrid(lmax, &dp);
956 /* For bar graphs (used for %values) */
957 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
958 dp = 0; /* No decimals */
960 /* Max should be always 100% except for percentage values greater than 100% */
968 yfactor = (double) -SVG_G_YSIZE / lmax;
970 /* Display horizontal lines and graduations */
971 display_hgrid(ypos, yfactor, lmax, dp);
973 /* Set number of vertical lines to 12 when option "oneday" is used */
974 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
976 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
977 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
979 /* Display vertical lines and graduations */
980 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
982 /* Draw current graphs set */
983 for (j = 0; j < group[i]; j++) {
984 out_p = *(out + pos + j);
985 if (g_type[i] == SVG_LINE_GRAPH) {
987 printf("<path d=\"%s\" "
988 "style=\"vector-effect: non-scaling-stroke; "
989 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
990 "transform=\"scale(%f,%f)\"/>\n",
992 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
994 yfactor * asfactor[j]);
996 else if (*out_p) { /* Ignore flat bars */
998 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
999 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1000 printf("%s\n", out_p);
1011 /* For next row of views */
1012 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1019 ***************************************************************************
1020 * Display CPU statistics in SVG.
1023 * @a Activity structure with statistics.
1024 * @curr Index in array for current sample statistics.
1025 * @action Action expected from current function.
1026 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1027 * flag indicating that a restart record has been previously
1028 * found (.@restart), and time used for the X axis origin
1030 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1032 * @record_hdr Pointer on record header of current stats sample.
1033 ***************************************************************************
1035 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1036 unsigned long long itv, struct record_header *record_hdr)
1038 struct stats_cpu *scc, *scp;
1039 unsigned long long deltot_jiffies = 1;
1040 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1043 int g_type[] = {SVG_BAR_GRAPH};
1044 char *title[] = {"CPU utilization"};
1045 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1046 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1047 static double *spmin, *spmax;
1049 static int *outsize;
1054 if (action & F_BEGIN) {
1056 * Allocate arrays that will contain the graphs data
1057 * and the min/max values.
1059 out = allocate_graph_lines(10 * a->item_list_sz, &outsize, &spmin, &spmax);
1062 if (action & F_MAIN) {
1064 /* @nr[curr] cannot normally be greater than @nr_ini */
1065 if (a->nr[curr] > a->nr_ini) {
1066 a->nr_ini = a->nr[curr];
1070 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1071 * and look for offline CPU.
1073 if (a->nr_ini > 1) {
1074 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1075 flags, offline_cpu_bitmap);
1079 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1081 /* Should current CPU (including CPU "all") be displayed? */
1082 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1083 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1084 /* Don't display CPU */
1087 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1088 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1094 /* This is CPU "all" */
1095 if (a->nr_ini == 1) {
1097 * This is a UP machine. In this case
1098 * interval has still not been calculated.
1100 deltot_jiffies = get_per_cpu_interval(scc, scp);
1102 if (!deltot_jiffies) {
1103 /* CPU "all" cannot be tickless */
1109 * Recalculate interval for current proc.
1110 * If result is 0 then current CPU is a tickless one.
1112 deltot_jiffies = get_per_cpu_interval(scc, scp);
1114 if (!deltot_jiffies) { /* Current CPU is tickless */
1116 val = 100.0; /* Tickless CPU: %idle = 100% */
1118 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1121 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1125 /* Check min/max values for %user, etc. */
1126 for (k = 0; k < j; k++) {
1127 if (0.0 < *(spmin + pos + k)) {
1128 *(spmin + pos + k) = 0.0;
1130 if (0.0 > *(spmax + pos + k)) {
1131 *(spmax + pos + k) = 0.0;
1136 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1138 out + pos + j, outsize + pos + j, svg_p->dt,
1139 spmin + pos + j, spmax + pos + j);
1144 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1146 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1147 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1148 out + pos, outsize + pos, svg_p->dt,
1149 spmin + pos, spmax + pos);
1153 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1155 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1157 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1158 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1159 out + pos, outsize + pos, svg_p->dt,
1160 spmin + pos, spmax + pos);
1163 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1165 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1166 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1167 out + pos + 1, outsize + pos + 1, svg_p->dt,
1168 spmin + pos + 1, spmax + pos + 1);
1172 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1174 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1176 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1177 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1178 out + pos + 1, outsize + pos + 1, svg_p->dt,
1179 spmin + pos + 1, spmax + pos + 1);
1182 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1184 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1186 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1187 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1189 out + pos + 2, outsize + pos + 2, svg_p->dt,
1190 spmin + pos + 2, spmax + pos + 2);
1194 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1195 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1196 out + pos + 2, outsize + pos + 2, svg_p->dt,
1197 spmin + pos + 2, spmax + pos + 2);
1201 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1202 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1203 out + pos + 3, outsize + pos + 3, svg_p->dt,
1204 spmin + pos + 3, spmax + pos + 3);
1206 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1207 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1208 out + pos + 4, outsize + pos + 4, svg_p->dt,
1209 spmin + pos + 4, spmax + pos + 4);
1211 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1213 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1214 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1215 out + pos + 5, outsize + pos + 5, svg_p->dt,
1216 spmin + pos + 5, spmax + pos + 5);
1218 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1219 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1220 out + pos + 6, outsize + pos + 6, svg_p->dt,
1221 spmin + pos + 6, spmax + pos + 6);
1223 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1224 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1225 out + pos + 7, outsize + pos + 7, svg_p->dt,
1226 spmin + pos + 7, spmax + pos + 7);
1228 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1229 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1230 out + pos + 8, outsize + pos + 8, svg_p->dt,
1231 spmin + pos + 8, spmax + pos + 8);
1240 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1242 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1243 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1244 out + pos + j, outsize + pos + j, svg_p->dt,
1245 spmin + pos + j, spmax + pos + j);
1249 if (action & F_END) {
1250 int xid = 0, displayed;
1252 if (DISPLAY_IDLE(flags)) {
1253 /* Include additional %idle field */
1258 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
1260 /* Should current CPU (including CPU "all") be displayed? */
1261 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1267 /* This is CPU "all" */
1268 strcpy(item_name, "all");
1271 sprintf(item_name, "%d", i - 1);
1274 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1275 displayed = draw_activity_graphs(a->g_nr, g_type,
1276 title, g_title1, item_name, group1,
1277 spmin + pos, spmax + pos, out + pos, outsize + pos,
1278 svg_p, record_hdr, i, a->id, xid);
1281 displayed = draw_activity_graphs(a->g_nr, g_type,
1282 title, g_title2, item_name, group2,
1283 spmin + pos, spmax + pos, out + pos, outsize + pos,
1284 svg_p, record_hdr, i, a->id, xid);
1291 /* Free remaining structures */
1292 free_graphs(out, outsize, spmin, spmax);
1297 ***************************************************************************
1298 * Display task creation and context switch statistics in SVG.
1301 * @a Activity structure with statistics.
1302 * @curr Index in array for current sample statistics.
1303 * @action Action expected from current function.
1304 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1305 * flag indicating that a restart record has been previously
1306 * found (.@restart) and time used for the X axis origin
1308 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1309 * @record_hdr Pointer on record header of current stats sample.
1310 ***************************************************************************
1312 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1313 unsigned long long itv, struct record_header *record_hdr)
1316 *spc = (struct stats_pcsw *) a->buf[curr],
1317 *spp = (struct stats_pcsw *) a->buf[!curr];
1318 int group[] = {1, 1};
1319 int g_fields[] = {1, 0};
1320 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1321 char *title[] = {"Task creation", "Switching activity"};
1322 char *g_title[] = {"proc/s",
1324 static double *spmin, *spmax;
1326 static int *outsize;
1328 if (action & F_BEGIN) {
1330 * Allocate arrays that will contain the graphs data
1331 * and the min/max values.
1333 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1336 if (action & F_MAIN) {
1337 /* Check for min/max values */
1338 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1339 itv, spmin, spmax, g_fields);
1341 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1342 S_VALUE(spp->processes, spc->processes, itv),
1343 out, outsize, svg_p->restart);
1345 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1346 S_VALUE(spp->context_switch, spc->context_switch, itv),
1347 out + 1, outsize + 1, svg_p->restart);
1350 if (action & F_END) {
1351 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1352 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1354 /* Free remaining structures */
1355 free_graphs(out, outsize, spmin, spmax);
1360 ***************************************************************************
1361 * Display swap statistics in SVG.
1364 * @a Activity structure with statistics.
1365 * @curr Index in array for current sample statistics.
1366 * @action Action expected from current function.
1367 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1368 * flag indicating that a restart record has been previously
1369 * found (.@restart) and time used for the X axis origin
1371 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1372 * @record_hdr Pointer on record header of current stats sample.
1373 ***************************************************************************
1375 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1376 unsigned long long itv, struct record_header *record_hdr)
1379 *ssc = (struct stats_swap *) a->buf[curr],
1380 *ssp = (struct stats_swap *) a->buf[!curr];
1382 int g_type[] = {SVG_LINE_GRAPH};
1383 char *title[] = {"Swap activity"};
1384 char *g_title[] = {"pswpin/s", "pswpout/s" };
1385 int g_fields[] = {0, 1};
1386 static double *spmin, *spmax;
1388 static int *outsize;
1390 if (action & F_BEGIN) {
1392 * Allocate arrays that will contain the graphs data
1393 * and the min/max values.
1395 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1398 if (action & F_MAIN) {
1399 /* Check for min/max values */
1400 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1401 itv, spmin, spmax, g_fields);
1403 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1404 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1405 out, outsize, svg_p->restart);
1407 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1408 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1409 out + 1, outsize + 1, svg_p->restart);
1412 if (action & F_END) {
1413 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1414 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1416 /* Free remaining structures */
1417 free_graphs(out, outsize, spmin, spmax);
1422 ***************************************************************************
1423 * Display paging statistics in SVG.
1426 * @a Activity structure with statistics.
1427 * @curr Index in array for current sample statistics.
1428 * @action Action expected from current function.
1429 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1430 * flag indicating that a restart record has been previously
1431 * found (.@restart) and time used for the X axis origin
1433 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1434 * @record_hdr Pointer on record header of current stats sample.
1435 ***************************************************************************
1437 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1438 unsigned long long itv, struct record_header *record_hdr)
1441 *spc = (struct stats_paging *) a->buf[curr],
1442 *spp = (struct stats_paging *) a->buf[!curr];
1443 int group[] = {2, 2, 4};
1444 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1445 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1446 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1447 "fault/s", "majflt/s",
1448 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1449 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1450 static double *spmin, *spmax;
1452 static int *outsize;
1454 if (action & F_BEGIN) {
1456 * Allocate arrays that will contain the graphs data
1457 * and the min/max values.
1459 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1462 if (action & F_MAIN) {
1463 /* Check for min/max values */
1464 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1465 itv, spmin, spmax, g_fields);
1467 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1468 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1469 out, outsize, svg_p->restart);
1471 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1472 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1473 out + 1, outsize + 1, svg_p->restart);
1475 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1476 S_VALUE(spp->pgfault, spc->pgfault, itv),
1477 out + 2, outsize + 2, svg_p->restart);
1479 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1480 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1481 out + 3, outsize + 3, svg_p->restart);
1483 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1484 S_VALUE(spp->pgfree, spc->pgfree, itv),
1485 out + 4, outsize + 4, svg_p->restart);
1487 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1488 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1489 out + 5, outsize + 5, svg_p->restart);
1491 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1492 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1493 out + 6, outsize + 6, svg_p->restart);
1495 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1496 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1497 out + 7, outsize + 7, svg_p->restart);
1500 if (action & F_END) {
1501 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1502 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1504 /* Free remaining structures */
1505 free_graphs(out, outsize, spmin, spmax);
1510 ***************************************************************************
1511 * Display I/O and transfer rate statistics in SVG.
1514 * @a Activity structure with statistics.
1515 * @curr Index in array for current sample statistics.
1516 * @action Action expected from current function.
1517 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1518 * flag indicating that a restart record has been previously
1519 * found (.@restart) and time used for the X axis origin
1521 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1522 * @record_hdr Pointer on record header of current stats sample.
1523 ***************************************************************************
1525 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1526 unsigned long long itv, struct record_header *record_hdr)
1529 *sic = (struct stats_io *) a->buf[curr],
1530 *sip = (struct stats_io *) a->buf[!curr];
1531 int group[] = {3, 2};
1532 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1533 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1534 char *g_title[] = {"tps", "rtps", "wtps",
1535 "bread/s", "bwrtn/s"};
1536 int g_fields[] = {0, 1, 2, 3, 4};
1537 static double *spmin, *spmax;
1539 static int *outsize;
1541 if (action & F_BEGIN) {
1543 * Allocate arrays that will contain the graphs data
1544 * and the min/max values.
1546 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1549 if (action & F_MAIN) {
1550 /* Check for min/max values */
1551 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1552 itv, spmin, spmax, g_fields);
1555 * If we get negative values, this is probably because
1556 * one or more devices/filesystems have been unmounted.
1557 * We display 0.0 in this case though we should rather tell
1558 * the user that the value cannot be calculated here.
1561 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1562 sic->dk_drive < sip->dk_drive ? 0.0 :
1563 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1564 out, outsize, svg_p->restart);
1566 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1567 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1568 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1569 out + 1, outsize + 1, svg_p->restart);
1571 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1572 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1573 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1574 out + 2, outsize + 2, svg_p->restart);
1576 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1577 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1578 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1579 out + 3, outsize + 3, svg_p->restart);
1581 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1582 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1583 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1584 out + 4, outsize + 4, svg_p->restart);
1587 if (action & F_END) {
1588 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1589 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1591 /* Free remaining structures */
1592 free_graphs(out, outsize, spmin, spmax);
1597 ***************************************************************************
1598 * Display memory statistics in SVG.
1601 * @a Activity structure with statistics.
1602 * @curr Index in array for current sample statistics.
1603 * @action Action expected from current function.
1604 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1605 * flag indicating that a restart record has been previously
1606 * found (.@restart) and time used for the X axis origin
1608 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1609 * @record_hdr Pointer on record header of current stats sample.
1610 ***************************************************************************
1612 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1613 unsigned long long itv, struct record_header *record_hdr)
1616 *smc = (struct stats_memory *) a->buf[curr];
1617 int group1[] = {3, 1, 3, 1, 3, 5};
1618 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1619 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1620 int group2[] = {3, 1, 1};
1621 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1622 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1623 "Memory utilization (3)", "Memory utilization (4)",
1624 "Memory utilization (5)", "Memory utilization (6)"};
1625 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1626 "Swap utilization (3)"};
1627 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1628 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1629 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1631 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1633 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1634 static double *spmin, *spmax;
1636 static int *outsize;
1640 unsigned long long nousedmem;
1642 if (action & F_BEGIN) {
1644 * Allocate arrays that will contain the graphs data
1645 * and the min/max values.
1647 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1650 if (action & F_MAIN) {
1651 /* Check for min/max values */
1652 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1653 itv, spmin, spmax, g_fields);
1654 /* Compute %memused min/max values */
1655 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1656 if (nousedmem > smc->tlmkb) {
1657 nousedmem = smc->tlmkb;
1659 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1660 if (tval > *(spmax + 3)) {
1661 *(spmax + 3) = tval;
1663 if (tval < *(spmin + 3)) {
1664 *(spmin + 3) = tval;
1666 /* Compute %commit min/max values */
1667 tval = (smc->tlmkb + smc->tlskb) ?
1668 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1669 if (tval > *(spmax + 7)) {
1670 *(spmax + 7) = tval;
1672 if (tval < *(spmin + 7)) {
1673 *(spmin + 7) = tval;
1675 /* Compute %swpused min/max values */
1677 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1678 if (tval > *(spmax + 19)) {
1679 *(spmax + 19) = tval;
1681 if (tval < *(spmin + 19)) {
1682 *(spmin + 19) = tval;
1684 /* Compute %swpcad min/max values */
1685 tval = (smc->tlskb - smc->frskb) ?
1686 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1687 if (tval > *(spmax + 20)) {
1688 *(spmax + 20) = tval;
1690 if (tval < *(spmin + 20)) {
1691 *(spmin + 20) = tval;
1693 /* Compute memused min/max values in MB */
1694 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1695 if (tval > *(spmax + 2)) {
1696 *(spmax + 2) = tval;
1698 if (tval < *(spmin + 2)) {
1699 *(spmin + 2) = tval;
1701 /* Compute swpused min/max values in MB */
1702 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1703 if (tval > *(spmax + 17)) {
1704 *(spmax + 17) = tval;
1706 if (tval < *(spmin + 17)) {
1707 *(spmin + 17) = tval;
1711 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1712 ((double) smc->frmkb) / 1024,
1713 out, outsize, svg_p->restart);
1715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1716 ((double) (smc->tlmkb - nousedmem)) / 1024,
1717 out + 2, outsize + 2, svg_p->restart);
1719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1720 ((double) smc->availablekb) / 1024,
1721 out + 1, outsize + 1, svg_p->restart);
1723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1724 ((double) smc->bufkb) / 1024,
1725 out + 4, outsize + 4, svg_p->restart);
1727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1728 ((double) smc->camkb) / 1024,
1729 out + 5, outsize + 5, svg_p->restart);
1731 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1732 ((double) smc->frskb) / 1024,
1733 out + 16, outsize + 16, svg_p->restart);
1735 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1736 ((double) (smc->tlskb - smc->frskb)) / 1024,
1737 out + 17, outsize + 17, svg_p->restart);
1739 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1740 ((double) smc->caskb) / 1024,
1741 out + 18, outsize + 18, svg_p->restart);
1743 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1744 ((double) smc->comkb) / 1024,
1745 out + 6, outsize + 6, svg_p->restart);
1747 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1748 ((double) smc->activekb) / 1024,
1749 out + 8, outsize + 8, svg_p->restart);
1751 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1752 ((double) smc->inactkb) / 1024,
1753 out + 9, outsize + 9, svg_p->restart);
1755 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1756 ((double) smc->dirtykb) / 1024,
1757 out + 10, outsize + 10, svg_p->restart);
1759 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1760 ((double) smc->anonpgkb) / 1024,
1761 out + 11, outsize + 11, svg_p->restart);
1763 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1764 ((double) smc->slabkb) / 1024,
1765 out + 12, outsize + 12, svg_p->restart);
1767 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1768 ((double) smc->kstackkb) / 1024,
1769 out + 13, outsize + 13, svg_p->restart);
1771 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1772 ((double) smc->pgtblkb) / 1024,
1773 out + 14, outsize + 14, svg_p->restart);
1775 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1776 ((double) smc->vmusedkb) / 1024,
1777 out + 15, outsize + 15, svg_p->restart);
1779 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1782 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1783 out + 3, outsize + 3, svg_p->dt);
1785 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1787 (smc->tlmkb + smc->tlskb) ?
1788 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1789 out + 7, outsize + 7, svg_p->dt);
1791 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1794 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1795 out + 19, outsize + 19, svg_p->dt);
1797 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1799 (smc->tlskb - smc->frskb) ?
1800 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1801 out + 20, outsize + 20, svg_p->dt);
1804 if (action & F_END) {
1806 /* Conversion kB -> MB */
1807 for (i = 0; i < 17; i++) {
1808 *(spmin + g_fields[i]) /= 1024;
1809 *(spmax + g_fields[i]) /= 1024;
1812 if (DISPLAY_MEMORY(a->opt_flags)) {
1813 if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1814 g_type1, title1, g_title1, NULL, group1,
1815 spmin, spmax, out, outsize, svg_p, record_hdr,
1816 FALSE, a->id, xid)) {
1821 if (DISPLAY_SWAP(a->opt_flags)) {
1822 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1823 spmin + 16, spmax + 16, out + 16, outsize + 16,
1824 svg_p, record_hdr, FALSE, a->id, xid);
1827 /* Free remaining structures */
1828 free_graphs(out, outsize, spmin, spmax);
1833 ***************************************************************************
1834 * Display kernel tables statistics in SVG.
1837 * @a Activity structure with statistics.
1838 * @curr Index in array for current sample statistics.
1839 * @action Action expected from current function.
1840 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1841 * flag indicating that a restart record has been previously
1842 * found (.@restart) and time used for the X axis origin
1844 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1845 * @record_hdr Pointer on record header of current stats sample.
1846 ***************************************************************************
1848 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1849 unsigned long long itv, struct record_header *record_hdr)
1851 struct stats_ktables
1852 *skc = (struct stats_ktables *) a->buf[curr];
1853 int group[] = {3, 1};
1854 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1855 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1856 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1858 int g_fields[] = {1, 2, 0, 3};
1859 static double *spmin, *spmax;
1861 static int *outsize;
1863 if (action & F_BEGIN) {
1865 * Allocate arrays that will contain the graphs data
1866 * and the min/max values.
1868 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1871 if (action & F_MAIN) {
1872 /* Check for min/max values */
1873 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1874 itv, spmin, spmax, g_fields);
1876 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1877 (unsigned long long) skc->dentry_stat,
1878 out, outsize, svg_p->restart);
1880 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1881 (unsigned long long) skc->file_used,
1882 out + 1, outsize + 1, svg_p->restart);
1884 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1885 (unsigned long long) skc->inode_used,
1886 out + 2, outsize + 2, svg_p->restart);
1888 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1889 (unsigned long long) skc->pty_nr,
1890 out + 3, outsize + 3, svg_p->restart);
1893 if (action & F_END) {
1894 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1895 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1897 /* Free remaining structures */
1898 free_graphs(out, outsize, spmin, spmax);
1903 ***************************************************************************
1904 * Display queue and load statistics in SVG.
1907 * @a Activity structure with statistics.
1908 * @curr Index in array for current sample statistics.
1909 * @action Action expected from current function.
1910 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1911 * flag indicating that a restart record has been previously
1912 * found (.@restart) and time used for the X axis origin
1914 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1915 * @record_hdr Pointer on record header of current stats sample.
1916 ***************************************************************************
1918 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1919 unsigned long long itv, struct record_header *record_hdr)
1922 *sqc = (struct stats_queue *) a->buf[curr];
1923 int group[] = {2, 1, 3};
1924 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1925 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
1926 char *g_title[] = {"~runq-sz", "~blocked",
1928 "ldavg-1", "ldavg-5", "ldavg-15"};
1929 int g_fields[] = {0, 1, 2, 3, 4, 5};
1930 static double *spmin, *spmax;
1932 static int *outsize;
1934 if (action & F_BEGIN) {
1936 * Allocate arrays that will contain the graphs data
1937 * and the min/max values.
1939 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1942 if (action & F_MAIN) {
1943 /* Check for min/max values */
1944 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1945 itv, spmin, spmax, g_fields);
1947 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1948 (unsigned long long) sqc->nr_running,
1949 out, outsize, svg_p->restart);
1951 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1952 (unsigned long long) sqc->procs_blocked,
1953 out + 1, outsize + 1, svg_p->restart);
1955 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1956 (unsigned long long) sqc->nr_threads,
1957 out + 2, outsize + 2, svg_p->restart);
1959 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1960 (double) sqc->load_avg_1 / 100,
1961 out + 3, outsize + 3, svg_p->restart);
1963 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1964 (double) sqc->load_avg_5 / 100,
1965 out + 4, outsize + 4, svg_p->restart);
1967 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1968 (double) sqc->load_avg_15 / 100,
1969 out + 5, outsize + 5, svg_p->restart);
1972 if (action & F_END) {
1973 /* Fix min/max values for load average */
1974 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1975 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1976 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1978 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1979 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1981 /* Free remaining structures */
1982 free_graphs(out, outsize, spmin, spmax);
1987 ***************************************************************************
1988 * Display disk statistics in SVG.
1991 * @a Activity structure with statistics.
1992 * @curr Index in array for current sample statistics.
1993 * @action Action expected from current function.
1994 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1995 * flag indicating that a restart record has been previously
1996 * found (.@restart) and time used for the X axis origin
1998 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1999 * @record_hdr Pointer on record header of current stats sample.
2000 ***************************************************************************
2002 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2003 unsigned long long itv, struct record_header *record_hdr)
2005 struct stats_disk *sdc, *sdp, sdpzero;
2006 struct ext_disk_stats xds;
2007 int group[] = {1, 2, 2, 2, 1};
2008 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2009 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2010 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2011 "Block devices statistics (3)", "Block devices statistics (4)",
2012 "Block devices statistics (5)"};
2013 char *g_title[] = {"tps",
2015 "areq-sz", "aqu-sz",
2018 int g_fields[] = {0, 1, 2};
2019 unsigned int local_types_nr[] = {1, 0, 0};
2020 static double *spmin, *spmax;
2022 static int *outsize;
2024 double rkB, wkB, aqusz;
2025 int i, j, k, pos, restart, *unregistered;
2027 if (action & F_BEGIN) {
2029 * Allocate arrays (#0..7) that will contain the graphs data
2030 * and the min/max values.
2031 * Also allocate one additional array (#8) for each disk device:
2032 * spmax + 8 will contain the device major number,
2033 * spmin + 8 will contain the device minor number,
2034 * outsize + 8 will contain a positive value (TRUE) if the device
2035 * has either still not been registered, or has been unregistered.
2037 out = allocate_graph_lines(9 * a->item_list_sz, &outsize, &spmin, &spmax);
2040 if (action & F_MAIN) {
2041 memset(&sdpzero, 0, STATS_DISK_SIZE);
2042 restart = svg_p->restart;
2044 * Mark previously registered devices as now
2045 * possibly unregistered for all graphs.
2047 for (k = 0; k < a->item_list_sz; k++) {
2048 unregistered = outsize + k * 9 + 8;
2049 if (*unregistered == FALSE) {
2050 *unregistered = MAYBE;
2054 /* For each device structure */
2055 for (i = 0; i < a->nr[curr]; i++) {
2056 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2058 /* Get device name */
2059 item_name = get_sa_devname(sdc->major, sdc->minor, flags);
2061 if (a->item_list != NULL) {
2062 /* A list of devices has been entered on the command line */
2063 if (!search_list_item(a->item_list, item_name))
2064 /* Device not found */
2068 /* Look for corresponding graph */
2069 for (k = 0; k < a->item_list_sz; k++) {
2070 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2071 (sdc->minor == *(spmin + k * 9 + 8)))
2075 if (k == a->item_list_sz) {
2076 /* Graph not found: Look for first free entry */
2077 for (k = 0; k < a->item_list_sz; k++) {
2078 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2081 if (k == a->item_list_sz) {
2082 /* No free graph entry: Ignore it (should never happen) */
2084 fprintf(stderr, "%s: Name=%s major=%d minor=%d\n",
2085 __FUNCTION__, item_name, sdc->major, sdc->minor);
2091 unregistered = outsize + pos + 8;
2094 * If current device was marked as previously unregistered,
2095 * then set restart variable to TRUE so that the graph will be
2096 * discontinuous, and mark it as now registered.
2098 if (*unregistered == TRUE) {
2101 *unregistered = FALSE;
2103 if (*(spmax + pos + 8) == -DBL_MAX) {
2104 /* Save device major and minor numbers (if not already done) */
2105 *(spmax + pos + 8) = sdc->major;
2106 *(spmin + pos + 8) = sdc->minor;
2109 j = check_disk_reg(a, curr, !curr, i);
2111 /* This is a newly registered interface. Previous stats are zero */
2115 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2118 /* Check for min/max values */
2119 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2120 itv, spmin + pos, spmax + pos, g_fields);
2122 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2123 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2124 if (rkB < *(spmin + pos + 1)) {
2125 *(spmin + pos + 1) = rkB;
2127 if (rkB > *(spmax + pos + 1)) {
2128 *(spmax + pos + 1) = rkB;
2130 if (wkB < *(spmin + pos + 2)) {
2131 *(spmin + pos + 2) = wkB;
2133 if (wkB > *(spmax + pos + 2)) {
2134 *(spmax + pos + 2) = wkB;
2137 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2138 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2139 *(spmin + pos + 3) = xds.arqsz / 2;
2141 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2142 *(spmax + pos + 3) = xds.arqsz / 2;
2144 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2145 if (aqusz < *(spmin + pos + 4)) {
2146 *(spmin + pos + 4) = aqusz;
2148 if (aqusz > *(spmax + pos + 4)) {
2149 *(spmax + pos + 4) = aqusz;
2151 if (xds.await < *(spmin + pos + 5)) {
2152 *(spmin + pos + 5) = xds.await;
2154 if (xds.await > *(spmax + pos + 5)) {
2155 *(spmax + pos + 5) = xds.await;
2157 if (xds.svctm < *(spmin + pos + 6)) {
2158 *(spmin + pos + 6) = xds.svctm;
2160 if (xds.svctm > *(spmax + pos + 6)) {
2161 *(spmax + pos + 6) = xds.svctm;
2163 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2164 *(spmin + pos + 7) = xds.util / 10.0;
2166 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2167 *(spmax + pos + 7) = xds.util / 10.0;
2171 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2172 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2173 out + pos, outsize + pos, restart);
2175 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2176 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2177 out + pos + 1, outsize + pos + 1, restart);
2179 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2180 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2181 out + pos + 2, outsize + pos + 2, restart);
2183 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2185 out + pos + 3, outsize + pos + 3, restart);
2187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2189 out + pos + 4, outsize + pos + 4, restart);
2191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2193 out + pos + 5, outsize + pos + 5, restart);
2195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2197 out + pos + 6, outsize + pos + 6, restart);
2199 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2200 0.0, xds.util / 10.0,
2201 out + pos + 7, outsize + pos + 7, svg_p->dt);
2204 /* Mark devices not seen here as now unregistered */
2205 for (k = 0; k < a->item_list_sz; k++) {
2206 unregistered = outsize + k * 9 + 8;
2207 if (*unregistered != FALSE) {
2208 *unregistered = TRUE;
2213 if (action & F_END) {
2216 for (i = 0; i < a->item_list_sz; i++) {
2217 /* Check if there is something to display */
2222 /* Get device name */
2223 item_name = get_sa_devname(*(spmax + pos + 8), *(spmin + pos + 8), flags);
2225 if (draw_activity_graphs(a->g_nr, g_type,
2226 title, g_title, item_name, group,
2227 spmin + pos, spmax + pos, out + pos, outsize + pos,
2228 svg_p, record_hdr, FALSE, a->id, xid)) {
2233 /* Free remaining structures */
2234 free_graphs(out, outsize, spmin, spmax);
2239 ***************************************************************************
2240 * Display network interfaces statistics in SVG.
2243 * @a Activity structure with statistics.
2244 * @curr Index in array for current sample statistics.
2245 * @action Action expected from current function.
2246 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2247 * flag indicating that a restart record has been previously
2248 * found (.@restart) and time used for the X axis origin
2250 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2251 * @record_hdr Pointer on record header of current stats sample.
2252 ***************************************************************************
2254 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2255 unsigned long long itv, struct record_header *record_hdr)
2257 struct stats_net_dev *sndc, *sndp, sndzero;
2258 int group[] = {2, 2, 3, 1};
2259 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2261 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2262 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2263 char *g_title[] = {"rxpck/s", "txpck/s",
2265 "rxcmp/s", "txcmp/s", "rxmcst/s",
2267 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2268 unsigned int local_types_nr[] = {7, 0, 0};
2269 static double *spmin, *spmax;
2271 static int *outsize;
2273 double rxkb, txkb, ifutil;
2274 int i, j, k, pos, restart, *unregistered;
2276 if (action & F_BEGIN) {
2278 * Allocate arrays (#0..7) that will contain the graphs data
2279 * and the min/max values.
2280 * Also allocate one additional array (#8) for each interface:
2281 * out + 8 will contain the interface name,
2282 * outsize + 8 will contain a positive value (TRUE) if the interface
2283 * has either still not been registered, or has been unregistered.
2285 out = allocate_graph_lines(9 * a->item_list_sz, &outsize, &spmin, &spmax);
2288 if (action & F_MAIN) {
2289 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2290 restart = svg_p->restart;
2292 * Mark previously registered interfaces as now
2293 * possibly unregistered for all graphs.
2295 for (k = 0; k < a->item_list_sz; k++) {
2296 unregistered = outsize + k * 9 + 8;
2297 if (*unregistered == FALSE) {
2298 *unregistered = MAYBE;
2302 /* For each network interfaces structure */
2303 for (i = 0; i < a->nr[curr]; i++) {
2304 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2306 if (a->item_list != NULL) {
2307 /* A list of devices has been entered on the command line */
2308 if (!search_list_item(a->item_list, sndc->interface))
2309 /* Device not found */
2313 /* Look for corresponding graph */
2314 for (k = 0; k < a->item_list_sz; k++) {
2315 item_name = *(out + k * 9 + 8);
2316 if (!strcmp(sndc->interface, item_name))
2320 if (k == a->item_list_sz) {
2321 /* Graph not found: Look for first free entry */
2322 for (k = 0; k < a->item_list_sz; k++) {
2323 item_name = *(out + k * 9 + 8);
2324 if (!strcmp(item_name, ""))
2327 if (k == a->item_list_sz) {
2328 /* No free graph entry: Ignore it (should never happen) */
2330 fprintf(stderr, "%s: Name=%s\n",
2331 __FUNCTION__, sndc->interface);
2337 unregistered = outsize + pos + 8;
2339 j = check_net_dev_reg(a, curr, !curr, i);
2341 /* This is a newly registered interface. Previous stats are zero */
2345 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2349 * If current interface was marked as previously unregistered,
2350 * then set restart variable to TRUE so that the graph will be
2351 * discontinuous, and mark it as now registered.
2353 if (*unregistered == TRUE) {
2356 *unregistered = FALSE;
2358 item_name = *(out + pos + 8);
2359 if (!item_name[0]) {
2360 /* Save network interface name (if not already done) */
2361 strncpy(item_name, sndc->interface, CHUNKSIZE);
2362 item_name[CHUNKSIZE - 1] = '\0';
2365 /* Check for min/max values */
2366 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2367 itv, spmin + pos, spmax + pos, g_fields);
2369 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2370 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2371 ifutil = compute_ifutil(sndc, rxkb, txkb);
2372 if (ifutil < *(spmin + pos + 7)) {
2373 *(spmin + pos + 7) = ifutil;
2375 if (ifutil > *(spmax + pos + 7)) {
2376 *(spmax + pos + 7) = ifutil;
2380 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2381 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2382 out + pos, outsize + pos, restart);
2384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2385 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2386 out + pos + 1, outsize + pos + 1, restart);
2388 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2390 out + pos + 2, outsize + pos + 2, restart);
2392 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2394 out + pos + 3, outsize + pos + 3, restart);
2396 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2397 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2398 out + pos + 4, outsize + pos + 4, restart);
2400 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2401 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2402 out + pos + 5, outsize + pos + 5, restart);
2404 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2405 S_VALUE(sndp->multicast, sndc->multicast, itv),
2406 out + pos + 6, outsize + pos + 6, restart);
2408 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2410 out + pos + 7, outsize + pos + 7, svg_p->dt);
2413 /* Mark interfaces not seen here as now unregistered */
2414 for (k = 0; k < a->item_list_sz; k++) {
2415 unregistered = outsize + k * 9 + 8;
2416 if (*unregistered != FALSE) {
2417 *unregistered = TRUE;
2422 if (action & F_END) {
2425 for (i = 0; i < a->item_list_sz; i++) {
2427 * Check if there is something to display.
2428 * Don't test sndc->interface because maybe the network
2429 * interface has been registered later.
2435 /* Recalculate min and max values in kB, not in B */
2436 *(spmin + pos + 2) /= 1024;
2437 *(spmax + pos + 2) /= 1024;
2438 *(spmin + pos + 3) /= 1024;
2439 *(spmax + pos + 3) /= 1024;
2441 item_name = *(out + pos + 8);
2442 if (draw_activity_graphs(a->g_nr, g_type,
2443 title, g_title, item_name, group,
2444 spmin + pos, spmax + pos, out + pos, outsize + pos,
2445 svg_p, record_hdr, FALSE, a->id, xid)) {
2450 /* Free remaining structures */
2451 free_graphs(out, outsize, spmin, spmax);
2456 ***************************************************************************
2457 * Display network interfaces errors statistics in SVG.
2460 * @a Activity structure with statistics.
2461 * @curr Index in array for current sample statistics.
2462 * @action Action expected from current function.
2463 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2464 * flag indicating that a restart record has been previously
2465 * found (.@restart) and time used for the X axis origin
2467 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2468 * @record_hdr Pointer on record header of current stats sample.
2469 ***************************************************************************
2471 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2472 unsigned long long itv, struct record_header *record_hdr)
2474 struct stats_net_edev *snedc, *snedp, snedzero;
2475 int group[] = {2, 2, 2, 3};
2476 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2478 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2479 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2480 char *g_title[] = {"rxerr/s", "txerr/s",
2481 "rxdrop/s", "txdrop/s",
2482 "rxfifo/s", "txfifo/s",
2483 "coll/s", "txcarr/s", "rxfram/s"};
2484 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2485 static double *spmin, *spmax;
2487 static int *outsize;
2489 int i, j, k, pos, restart, *unregistered;
2491 if (action & F_BEGIN) {
2493 * Allocate arrays (#0..8) that will contain the graphs data
2494 * and the min/max values.
2495 * Also allocate one additional array (#9) for each interface:
2496 * out + 9 will contain the interface name,
2497 * outsize + 9 will contain a positive value (TRUE) if the interface
2498 * has either still not been registered, or has been unregistered.
2500 out = allocate_graph_lines(10 * a->item_list_sz, &outsize, &spmin, &spmax);
2503 if (action & F_MAIN) {
2504 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2505 restart = svg_p->restart;
2507 * Mark previously registered interfaces as now
2508 * possibly unregistered for all graphs.
2510 for (k = 0; k < a->item_list_sz; k++) {
2511 unregistered = outsize + k * 10 + 9;
2512 if (*unregistered == FALSE) {
2513 *unregistered = MAYBE;
2517 /* For each network interfaces structure */
2518 for (i = 0; i < a->nr[curr]; i++) {
2519 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2520 if (!strcmp(snedc->interface, ""))
2521 /* Empty structure: This is the end of the list */
2524 if (a->item_list != NULL) {
2525 /* A list of devices has been entered on the command line */
2526 if (!search_list_item(a->item_list, snedc->interface))
2527 /* Device not found */
2531 /* Look for corresponding graph */
2532 for (k = 0; k < a->item_list_sz; k++) {
2533 item_name = *(out + k * 10 + 9);
2534 if (!strcmp(snedc->interface, item_name))
2538 if (k == a->item_list_sz) {
2539 /* Graph not found: Look for first free entry */
2540 for (k = 0; k < a->item_list_sz; k++) {
2541 item_name = *(out + k * 10 + 9);
2542 if (!strcmp(item_name, ""))
2545 if (k == a->item_list_sz) {
2546 /* No free graph entry: Ignore it (should never happen) */
2548 fprintf(stderr, "%s: Name=%s\n",
2549 __FUNCTION__, snedc->interface);
2556 unregistered = outsize + pos + 9;
2558 j = check_net_edev_reg(a, curr, !curr, i);
2560 /* This is a newly registered interface. Previous stats are zero */
2564 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2568 * If current interface was marked as previously unregistered,
2569 * then set restart variable to TRUE so that the graph will be
2570 * discontinuous, and mark it as now registered.
2572 if (*unregistered == TRUE) {
2575 *unregistered = FALSE;
2577 item_name = *(out + pos + 9);
2578 if (!item_name[0]) {
2579 /* Save network interface name (if not already done) */
2580 strncpy(item_name, snedc->interface, CHUNKSIZE);
2581 item_name[CHUNKSIZE - 1] = '\0';
2584 /* Check for min/max values */
2585 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2586 itv, spmin + pos, spmax + pos, g_fields);
2589 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2590 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2591 out + pos, outsize + pos, restart);
2593 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2594 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2595 out + pos + 1, outsize + pos + 1, restart);
2597 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2598 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2599 out + pos + 2, outsize + pos + 2, restart);
2601 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2602 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2603 out + pos + 3, outsize + pos + 3, restart);
2605 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2606 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2607 out + pos + 4, outsize + pos + 4, restart);
2609 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2610 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2611 out + pos + 5, outsize + pos + 5, restart);
2613 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2614 S_VALUE(snedp->collisions, snedc->collisions, itv),
2615 out + pos + 6, outsize + pos + 6, restart);
2617 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2618 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2619 out + pos + 7, outsize + pos + 7, restart);
2621 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2622 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2623 out + pos + 8, outsize + pos + 8, restart);
2626 /* Mark interfaces not seen here as now unregistered */
2627 for (k = 0; k < a->item_list_sz; k++) {
2628 unregistered = outsize + k * 10 + 9;
2629 if (*unregistered != FALSE) {
2630 *unregistered = TRUE;
2635 if (action & F_END) {
2638 for (i = 0; i < a->item_list_sz; i++) {
2640 * Check if there is something to display.
2641 * Don't test snedc->interface because maybe the network
2642 * interface has been registered later.
2648 item_name = *(out + pos + 9);
2649 if (draw_activity_graphs(a->g_nr, g_type,
2650 title, g_title, item_name, group,
2651 spmin + pos, spmax + pos, out + pos, outsize + pos,
2652 svg_p, record_hdr, FALSE, a->id, xid)) {
2657 /* Free remaining structures */
2658 free_graphs(out, outsize, spmin, spmax);
2663 ***************************************************************************
2664 * Display NFS client statistics in SVG.
2667 * @a Activity structure with statistics.
2668 * @curr Index in array for current sample statistics.
2669 * @action Action expected from current function.
2670 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2671 * flag indicating that a restart record has been previously
2672 * found (.@restart) and time used for the X axis origin
2674 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2675 * @record_hdr Pointer on record header of current stats sample.
2676 ***************************************************************************
2678 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2679 unsigned long long itv, struct record_header *record_hdr)
2681 struct stats_net_nfs
2682 *snnc = (struct stats_net_nfs *) a->buf[curr],
2683 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2684 int group[] = {2, 2, 2};
2685 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2686 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2687 "NFS client statistics (3)"};
2688 char *g_title[] = {"call/s", "retrans/s",
2689 "read/s", "write/s",
2690 "access/s", "getatt/s"};
2691 int g_fields[] = {0, 1, 2, 3, 4, 5};
2692 static double *spmin, *spmax;
2694 static int *outsize;
2696 if (action & F_BEGIN) {
2698 * Allocate arrays that will contain the graphs data
2699 * and the min/max values.
2701 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2704 if (action & F_MAIN) {
2705 /* Check for min/max values */
2706 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2707 itv, spmin, spmax, g_fields);
2710 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2711 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2712 out, outsize, svg_p->restart);
2714 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2715 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2716 out + 1, outsize + 1, svg_p->restart);
2718 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2719 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2720 out + 2, outsize + 2, svg_p->restart);
2722 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2723 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2724 out + 3, outsize + 3, svg_p->restart);
2726 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2727 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2728 out + 4, outsize + 4, svg_p->restart);
2730 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2731 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2732 out + 5, outsize + 5, svg_p->restart);
2735 if (action & F_END) {
2736 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2737 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2739 /* Free remaining structures */
2740 free_graphs(out, outsize, spmin, spmax);
2745 ***************************************************************************
2746 * Display NFS server statistics in SVG.
2749 * @a Activity structure with statistics.
2750 * @curr Index in array for current sample statistics.
2751 * @action Action expected from current function.
2752 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2753 * flag indicating that a restart record has been previously
2754 * found (.@restart) and time used for the X axis origin
2756 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2757 * @record_hdr Pointer on record header of current stats sample.
2758 ***************************************************************************
2760 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2761 unsigned long long itv, struct record_header *record_hdr)
2763 struct stats_net_nfsd
2764 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2765 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2766 int group[] = {2, 3, 2, 2, 2};
2767 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2768 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2769 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2770 "NFS server statistics (3)", "NFS server statistics (4)",
2771 "NFS server statistics (5)"};
2772 char *g_title[] = {"scall/s", "badcall/s",
2773 "packet/s", "udp/s", "tcp/s",
2775 "sread/s", "swrite/s",
2776 "saccess/s", "sgetatt/s"};
2777 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2778 static double *spmin, *spmax;
2780 static int *outsize;
2782 if (action & F_BEGIN) {
2784 * Allocate arrays that will contain the graphs data
2785 * and the min/max values.
2787 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2790 if (action & F_MAIN) {
2791 /* Check for min/max values */
2792 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2793 itv, spmin, spmax, g_fields);
2796 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2797 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2798 out, outsize, svg_p->restart);
2800 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2801 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2802 out + 1, outsize + 1, svg_p->restart);
2804 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2805 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2806 out + 2, outsize + 2, svg_p->restart);
2808 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2809 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2810 out + 3, outsize + 3, svg_p->restart);
2812 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2813 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2814 out + 4, outsize + 4, svg_p->restart);
2816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2817 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2818 out + 5, outsize + 5, svg_p->restart);
2820 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2821 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2822 out + 6, outsize + 6, svg_p->restart);
2824 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2825 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2826 out + 7, outsize + 7, svg_p->restart);
2828 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2829 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2830 out + 8, outsize + 8, svg_p->restart);
2832 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2833 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2834 out + 9, outsize + 9, svg_p->restart);
2836 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2837 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2838 out + 10, outsize + 10, svg_p->restart);
2841 if (action & F_END) {
2842 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2843 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2845 /* Free remaining structures */
2846 free_graphs(out, outsize, spmin, spmax);
2851 ***************************************************************************
2852 * Display socket statistics in SVG.
2855 * @a Activity structure with statistics.
2856 * @curr Index in array for current sample statistics.
2857 * @action Action expected from current function.
2858 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2859 * flag indicating that a restart record has been previously
2860 * found (.@restart) and time used for the X axis origin
2862 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2863 * @record_hdr Pointer on record header of current stats sample.
2864 ***************************************************************************
2866 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2867 unsigned long long itv, struct record_header *record_hdr)
2869 struct stats_net_sock
2870 *snsc = (struct stats_net_sock *) a->buf[curr];
2871 int group[] = {1, 5};
2872 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2873 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2874 char *g_title[] = {"~totsck",
2875 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2876 int g_fields[] = {0, 1, 5, 2, 3, 4};
2877 static double *spmin, *spmax;
2879 static int *outsize;
2881 if (action & F_BEGIN) {
2883 * Allocate arrays that will contain the graphs data
2884 * and the min/max values.
2886 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2889 if (action & F_MAIN) {
2890 /* Check for min/max values */
2891 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2892 itv, spmin, spmax, g_fields);
2894 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2895 (unsigned long long) snsc->sock_inuse,
2896 out, outsize, svg_p->restart);
2898 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2899 (unsigned long long) snsc->tcp_inuse,
2900 out + 1, outsize + 1, svg_p->restart);
2902 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2903 (unsigned long long) snsc->udp_inuse,
2904 out + 2, outsize + 2, svg_p->restart);
2906 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2907 (unsigned long long) snsc->raw_inuse,
2908 out + 3, outsize + 3, svg_p->restart);
2910 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2911 (unsigned long long) snsc->frag_inuse,
2912 out + 4, outsize + 4, svg_p->restart);
2914 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2915 (unsigned long long) snsc->tcp_tw,
2916 out + 5, outsize + 5, svg_p->restart);
2919 if (action & F_END) {
2920 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2921 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2923 /* Free remaining structures */
2924 free_graphs(out, outsize, spmin, spmax);
2929 ***************************************************************************
2930 * Display IPv4 traffic statistics in SVG.
2933 * @a Activity structure with statistics.
2934 * @curr Index in array for current sample statistics.
2935 * @action Action expected from current function.
2936 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2937 * flag indicating that a restart record has been previously
2938 * found (.@restart) and time used for the X axis origin
2940 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2941 * @record_hdr Pointer on record header of current stats sample.
2942 ***************************************************************************
2944 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2945 unsigned long long itv, struct record_header *record_hdr)
2948 *snic = (struct stats_net_ip *) a->buf[curr],
2949 *snip = (struct stats_net_ip *) a->buf[!curr];
2950 int group[] = {4, 2, 2};
2951 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2952 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
2953 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2954 "asmrq/s", "asmok/s",
2955 "fragok/s", "fragcrt/s"};
2956 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2957 static double *spmin, *spmax;
2959 static int *outsize;
2961 if (action & F_BEGIN) {
2963 * Allocate arrays that will contain the graphs data
2964 * and the min/max values.
2966 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2969 if (action & F_MAIN) {
2970 /* Check for min/max values */
2971 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2972 itv, spmin, spmax, g_fields);
2975 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2976 S_VALUE(snip->InReceives, snic->InReceives, itv),
2977 out, outsize, svg_p->restart);
2979 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2980 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2981 out + 1, outsize + 1, svg_p->restart);
2983 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2984 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2985 out + 2, outsize + 2, svg_p->restart);
2987 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2988 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2989 out + 3, outsize + 3, svg_p->restart);
2991 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2992 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2993 out + 4, outsize + 4, svg_p->restart);
2995 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2996 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2997 out + 5, outsize + 5, svg_p->restart);
2999 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3000 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3001 out + 6, outsize + 6, svg_p->restart);
3003 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3004 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3005 out + 7, outsize + 7, svg_p->restart);
3008 if (action & F_END) {
3009 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3010 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3012 /* Free remaining structures */
3013 free_graphs(out, outsize, spmin, spmax);
3018 ***************************************************************************
3019 * Display IPv4 traffic errors statistics in SVG.
3022 * @a Activity structure with statistics.
3023 * @curr Index in array for current sample statistics.
3024 * @action Action expected from current function.
3025 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3026 * flag indicating that a restart record has been previously
3027 * found (.@restart) and time used for the X axis origin
3029 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3030 * @record_hdr Pointer on record header of current stats sample.
3031 ***************************************************************************
3033 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3034 unsigned long long itv, struct record_header *record_hdr)
3036 struct stats_net_eip
3037 *sneic = (struct stats_net_eip *) a->buf[curr],
3038 *sneip = (struct stats_net_eip *) a->buf[!curr];
3039 int group[] = {3, 2, 3};
3040 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3041 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3042 "IPv4 traffic errors statistics (3)"};
3043 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3044 "idisc/s", "odisc/s",
3045 "onort/s", "asmf/s", "fragf/s"};
3046 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3047 static double *spmin, *spmax;
3049 static int *outsize;
3051 if (action & F_BEGIN) {
3053 * Allocate arrays that will contain the graphs data
3054 * and the min/max values.
3056 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3059 if (action & F_MAIN) {
3060 /* Check for min/max values */
3061 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3062 itv, spmin, spmax, g_fields);
3065 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3066 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3067 out, outsize, svg_p->restart);
3069 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3070 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3071 out + 1, outsize + 1, svg_p->restart);
3073 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3074 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3075 out + 2, outsize + 2, svg_p->restart);
3077 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3078 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3079 out + 3, outsize + 3, svg_p->restart);
3081 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3082 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3083 out + 4, outsize + 4, svg_p->restart);
3085 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3086 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3087 out + 5, outsize + 5, svg_p->restart);
3089 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3090 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3091 out + 6, outsize + 6, svg_p->restart);
3093 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3094 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3095 out + 7, outsize + 7, svg_p->restart);
3098 if (action & F_END) {
3099 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3100 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3102 /* Free remaining structures */
3103 free_graphs(out, outsize, spmin, spmax);
3108 ***************************************************************************
3109 * Display ICMPv4 traffic statistics in SVG.
3112 * @a Activity structure with statistics.
3113 * @curr Index in array for current sample statistics.
3114 * @action Action expected from current function.
3115 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3116 * flag indicating that a restart record has been previously
3117 * found (.@restart) and time used for the X axis origin
3119 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3120 * @record_hdr Pointer on record header of current stats sample.
3121 ***************************************************************************
3123 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3124 unsigned long long itv, struct record_header *record_hdr)
3126 struct stats_net_icmp
3127 *snic = (struct stats_net_icmp *) a->buf[curr],
3128 *snip = (struct stats_net_icmp *) a->buf[!curr];
3129 int group[] = {2, 4, 4, 4};
3130 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3132 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3133 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3134 char *g_title[] = {"imsg/s", "omsg/s",
3135 "iech/s", "iechr/s", "oech/s", "oechr/s",
3136 "itm/s", "itmr/s", "otm/s", "otmr/s",
3137 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3138 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3139 static double *spmin, *spmax;
3141 static int *outsize;
3143 if (action & F_BEGIN) {
3145 * Allocate arrays that will contain the graphs data
3146 * and the min/max values.
3148 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3151 if (action & F_MAIN) {
3152 /* Check for min/max values */
3153 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3154 itv, spmin, spmax, g_fields);
3157 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3158 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3159 out, outsize, svg_p->restart);
3161 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3162 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3163 out + 1, outsize + 1, svg_p->restart);
3165 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3166 S_VALUE(snip->InEchos, snic->InEchos, itv),
3167 out + 2, outsize + 2, svg_p->restart);
3169 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3170 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3171 out + 3, outsize + 3, svg_p->restart);
3173 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3174 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3175 out + 4, outsize + 4, svg_p->restart);
3177 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3178 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3179 out + 5, outsize + 5, svg_p->restart);
3181 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3182 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3183 out + 6, outsize + 6, svg_p->restart);
3185 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3186 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3187 out + 7, outsize + 7, svg_p->restart);
3189 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3190 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3191 out + 8, outsize + 8, svg_p->restart);
3193 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3194 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3195 out + 9, outsize + 9, svg_p->restart);
3197 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3198 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3199 out + 10, outsize + 10, svg_p->restart);
3201 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3202 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3203 out + 11, outsize + 11, svg_p->restart);
3205 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3206 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3207 out + 12, outsize + 12, svg_p->restart);
3209 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3210 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3211 out + 13, outsize + 13, svg_p->restart);
3214 if (action & F_END) {
3215 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3216 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3218 /* Free remaining structures */
3219 free_graphs(out, outsize, spmin, spmax);
3224 ***************************************************************************
3225 * Display ICMPv4 traffic errors statistics in SVG.
3228 * @a Activity structure with statistics.
3229 * @curr Index in array for current sample statistics.
3230 * @action Action expected from current function.
3231 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3232 * flag indicating that a restart record has been previously
3233 * found (.@restart) and time used for the X axis origin
3235 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3236 * @record_hdr Pointer on record header of current stats sample.
3237 ***************************************************************************
3239 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3240 unsigned long long itv, struct record_header *record_hdr)
3242 struct stats_net_eicmp
3243 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3244 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3245 int group[] = {2, 2, 2, 2, 2, 2};
3246 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3247 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3248 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3249 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3250 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3251 char *g_title[] = {"ierr/s", "oerr/s",
3252 "idstunr/s", "odstunr/s",
3253 "itmex/s", "otmex/s",
3254 "iparmpb/s", "oparmpb/s",
3255 "isrcq/s", "osrcq/s",
3256 "iredir/s", "oredir/s"};
3257 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3258 static double *spmin, *spmax;
3260 static int *outsize;
3262 if (action & F_BEGIN) {
3264 * Allocate arrays that will contain the graphs data
3265 * and the min/max values.
3267 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3270 if (action & F_MAIN) {
3271 /* Check for min/max values */
3272 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3273 itv, spmin, spmax, g_fields);
3276 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3277 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3278 out, outsize, svg_p->restart);
3280 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3281 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3282 out + 1, outsize + 1, svg_p->restart);
3284 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3285 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3286 out + 2, outsize + 2, svg_p->restart);
3288 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3289 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3290 out + 3, outsize + 3, svg_p->restart);
3292 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3293 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3294 out + 4, outsize + 4, svg_p->restart);
3296 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3297 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3298 out + 5, outsize + 5, svg_p->restart);
3300 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3301 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3302 out + 6, outsize + 6, svg_p->restart);
3304 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3305 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3306 out + 7, outsize + 7, svg_p->restart);
3308 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3309 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3310 out + 8, outsize + 8, svg_p->restart);
3312 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3313 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3314 out + 9, outsize + 9, svg_p->restart);
3316 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3317 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3318 out + 10, outsize + 10, svg_p->restart);
3320 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3321 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3322 out + 11, outsize + 11, svg_p->restart);
3325 if (action & F_END) {
3326 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3327 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3329 /* Free remaining structures */
3330 free_graphs(out, outsize, spmin, spmax);
3335 ***************************************************************************
3336 * Display TCPv4 traffic statistics in SVG.
3339 * @a Activity structure with statistics.
3340 * @curr Index in array for current sample statistics.
3341 * @action Action expected from current function.
3342 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3343 * flag indicating that a restart record has been previously
3344 * found (.@restart) and time used for the X axis origin
3346 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3347 * @record_hdr Pointer on record header of current stats sample.
3348 ***************************************************************************
3350 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3351 unsigned long long itv, struct record_header *record_hdr)
3353 struct stats_net_tcp
3354 *sntc = (struct stats_net_tcp *) a->buf[curr],
3355 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3356 int group[] = {2, 2};
3357 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3358 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3359 char *g_title[] = {"active/s", "passive/s",
3360 "iseg/s", "oseg/s"};
3361 int g_fields[] = {0, 1, 2, 3};
3362 static double *spmin, *spmax;
3364 static int *outsize;
3366 if (action & F_BEGIN) {
3368 * Allocate arrays that will contain the graphs data
3369 * and the min/max values.
3371 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3374 if (action & F_MAIN) {
3375 /* Check for min/max values */
3376 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3377 itv, spmin, spmax, g_fields);
3380 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3381 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3382 out, outsize, svg_p->restart);
3384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3385 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3386 out + 1, outsize + 1, svg_p->restart);
3388 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3389 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3390 out + 2, outsize + 2, svg_p->restart);
3392 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3393 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3394 out + 3, outsize + 3, svg_p->restart);
3397 if (action & F_END) {
3398 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3399 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3401 /* Free remaining structures */
3402 free_graphs(out, outsize, spmin, spmax);
3407 ***************************************************************************
3408 * Display TCPv4 traffic errors statistics in SVG.
3411 * @a Activity structure with statistics.
3412 * @curr Index in array for current sample statistics.
3413 * @action Action expected from current function.
3414 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3415 * flag indicating that a restart record has been previously
3416 * found (.@restart) and time used for the X axis origin
3418 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3419 * @record_hdr Pointer on record header of current stats sample.
3420 ***************************************************************************
3422 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3423 unsigned long long itv, struct record_header *record_hdr)
3425 struct stats_net_etcp
3426 *snetc = (struct stats_net_etcp *) a->buf[curr],
3427 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3428 int group[] = {2, 3};
3429 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3430 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3431 char *g_title[] = {"atmptf/s", "estres/s",
3432 "retrans/s", "isegerr/s", "orsts/s"};
3433 int g_fields[] = {0, 1, 2, 3, 4};
3434 static double *spmin, *spmax;
3436 static int *outsize;
3438 if (action & F_BEGIN) {
3440 * Allocate arrays that will contain the graphs data
3441 * and the min/max values.
3443 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3446 if (action & F_MAIN) {
3447 /* Check for min/max values */
3448 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3449 itv, spmin, spmax, g_fields);
3452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3453 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3454 out, outsize, svg_p->restart);
3456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3457 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3458 out + 1, outsize + 1, svg_p->restart);
3460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3461 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3462 out + 2, outsize + 2, svg_p->restart);
3464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3465 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3466 out + 3, outsize + 3, svg_p->restart);
3468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3469 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3470 out + 4, outsize + 4, svg_p->restart);
3473 if (action & F_END) {
3474 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3475 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3477 /* Free remaining structures */
3478 free_graphs(out, outsize, spmin, spmax);
3483 ***************************************************************************
3484 * Display UDPv4 traffic statistics in SVG.
3487 * @a Activity structure with statistics.
3488 * @curr Index in array for current sample statistics.
3489 * @action Action expected from current function.
3490 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3491 * flag indicating that a restart record has been previously
3492 * found (.@restart) and time used for the X axis origin
3494 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3495 * @record_hdr Pointer on record header of current stats sample.
3496 ***************************************************************************
3498 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3499 unsigned long long itv, struct record_header *record_hdr)
3501 struct stats_net_udp
3502 *snuc = (struct stats_net_udp *) a->buf[curr],
3503 *snup = (struct stats_net_udp *) a->buf[!curr];
3504 int group[] = {2, 2};
3505 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3506 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3507 char *g_title[] = {"idgm/s", "odgm/s",
3508 "noport/s", "idgmerr/s"};
3509 int g_fields[] = {0, 1, 2, 3};
3510 static double *spmin, *spmax;
3512 static int *outsize;
3514 if (action & F_BEGIN) {
3516 * Allocate arrays that will contain the graphs data
3517 * and the min/max values.
3519 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3522 if (action & F_MAIN) {
3523 /* Check for min/max values */
3524 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3525 itv, spmin, spmax, g_fields);
3528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3529 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3530 out, outsize, svg_p->restart);
3532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3533 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3534 out + 1, outsize + 1, svg_p->restart);
3536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3537 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3538 out + 2, outsize + 2, svg_p->restart);
3540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3541 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3542 out + 3, outsize + 3, svg_p->restart);
3545 if (action & F_END) {
3546 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3547 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3549 /* Free remaining structures */
3550 free_graphs(out, outsize, spmin, spmax);
3555 ***************************************************************************
3556 * Display IPV6 socket statistics in SVG.
3559 * @a Activity structure with statistics.
3560 * @curr Index in array for current sample statistics.
3561 * @action Action expected from current function.
3562 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3563 * flag indicating that a restart record has been previously
3564 * found (.@restart) and time used for the X axis origin
3566 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3567 * @record_hdr Pointer on record header of current stats sample.
3568 ***************************************************************************
3570 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3571 unsigned long long itv, struct record_header *record_hdr)
3573 struct stats_net_sock6
3574 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3576 int g_type[] = {SVG_LINE_GRAPH};
3577 char *title[] = {"IPv6 sockets statistics"};
3578 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3579 int g_fields[] = {0, 1, 2, 3};
3580 static double *spmin, *spmax;
3582 static int *outsize;
3584 if (action & F_BEGIN) {
3586 * Allocate arrays that will contain the graphs data
3587 * and the min/max values.
3589 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3592 if (action & F_MAIN) {
3593 /* Check for min/max values */
3594 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3595 itv, spmin, spmax, g_fields);
3597 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3598 (unsigned long long) snsc->tcp6_inuse,
3599 out, outsize, svg_p->restart);
3601 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3602 (unsigned long long) snsc->udp6_inuse,
3603 out + 1, outsize + 1, svg_p->restart);
3605 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3606 (unsigned long long) snsc->raw6_inuse,
3607 out + 2, outsize + 2, svg_p->restart);
3609 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3610 (unsigned long long) snsc->frag6_inuse,
3611 out + 3, outsize + 3, svg_p->restart);
3614 if (action & F_END) {
3615 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3616 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3618 /* Free remaining structures */
3619 free_graphs(out, outsize, spmin, spmax);
3624 ***************************************************************************
3625 * Display IPv6 traffic statistics in SVG.
3628 * @a Activity structure with statistics.
3629 * @curr Index in array for current sample statistics.
3630 * @action Action expected from current function.
3631 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3632 * flag indicating that a restart record has been previously
3633 * found (.@restart) and time used for the X axis origin
3635 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3636 * @record_hdr Pointer on record header of current stats sample.
3637 ***************************************************************************
3639 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3640 unsigned long long itv, struct record_header *record_hdr)
3642 struct stats_net_ip6
3643 *snic = (struct stats_net_ip6 *) a->buf[curr],
3644 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3645 int group[] = {4, 2, 2, 2};
3646 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3648 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3649 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3650 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3651 "asmrq6/s", "asmok6/s",
3652 "imcpck6/s", "omcpck6/s",
3653 "fragok6/s", "fragcr6/s"};
3654 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3655 static double *spmin, *spmax;
3657 static int *outsize;
3659 if (action & F_BEGIN) {
3661 * Allocate arrays that will contain the graphs data
3662 * and the min/max values.
3664 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3667 if (action & F_MAIN) {
3668 /* Check for min/max values */
3669 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3670 itv, spmin, spmax, g_fields);
3673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3674 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3675 out, outsize, svg_p->restart);
3677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3678 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3679 out + 1, outsize + 1, svg_p->restart);
3681 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3682 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3683 out + 2, outsize + 2, svg_p->restart);
3685 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3686 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3687 out + 3, outsize + 3, svg_p->restart);
3689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3690 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3691 out + 4, outsize + 4, svg_p->restart);
3693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3694 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3695 out + 5, outsize + 5, svg_p->restart);
3697 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3698 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3699 out + 6, outsize + 6, svg_p->restart);
3701 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3702 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3703 out + 7, outsize + 7, svg_p->restart);
3705 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3706 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3707 out + 8, outsize + 8, svg_p->restart);
3709 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3710 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3711 out + 9, outsize + 9, svg_p->restart);
3714 if (action & F_END) {
3715 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3716 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3718 /* Free remaining structures */
3719 free_graphs(out, outsize, spmin, spmax);
3724 ***************************************************************************
3725 * Display IPv6 traffic errors statistics in SVG.
3728 * @a Activity structure with statistics.
3729 * @curr Index in array for current sample statistics.
3730 * @action Action expected from current function.
3731 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3732 * flag indicating that a restart record has been previously
3733 * found (.@restart) and time used for the X axis origin
3735 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3736 * @record_hdr Pointer on record header of current stats sample.
3737 ***************************************************************************
3739 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3740 unsigned long long itv, struct record_header *record_hdr)
3742 struct stats_net_eip6
3743 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3744 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3745 int group[] = {4, 2, 2, 3};
3746 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3748 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3749 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3750 "IPv6 traffic errors statistics (5)"};
3751 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3752 "idisc6/s", "odisc6/s",
3753 "inort6/s", "onort6/s",
3754 "asmf6/s", "fragf6/s", "itrpck6/s"};
3755 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3756 static double *spmin, *spmax;
3758 static int *outsize;
3760 if (action & F_BEGIN) {
3762 * Allocate arrays that will contain the graphs data
3763 * and the min/max values.
3765 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3768 if (action & F_MAIN) {
3769 /* Check for min/max values */
3770 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3771 itv, spmin, spmax, g_fields);
3774 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3775 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3776 out, outsize, svg_p->restart);
3778 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3779 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3780 out + 1, outsize + 1, svg_p->restart);
3782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3783 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3784 out + 2, outsize + 2, svg_p->restart);
3786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3787 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3788 out + 3, outsize + 3, svg_p->restart);
3790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3791 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3792 out + 4, outsize + 4, svg_p->restart);
3794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3795 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3796 out + 5, outsize + 5, svg_p->restart);
3798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3799 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3800 out + 6, outsize + 6, svg_p->restart);
3802 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3803 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3804 out + 7, outsize + 7, svg_p->restart);
3806 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3807 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3808 out + 8, outsize + 8, svg_p->restart);
3810 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3811 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3812 out + 9, outsize + 9, svg_p->restart);
3814 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3815 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3816 out + 10, outsize + 10, svg_p->restart);
3819 if (action & F_END) {
3820 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3821 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3823 /* Free remaining structures */
3824 free_graphs(out, outsize, spmin, spmax);
3829 ***************************************************************************
3830 * Display ICMPv6 traffic statistics in SVG.
3833 * @a Activity structure with statistics.
3834 * @curr Index in array for current sample statistics.
3835 * @action Action expected from current function.
3836 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3837 * flag indicating that a restart record has been previously
3838 * found (.@restart) and time used for the X axis origin
3840 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3841 * @record_hdr Pointer on record header of current stats sample.
3842 ***************************************************************************
3844 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3845 unsigned long long itv, struct record_header *record_hdr)
3847 struct stats_net_icmp6
3848 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3849 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3850 int group[] = {2, 3, 5, 3, 4};
3851 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3852 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3853 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3854 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3855 "ICMPv6 traffic statistics (5)"};
3856 char *g_title[] = {"imsg6/s", "omsg6/s",
3857 "iech6/s", "iechr6/s", "oechr6/s",
3858 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3859 "irtsol6/s", "ortsol6/s", "irtad6/s",
3860 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3861 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3862 static double *spmin, *spmax;
3864 static int *outsize;
3866 if (action & F_BEGIN) {
3868 * Allocate arrays that will contain the graphs data
3869 * and the min/max values.
3871 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3874 if (action & F_MAIN) {
3875 /* Check for min/max values */
3876 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3877 itv, spmin, spmax, g_fields);
3880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3881 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3882 out, outsize, svg_p->restart);
3884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3885 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3886 out + 1, outsize + 1, svg_p->restart);
3888 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3889 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3890 out + 2, outsize + 2, svg_p->restart);
3892 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3893 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3894 out + 3, outsize + 3, svg_p->restart);
3896 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3897 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3898 out + 4, outsize + 4, svg_p->restart);
3900 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3901 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3902 out + 5, outsize + 5, svg_p->restart);
3904 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3905 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3906 out + 6, outsize + 6, svg_p->restart);
3908 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3909 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3910 out + 7, outsize + 7, svg_p->restart);
3912 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3913 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3914 out + 8, outsize + 8, svg_p->restart);
3916 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3917 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3918 out + 9, outsize + 9, svg_p->restart);
3920 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3921 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3922 out + 10, outsize + 10, svg_p->restart);
3924 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3925 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3926 out + 11, outsize + 11, svg_p->restart);
3928 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3929 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3930 out + 12, outsize + 12, svg_p->restart);
3932 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3933 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
3934 out + 13, outsize + 13, svg_p->restart);
3936 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3937 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3938 out + 14, outsize + 14, svg_p->restart);
3940 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3941 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3942 out + 15, outsize + 15, svg_p->restart);
3944 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3945 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3946 out + 16, outsize + 16, svg_p->restart);
3949 if (action & F_END) {
3950 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3951 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3953 /* Free remaining structures */
3954 free_graphs(out, outsize, spmin, spmax);
3959 ***************************************************************************
3960 * Display ICMPv6 traffic errors statistics in SVG.
3963 * @a Activity structure with statistics.
3964 * @curr Index in array for current sample statistics.
3965 * @action Action expected from current function.
3966 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3967 * flag indicating that a restart record has been previously
3968 * found (.@restart) and time used for the X axis origin
3970 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3971 * @record_hdr Pointer on record header of current stats sample.
3972 ***************************************************************************
3974 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3975 unsigned long long itv, struct record_header *record_hdr)
3977 struct stats_net_eicmp6
3978 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3979 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3980 int group[] = {1, 2, 2, 2, 2, 2};
3981 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3982 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3983 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
3984 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
3985 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
3986 char *g_title[] = {"ierr6/s",
3987 "idtunr6/s", "odtunr6/s",
3988 "itmex6/s", "otmex6/s",
3989 "iprmpb6/s", "oprmpb6/s",
3990 "iredir6/s", "oredir6/s",
3991 "ipck2b6/s", "opck2b6/s"};
3992 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3993 static double *spmin, *spmax;
3995 static int *outsize;
3997 if (action & F_BEGIN) {
3999 * Allocate arrays that will contain the graphs data
4000 * and the min/max values.
4002 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4005 if (action & F_MAIN) {
4006 /* Check for min/max values */
4007 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4008 itv, spmin, spmax, g_fields);
4011 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4012 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4013 out, outsize, svg_p->restart);
4015 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4016 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4017 out + 1, outsize + 1, svg_p->restart);
4019 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4020 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4021 out + 2, outsize + 2, svg_p->restart);
4023 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4024 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4025 out + 3, outsize + 3, svg_p->restart);
4027 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4028 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4029 out + 4, outsize + 4, svg_p->restart);
4031 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4032 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4033 out + 5, outsize + 5, svg_p->restart);
4035 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4036 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4037 out + 6, outsize + 6, svg_p->restart);
4039 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4040 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4041 out + 7, outsize + 7, svg_p->restart);
4043 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4044 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4045 out + 8, outsize + 8, svg_p->restart);
4047 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4048 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4049 out + 9, outsize + 9, svg_p->restart);
4051 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4052 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4053 out + 10, outsize + 10, svg_p->restart);
4056 if (action & F_END) {
4057 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4058 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4060 /* Free remaining structures */
4061 free_graphs(out, outsize, spmin, spmax);
4066 ***************************************************************************
4067 * Display UDPv6 traffic statistics in SVG.
4070 * @a Activity structure with statistics.
4071 * @curr Index in array for current sample statistics.
4072 * @action Action expected from current function.
4073 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4074 * flag indicating that a restart record has been previously
4075 * found (.@restart) and time used for the X axis origin
4077 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4078 * @record_hdr Pointer on record header of current stats sample.
4079 ***************************************************************************
4081 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4082 unsigned long long itv, struct record_header *record_hdr)
4084 struct stats_net_udp6
4085 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4086 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4087 int group[] = {2, 2};
4088 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4089 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4090 char *g_title[] = {"idgm6/s", "odgm6/s",
4091 "noport6/s", "idgmer6/s"};
4092 int g_fields[] = {0, 1, 2, 3};
4093 static double *spmin, *spmax;
4095 static int *outsize;
4097 if (action & F_BEGIN) {
4099 * Allocate arrays that will contain the graphs data
4100 * and the min/max values.
4102 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4105 if (action & F_MAIN) {
4106 /* Check for min/max values */
4107 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4108 itv, spmin, spmax, g_fields);
4111 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4112 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4113 out, outsize, svg_p->restart);
4115 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4116 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4117 out + 1, outsize + 1, svg_p->restart);
4119 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4120 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4121 out + 2, outsize + 2, svg_p->restart);
4123 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4124 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4125 out + 3, outsize + 3, svg_p->restart);
4128 if (action & F_END) {
4129 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4130 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4132 /* Free remaining structures */
4133 free_graphs(out, outsize, spmin, spmax);
4138 ***************************************************************************
4139 * Display CPU frequency statistics in SVG.
4142 * @a Activity structure with statistics.
4143 * @curr Index in array for current sample statistics.
4144 * @action Action expected from current function.
4145 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4146 * flag indicating that a restart record has been previously
4147 * found (.@restart) and time used for the X axis origin
4149 * @itv Interval of time in 1/100th of a second (unused here).
4150 * @record_hdr Pointer on record header of current stats sample.
4151 ***************************************************************************
4153 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4154 unsigned long long itv, struct record_header *record_hdr)
4156 struct stats_pwr_cpufreq *spc, *spp;
4158 int g_type[] = {SVG_LINE_GRAPH};
4159 char *title[] = {"CPU clock frequency"};
4160 char *g_title[] = {"MHz"};
4161 static double *spmin, *spmax;
4163 static int *outsize;
4167 if (action & F_BEGIN) {
4169 * Allocate arrays that will contain the graphs data
4170 * and the min/max values.
4172 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4175 if (action & F_MAIN) {
4177 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4179 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4180 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4182 /* Should current CPU (including CPU "all") be displayed? */
4183 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4188 * Note: Don't skip offline CPU here as it is needed
4189 * to make the graph go though 0.
4193 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4194 ((double) spp->cpufreq) / 100,
4195 ((double) spc->cpufreq) / 100,
4196 out + i, outsize + i, svg_p->restart, svg_p->dt,
4197 spmin + i, spmax + i);
4201 if (action & F_END) {
4204 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
4206 /* Should current CPU (including CPU "all") be displayed? */
4207 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4212 /* This is CPU "all" */
4213 strcpy(item_name, "all");
4217 * If the maximum frequency reached by the CPU is 0, then
4218 * the CPU has been offline on the whole period.
4219 * => Don't display it.
4221 if (*(spmax + i) == 0)
4224 sprintf(item_name, "%d", i - 1);
4227 if (draw_activity_graphs(a->g_nr, g_type,
4228 title, g_title, item_name, group,
4229 spmin + i, spmax + i, out + i, outsize + i,
4230 svg_p, record_hdr, i, a->id, xid)) {
4235 /* Free remaining structures */
4236 free_graphs(out, outsize, spmin, spmax);
4241 ***************************************************************************
4242 * Display fan statistics in SVG.
4245 * @a Activity structure with statistics.
4246 * @curr Index in array for current sample statistics.
4247 * @action Action expected from current function.
4248 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4249 * flag indicating that a restart record has been previously
4250 * found (.@restart) and time used for the X axis origin
4252 * @itv Interval of time in 1/100th of a second (unused here).
4253 * @record_hdr Pointer on record header of current stats sample.
4254 ***************************************************************************
4256 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4257 unsigned long long itv, struct record_header *record_hdr)
4259 struct stats_pwr_fan *spc, *spp;
4261 int g_type[] = {SVG_LINE_GRAPH};
4262 char *title[] = {"Fans speed"};
4263 char *g_title[] = {"~rpm"};
4264 static double *spmin, *spmax;
4266 static int *outsize;
4267 char item_name[MAX_SENSORS_DEV_LEN + 8];
4270 if (action & F_BEGIN) {
4272 * Allocate arrays that will contain the graphs data
4273 * and the min/max values.
4275 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4278 if (action & F_MAIN) {
4280 for (i = 0; i < a->nr[curr]; i++) {
4282 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4283 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4286 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4289 out + i, outsize + i, svg_p->restart, svg_p->dt,
4290 spmin + i, spmax + i);
4294 if (action & F_END) {
4297 for (i = 0; i < a->item_list_sz; i++) {
4299 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4301 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4302 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4304 if (draw_activity_graphs(a->g_nr, g_type,
4305 title, g_title, item_name, group,
4306 spmin + i, spmax + i, out + i, outsize + i,
4307 svg_p, record_hdr, FALSE, a->id, xid)) {
4312 /* Free remaining structures */
4313 free_graphs(out, outsize, spmin, spmax);
4318 ***************************************************************************
4319 * Display temperature statistics in SVG.
4322 * @a Activity structure with statistics.
4323 * @curr Index in array for current sample statistics.
4324 * @action Action expected from current function.
4325 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4326 * flag indicating that a restart record has been previously
4327 * found (.@restart) and time used for the X axis origin
4329 * @itv Interval of time in 1/100th of a second (unused here).
4330 * @record_hdr Pointer on record header of current stats sample.
4331 ***************************************************************************
4333 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4334 unsigned long long itv, struct record_header *record_hdr)
4336 struct stats_pwr_temp *spc;
4337 int group[] = {1, 1};
4338 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4339 char *title[] = {"Devices temperature (1)",
4340 "Devices temperature (2)"};
4341 char *g_title[] = {"~degC",
4343 static double *spmin, *spmax;
4345 static int *outsize;
4346 char item_name[MAX_SENSORS_DEV_LEN + 8];
4350 if (action & F_BEGIN) {
4352 * Allocate arrays that will contain the graphs data
4353 * and the min/max values.
4355 out = allocate_graph_lines(2 * a->item_list_sz, &outsize, &spmin, &spmax);
4358 if (action & F_MAIN) {
4359 /* For each temperature sensor */
4360 for (i = 0; i < a->nr[curr]; i++) {
4362 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4364 /* Look for min/max values */
4365 if (spc->temp < *(spmin + 2 * i)) {
4366 *(spmin + 2 * i) = spc->temp;
4368 if (spc->temp > *(spmax + 2 * i)) {
4369 *(spmax + 2 * i) = spc->temp;
4371 tval = (spc->temp_max - spc->temp_min) ?
4372 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4374 if (tval < *(spmin + 2 * i + 1)) {
4375 *(spmin + 2 * i + 1) = tval;
4377 if (tval > *(spmax + 2 * i + 1)) {
4378 *(spmax + 2 * i + 1) = tval;
4382 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4384 out + 2 * i, outsize + 2 * i, svg_p->restart);
4386 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4388 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4392 if (action & F_END) {
4395 for (i = 0; i < a->item_list_sz; 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 if (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, a->id, xid)) {
4410 /* Free remaining structures */
4411 free_graphs(out, outsize, spmin, spmax);
4416 ***************************************************************************
4417 * Display voltage inputs statistics in SVG.
4420 * @a Activity structure with statistics.
4421 * @curr Index in array for current sample statistics.
4422 * @action Action expected from current function.
4423 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4424 * flag indicating that a restart record has been previously
4425 * found (.@restart) and time used for the X axis origin
4427 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4428 * @record_hdr Pointer on record header of current stats sample.
4429 ***************************************************************************
4431 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4432 unsigned long long itv, struct record_header *record_hdr)
4434 struct stats_pwr_in *spc;
4435 int group[] = {1, 1};
4436 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4437 char *title[] = {"Voltage inputs statistics (1)",
4438 "Voltage inputs statistics (2)"};
4439 char *g_title[] = {"inV",
4441 static double *spmin, *spmax;
4443 static int *outsize;
4444 char item_name[MAX_SENSORS_DEV_LEN + 8];
4448 if (action & F_BEGIN) {
4450 * Allocate arrays that will contain the graphs data
4451 * and the min/max values.
4453 out = allocate_graph_lines(2 * a->item_list_sz, &outsize, &spmin, &spmax);
4456 if (action & F_MAIN) {
4457 /* For each voltage input sensor */
4458 for (i = 0; i < a->nr[curr]; i++) {
4460 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4462 /* Look for min/max values */
4463 if (spc->in < *(spmin + 2 * i)) {
4464 *(spmin + 2 * i) = spc->in;
4466 if (spc->in > *(spmax + 2 * i)) {
4467 *(spmax + 2 * i) = spc->in;
4469 tval = (spc->in_max - spc->in_min) ?
4470 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4472 if (tval < *(spmin + 2 * i + 1)) {
4473 *(spmin + 2 * i + 1) = tval;
4475 if (tval > *(spmax + 2 * i + 1)) {
4476 *(spmax + 2 * i + 1) = tval;
4480 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4482 out + 2 * i, outsize + 2 * i, svg_p->restart);
4484 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4486 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4490 if (action & F_END) {
4493 for (i = 0; i < a->item_list_sz; i++) {
4495 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4497 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4498 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4500 if (draw_activity_graphs(a->g_nr, g_type,
4501 title, g_title, item_name, group,
4502 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4503 svg_p, record_hdr, FALSE, a->id, xid)) {
4508 /* Free remaining structures */
4509 free_graphs(out, outsize, spmin, spmax);
4514 ***************************************************************************
4515 * Display huge pages statistics in SVG.
4518 * @a Activity structure with statistics.
4519 * @curr Index in array for current sample statistics.
4520 * @action Action expected from current function.
4521 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4522 * flag indicating that a restart record has been previously
4523 * found (.@restart) and time used for the X axis origin
4525 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4526 * @record_hdr Pointer on record header of current stats sample.
4527 ***************************************************************************
4529 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4530 unsigned long long itv, struct record_header *record_hdr)
4533 *smc = (struct stats_huge *) a->buf[curr];
4534 int group[] = {2, 1};
4535 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4536 char *title[] = {"Huge pages utilization (1)",
4537 "Huge pages utilization (2)"};
4538 char *g_title[] = {"~kbhugfree", "~kbhugused",
4540 int g_fields[] = {0};
4541 unsigned int local_types_nr[] = {0, 1, 0};
4542 static double *spmin, *spmax;
4544 static int *outsize;
4547 if (action & F_BEGIN) {
4549 * Allocate arrays that will contain the graphs data
4550 * and the min/max values.
4552 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4555 if (action & F_MAIN) {
4556 /* Check for min/max values */
4557 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4558 itv, spmin, spmax, g_fields);
4560 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4561 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4563 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4564 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4566 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4567 if (tval < *(spmin + 2)) {
4568 *(spmin + 2) = tval;
4570 if (tval > *(spmax + 2)) {
4571 *(spmax + 2) = tval;
4575 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4576 (unsigned long long) smc->frhkb,
4577 out, outsize, svg_p->restart);
4579 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4580 (unsigned long long) smc->tlhkb - smc->frhkb,
4581 out + 1, outsize + 1, svg_p->restart);
4583 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4585 out + 2, outsize + 2, svg_p->dt);
4588 if (action & F_END) {
4589 draw_activity_graphs(a->g_nr, g_type,
4590 title, g_title, NULL, group,
4591 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4593 /* Free remaining structures */
4594 free_graphs(out, outsize, spmin, spmax);
4599 ***************************************************************************
4600 * Display filesystem statistics in SVG.
4603 * @a Activity structure with statistics.
4604 * @curr Index in array for current sample statistics.
4605 * @action Action expected from current function.
4606 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4607 * flag indicating that a restart record has been previously
4608 * found (.@restart) and time used for the X axis origin
4610 * @itv Interval of time in 1/100th of a second (unused here).
4611 * @record_hdr Pointer on record header of current stats sample.
4612 ***************************************************************************
4614 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4615 unsigned long long itv, struct record_header *record_hdr)
4617 struct stats_filesystem *sfc, *sfp;
4618 int group[] = {2, 2, 2, 1};
4619 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4620 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4621 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4622 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4623 char *g_title[] = {"~MBfsfree", "~MBfsused",
4624 "%ufsused", "%fsused",
4625 "Ifree/1000", "Iused/1000",
4627 static double *spmin, *spmax;
4629 static int *outsize;
4632 int i, k, pos, restart;
4634 if (action & F_BEGIN) {
4636 * Allocate arrays (#0..6) that will contain the graphs data
4637 * and the min/max values.
4638 * Also allocate two additional arrays (#7..8) for each filesystem:
4639 * out + 7 will contain the filesystem name,
4640 * out + 8 will contain the mount point.
4642 out = allocate_graph_lines(9 * a->item_list_sz, &outsize, &spmin, &spmax);
4645 if (action & F_MAIN) {
4646 /* For each filesystem structure */
4647 for (i = 0; i < a->nr[curr]; i++) {
4648 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4650 if (a->item_list != NULL) {
4651 /* A list of devices has been entered on the command line */
4652 if (!search_list_item(a->item_list,
4653 DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name))
4654 /* Device not found */
4658 /* Look for corresponding graph */
4659 for (k = 0; k < a->item_list_sz; k++) {
4660 item_name = *(out + k * 9 + 7);
4661 if (!strcmp(sfc->fs_name, item_name))
4666 if (k == a->item_list_sz) {
4667 /* Graph not found: Look for first free entry */
4668 for (k = 0; k < a->item_list_sz; k++) {
4669 item_name = *(out + k * 9 + 7);
4670 if (!strcmp(item_name, ""))
4673 if (k == a->item_list_sz) {
4674 /* No free graph entry: Ignore it (should never happen) */
4676 fprintf(stderr, "%s: Name=%s\n",
4677 __FUNCTION__, sfc->fs_name);
4685 item_name = *(out + pos + 7);
4686 if (!item_name[0]) {
4687 /* Save filesystem name and mount point (if not already done) */
4688 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4689 item_name[CHUNKSIZE - 1] = '\0';
4690 item_name = *(out + pos + 8);
4691 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4692 item_name[CHUNKSIZE - 1] = '\0';
4696 for (k = 0; k < a->nr[!curr]; k++) {
4697 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4698 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4699 /* Filesystem found in previous sample */
4700 restart = svg_p->restart;
4704 /* Check for min/max values */
4706 /* Compute fsfree min/max values */
4707 tval = (double) sfc->f_bfree;
4708 if (tval > *(spmax + pos)) {
4709 *(spmax + pos) = tval;
4711 if (tval < *(spmin + pos)) {
4712 *(spmin + pos) = tval;
4714 /* Compute fsused min/max values */
4715 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4716 if (tval > *(spmax + pos + 1)) {
4717 *(spmax + pos + 1) = tval;
4719 if (tval < *(spmin + pos + 1)) {
4720 *(spmin + pos + 1) = tval;
4722 /* Compute %ufsused min/max values */
4723 tval = sfc->f_blocks ?
4724 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4725 if (tval > *(spmax + pos + 2)) {
4726 *(spmax + pos + 2) = tval;
4728 if (tval < *(spmin + pos + 2)) {
4729 *(spmin + pos + 2) = tval;
4731 /* Compute %fsused min/max values */
4732 tval = sfc->f_blocks ?
4733 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4734 if (tval > *(spmax + pos + 3)) {
4735 *(spmax + pos + 3) = tval;
4737 if (tval < *(spmin + pos + 3)) {
4738 *(spmin + pos + 3) = tval;
4740 /* Compute Ifree min/max values */
4741 tval = (double) sfc->f_ffree;
4742 if (tval > *(spmax + pos + 4)) {
4743 *(spmax + pos + 4) = tval;
4745 if (tval < *(spmin + pos + 4)) {
4746 *(spmin + pos + 4) = tval;
4748 /* Compute Iused min/max values */
4749 tval = (double) (sfc->f_files - sfc->f_ffree);
4750 if (tval > *(spmax + pos + 5)) {
4751 *(spmax + pos + 5) = tval;
4753 if (tval < *(spmin + pos + 5)) {
4754 *(spmin + pos + 5) = tval;
4756 /* Compute %Iused min/max values */
4757 tval = sfc->f_files ?
4758 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4759 if (tval > *(spmax + pos + 6)) {
4760 *(spmax + pos + 6) = tval;
4762 if (tval < *(spmin + pos + 6)) {
4763 *(spmin + pos + 6) = tval;
4767 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4768 (double) sfc->f_bfree / 1024 / 1024,
4769 out + pos, outsize + pos, restart);
4771 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4772 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4773 out + pos + 1, outsize + pos + 1, restart);
4775 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4778 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4779 out + pos + 2, outsize + pos + 2, svg_p->dt);
4781 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4784 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4785 out + pos + 3, outsize + pos + 3, svg_p->dt);
4787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4788 ((double) sfc->f_ffree) / 1000,
4789 out + pos + 4, outsize + pos + 4, restart);
4791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4792 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4793 out + pos + 5, outsize + pos + 5, restart);
4795 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4798 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4799 out + pos + 6, outsize + pos + 6, svg_p->dt);
4803 if (action & F_END) {
4806 for (i = 0; i < a->item_list_sz; i++) {
4808 /* Check if there is something to display */
4813 /* Conversion B -> MB and inodes/1000 */
4814 for (k = 0; k < 2; k++) {
4815 *(spmin + pos + k) /= (1024 * 1024);
4816 *(spmax + pos + k) /= (1024 * 1024);
4817 *(spmin + pos + 4 + k) /= 1000;
4818 *(spmax + pos + 4 + k) /= 1000;
4821 if (DISPLAY_MOUNT(a->opt_flags)) {
4822 item_name = *(out + pos + 8);
4825 item_name = *(out + pos + 7);
4828 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4829 spmin + pos, spmax + pos, out + pos, outsize + pos,
4830 svg_p, record_hdr, FALSE, a->id, xid)) {
4835 /* Free remaining structures */
4836 free_graphs(out, outsize, spmin, spmax);
4841 ***************************************************************************
4842 * Display Fibre Channel HBA statistics in SVG.
4845 * @a Activity structure with statistics.
4846 * @curr Index in array for current sample statistics.
4847 * @action Action expected from current function.
4848 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4849 * flag indicating that a restart record has been previously
4850 * found (.@restart) and time used for the X axis origin
4852 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4853 * @record_hdr Pointer on record header of current stats sample.
4854 ***************************************************************************
4856 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4857 unsigned long long itv, struct record_header *record_hdr)
4859 struct stats_fchost *sfcc, *sfcp;
4860 int group[] = {2, 2};
4861 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4862 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4863 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4864 "fch_rxw/s", "fch_txw/s"};
4865 int g_fields[] = {0, 1, 2, 3};
4866 static double *spmin, *spmax;
4868 static int *outsize;
4870 int i, j, j0, k, found, pos, restart, *unregistered;
4872 if (action & F_BEGIN) {
4874 * Allocate arrays (#0..3) that will contain the graphs data
4875 * and the min/max values.
4876 * Also allocate one additional array (#4) that will contain
4877 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4878 * has either still not been registered, or has been unregistered
4881 out = allocate_graph_lines(5 * a->item_list_sz, &outsize, &spmin, &spmax);
4884 if (action & F_MAIN) {
4885 restart = svg_p->restart;
4887 * Mark previously registered interfaces as now
4888 * possibly unregistered for all graphs.
4890 for (k = 0; k < a->item_list_sz; k++) {
4891 unregistered = outsize + k * 5 + 4;
4892 if (*unregistered == FALSE) {
4893 *unregistered = MAYBE;
4897 /* For each FC HBA */
4898 for (i = 0; i < a->nr[curr]; i++) {
4902 if (a->nr[!curr] > 0) {
4903 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4905 /* Look for corresponding graph */
4906 for (k = 0; k < a->item_list_sz; k++) {
4907 item_name = *(out + k * 5 + 4);
4908 if (!strcmp(sfcc->fchost_name, item_name))
4912 if (k == a->item_list_sz) {
4913 /* Graph not found: Look for first free entry */
4914 for (k = 0; k < a->item_list_sz; k++) {
4915 item_name = *(out + k * 5 + 4);
4916 if (!strcmp(item_name, ""))
4919 if (k == a->item_list_sz) {
4920 /* No free graph entry: Ignore it (should never happen) */
4922 fprintf(stderr, "%s: Name=%s\n",
4923 __FUNCTION__, sfcc->fchost_name);
4930 unregistered = outsize + pos + 4;
4932 /* Look for corresponding structure in previous iteration */
4935 if (j >= a->nr[!curr]) {
4936 j = a->nr[!curr] - 1;
4942 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4943 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4947 if (++j >= a->nr[!curr]) {
4958 * If current interface was marked as previously unregistered,
4959 * then set restart variable to TRUE so that the graph will be
4960 * discontinuous, and mark it as now registered.
4962 if (*unregistered == TRUE) {
4965 *unregistered = FALSE;
4967 item_name = *(out + pos + 4);
4968 if (!item_name[0]) {
4969 /* Save FC HBA name */
4970 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4971 item_name[CHUNKSIZE - 1] = '\0';
4974 /* Look for min/max values */
4975 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4976 itv, spmin + pos, spmax + pos, g_fields);
4979 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4980 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4981 out + pos, outsize + pos, restart);
4983 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4984 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4985 out + pos + 1, outsize + pos + 1, restart);
4987 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4988 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4989 out + pos + 2, outsize + pos + 2, restart);
4991 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4992 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4993 out + pos + 3, outsize + pos + 3, restart);
4996 /* Mark interfaces not seen here as now unregistered */
4997 for (k = 0; k < a->item_list_sz; k++) {
4998 unregistered = outsize + k * 5 + 4;
4999 if (*unregistered != FALSE) {
5000 *unregistered = TRUE;
5005 if (action & F_END) {
5006 for (i = 0; i < a->item_list_sz; i++) {
5008 /* Check if there is something to display */
5013 item_name = *(out + pos + 4);
5014 draw_activity_graphs(a->g_nr, g_type,
5015 title, g_title, item_name, group,
5016 spmin + pos, spmax + pos, out + pos, outsize + pos,
5017 svg_p, record_hdr, FALSE, a->id, i);
5020 /* Free remaining structures */
5021 free_graphs(out, outsize, spmin, spmax);
5026 ***************************************************************************
5027 * Display softnet statistics in SVG.
5030 * @a Activity structure with statistics.
5031 * @curr Index in array for current sample statistics.
5032 * @action Action expected from current function.
5033 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5034 * flag indicating that a restart record has been previously
5035 * found (.@restart) and time used for the X axis origin
5037 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5038 * @record_hdr Pointer on record header of current stats sample.
5039 ***************************************************************************
5041 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5042 unsigned long long itv, struct record_header *record_hdr)
5044 struct stats_softnet *ssnc, *ssnp, ssnczero;
5045 int group[] = {2, 3};
5046 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5047 char *title[] = {"Software-based network processing statistics (1)",
5048 "Software-based network processing statistics (2)"};
5049 char *g_title[] = {"total/s", "dropd/s",
5050 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5051 int g_fields[] = {0, 1, 2, 3, 4};
5052 static double *spmin, *spmax;
5054 static int *outsize;
5056 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5057 int i, pos, restart;
5059 if (action & F_BEGIN) {
5061 * Allocate arrays that will contain the graphs data
5062 * and the min/max values.
5064 out = allocate_graph_lines(5 * a->item_list_sz, &outsize, &spmin, &spmax);
5067 if (action & F_MAIN) {
5068 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5070 /* @nr[curr] cannot normally be greater than @nr_ini */
5071 if (a->nr[curr] > a->nr_ini) {
5072 a->nr_ini = a->nr[curr];
5075 /* Compute statistics for CPU "all" */
5076 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5079 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5080 restart = svg_p->restart;
5082 /* Should current CPU (including CPU "all") be displayed? */
5083 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5087 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5088 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5090 /* Is current CPU marked offline? */
5091 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5093 * Yes and it doesn't follow a RESTART record.
5094 * To add a discontinuity in graph, we simulate
5098 if (svg_p->restart) {
5100 * CPU is offline and it follows a real
5101 * RESTART record. Ignore its current value
5102 * (no previous sample).
5109 /* Check for min/max values */
5110 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5111 itv, spmin + pos, spmax + pos, g_fields);
5114 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5115 S_VALUE(ssnp->processed, ssnc->processed, itv),
5116 out + pos, outsize + pos, restart);
5118 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5119 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5120 out + pos + 1, outsize + pos + 1, restart);
5122 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5123 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5124 out + pos + 2, outsize + pos + 2, restart);
5126 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5127 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5128 out + pos + 3, outsize + pos + 3, restart);
5130 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5131 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5132 out + pos + 4, outsize + pos + 4, restart);
5136 if (action & F_END) {
5137 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
5139 /* Should current CPU (including CPU "all") be displayed? */
5140 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5147 /* This is CPU "all" */
5148 strcpy(item_name, "all");
5151 sprintf(item_name, "%d", i - 1);
5154 draw_activity_graphs(a->g_nr, g_type,
5155 title, g_title, item_name, group,
5156 spmin + pos, spmax + pos, out + pos, outsize + pos,
5157 svg_p, record_hdr, FALSE, a->id, i);
5160 /* Free remaining structures */
5161 free_graphs(out, outsize, spmin, spmax);