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)
392 unsigned long long t = 0;
394 /* Prepare additional graph definition data */
395 if ((value == 0.0) || (dt == 0))
396 /* Don't draw a flat rectangle! */
402 snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
403 t, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
406 save_svg_data(data, out, outsize);
411 ***************************************************************************
412 * Update CPU graph and min/max values for each metric.
415 * @timetag Timestamp in seconds since the epoch for current sample
416 * stats. Will be used as X coordinate.
417 * @offset Offset for Y coordinate.
418 * @value Value of current CPU metric. Will be used as rectangle
420 * @out Pointer on array of chars for current graph definition.
421 * @outsize Size of array of chars for current graph definition.
422 * @dt Interval of time in seconds between current and previous
424 * @spmin Min value already found for this CPU metric.
425 * @spmax Max value already found for this CPU metric.
428 * @offset New offset value, to use to draw next rectangle
429 * @out Pointer on array of chars for current graph definition that
430 * has been updated with the addition of current sample data.
431 * @outsize Array that containing the (possibly new) sizes of each
432 * element in array of chars.
433 ***************************************************************************
435 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
436 int *outsize, unsigned long long dt, double *spmin, double *spmax)
438 /* Save min and max values */
439 if (value < *spmin) {
442 if (value > *spmax) {
445 /* Prepare additional graph definition data */
446 brappend(timetag, *offset, value, out, outsize, dt);
452 ***************************************************************************
453 * Update rectangular graph and min/max values.
456 * @timetag Timestamp in seconds since the epoch for current sample
457 * stats. Will be used as X coordinate.
458 * @p_value Metric value for previous sample
459 * @value Metric value for current sample.
460 * @out Pointer on array of chars for current graph definition.
461 * @outsize Size of array of chars for current graph definition.
462 * @restart Set to TRUE if a RESTART record has been read since the last
464 * @dt Interval of time in seconds between current and previous
466 * @spmin Min value already found for this metric.
467 * @spmax Max value already found for this metric.
470 * @out Pointer on array of chars for current graph definition that
471 * has been updated with the addition of current sample data.
472 * @outsize Array that containing the (possibly new) sizes of each
473 * element in array of chars.
474 * @spmin Min value for this metric.
475 * @spmax Max value for this metric.
476 ***************************************************************************
478 void recappend(unsigned long long timetag, double p_value, double value, char **out,
479 int *outsize, int restart, unsigned long long dt,
480 double *spmin, double *spmax)
482 char data[512], data1[128], data2[128];
483 unsigned long long t = 0;
485 /* Save min and max values */
486 if (value < *spmin) {
489 if (value > *spmax) {
495 /* Prepare additional graph definition data */
497 snprintf(data1, sizeof(data1), " M%llu,%.2f", t, p_value);
498 data1[sizeof(data1) - 1] = '\0';
500 if (p_value != value) {
501 snprintf(data2, sizeof(data2), " L%llu,%.2f", timetag, value);
502 data2[sizeof(data2) - 1] = '\0';
504 snprintf(data, sizeof(data), "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
505 p_value != value ? data2 : "");
506 data[sizeof(data) - 1] = '\0';
508 save_svg_data(data, out, outsize);
512 ***************************************************************************
513 * Calculate 10 raised to the power of n.
516 * @n Power number to use.
519 * 10 raised to the power of n.
520 ***************************************************************************
522 unsigned int pwr10(int n)
527 for (i = 0; i < n; i++) {
535 ***************************************************************************
536 * Autoscale graphs of a given view.
539 * @asf_nr (Maximum) number of autoscale factors.
540 * @group Number of graphs in current view.
541 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
542 * @pos Position in array for the first graph in view.
543 * @gmax Global max value for all graphs in view.
544 * @spmax Array containing max values for graphs.
547 * @asfactor Autoscale factors (one for each graph).
548 ***************************************************************************
550 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
551 double gmax, double *spmax)
556 for (j = 0; j < asf_nr; j++) {
557 /* Init autoscale factors */
561 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
563 for (j = 0; (j < group) && (j < asf_nr); j++) {
564 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
567 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
568 if (strlen(val) > 0) {
569 asfactor[j] = pwr10(strlen(val) - 1);
576 ***************************************************************************
577 * Display background grid (horizontal lines) and corresponding graduations.
580 * @ypos Gap between two horizontal lines.
581 * @yfactor Scaling factor on Y axis.
582 * @lmax Max value for current view.
583 * @dp Number of decimal places for graduations.
584 ***************************************************************************
586 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
592 /* Display horizontal lines (except on X axis) */
594 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
595 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
596 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
600 * Display graduations.
601 * Use same rounded value for graduation numbers as for grid lines
602 * to make sure they are properly aligned.
604 sprintf(stmp, "%.2f", ypos * j);
605 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
606 "text-anchor: end\">%.*f.</text>\n",
607 (long) (atof(stmp) * yfactor), dp, ypos * j);
610 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
614 ***************************************************************************
615 * Display background grid (vertical lines) and corresponding graduations.
618 * @xpos Gap between two vertical lines.
619 * @xfactor Scaling factor on X axis.
620 * @v_gridnr Default number of vertical lines to display. The actual
621 * number may vary between this value and 2 times this value.
622 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
623 ***************************************************************************
625 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
627 struct record_header stamp;
629 char cur_time[TIMESTAMP_LEN];
632 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
635 * What really matters to know when we should stop drawing vertical lines
636 * is the time end. v_gridnr is only informative and used to calculate
637 * the gap between two lines.
639 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
641 /* Display vertical lines */
642 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
643 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
644 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
645 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
646 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
648 * Display graduations.
649 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
650 * In this case, we should rather display the exact time instead of only the hour.
652 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
653 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
654 "text-anchor: start\">%2d:00</text>\n",
655 (long) (xpos * j * xfactor) - 15, rectime.tm_hour);
658 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
659 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
660 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
662 stamp.ust_time += xpos;
665 if (!PRINT_LOCAL_TIME(flags)) {
666 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
667 "text-anchor: end\">UTC</text>\n");
672 ***************************************************************************
673 * Calculate the value on the Y axis between two horizontal lines that will
674 * make the graph background grid.
677 * @lmax Max value reached for this graph.
680 * @dp Number of decimal places for Y graduations.
683 * Value between two horizontal lines.
684 ***************************************************************************
686 double ygrid(double lmax, int *dp)
697 n = (long) (lmax / SVG_H_GRIDNR);
700 return (lmax / SVG_H_GRIDNR);
702 snprintf(val, 32, "%ld", n);
709 return ((double) (((long) (n / e)) * e));
713 ***************************************************************************
714 * Calculate the value on the X axis between two vertical lines that will
715 * make the graph background grid.
718 * @timestart First data timestamp (X coordinate of the first data point).
719 * @timeend Last data timestamp (X coordinate of the last data point).
720 * @v_gridnr Number of vertical lines to display. Its value is normally
721 * SVG_V_GRIDNR, except when option "oneday" is used, in which
722 * case it is set to 12.
725 * Value between two vertical lines.
726 ***************************************************************************
728 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
730 if ((timeend - timestart) <= v_gridnr)
733 return ((timeend - timestart) / v_gridnr);
737 ***************************************************************************
738 * Free global graphs structures.
741 * @out Pointer on array of chars for each graph definition.
742 * @outsize Size of array of chars for each graph definition.
743 * @spmin Array containing min values for graphs.
744 * @spmax Array containing max values for graphs.
745 ***************************************************************************
747 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
764 ***************************************************************************
765 * Skip current view where all graphs have only zero values. This function
766 * is called when option "skipempty" has been used, or when "No data" have
767 * been found for current view.
770 * @out Pointer on array of chars for each graph definition.
771 * @pos Position of current view in the array of graphs definitions.
772 * @group Number of graphs in current view.
775 * @pos Position of next view in the array of graphs definitions.
776 ***************************************************************************
778 void skip_current_view(char **out, int *pos, int group)
783 for (j = 0; j < group; j++) {
784 out_p = *(out + *pos + j);
786 /* Even if not displayed, current graph data have to be freed */
794 ***************************************************************************
795 * Display all graphs for current activity.
798 * @g_nr Number of views to display.
799 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
800 * @title Titles for each set of graphs.
801 * @g_title Titles for each graph.
802 * @item_name Item (network interface, etc.) name.
803 * @group Indicate how graphs are grouped together to make sets.
804 * @spmin Array containing min values for graphs.
805 * @spmax Array containing max values for graphs.
806 * @out Pointer on array of chars for each graph definition.
807 * @outsize Size of array of chars for each graph definition.
808 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
809 * time for the first sample of stats (.@ust_time_first), and
810 * times used as start and end values on the X axis
811 * (.@ust_time_ref and .@ust_time_end).
812 * @record_hdr Pointer on record header of current stats sample.
813 * @skip_void Set to <> 0 if graphs with no data should be skipped.
814 * This is typicallly used to not display CPU offline on the
816 * @id Current activity id.
817 * @xid Current activity extra id number.
820 * TRUE if at least one graph has been displayed.
821 ***************************************************************************
823 int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
824 int group[], double *spmin, double *spmax, char **out, int *outsize,
825 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
826 unsigned int id, unsigned int xid)
829 int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE;
830 int v_gridnr, xv, yv;
831 unsigned int asfactor[16];
833 double lmax, xfactor, yfactor, ypos, gmin, gmax;
834 char val[32], cur_date[TIMESTAMP_LEN];
837 /* For each view which is part of current activity */
838 for (i = 0; i < g_nr; i++) {
840 /* Get global min and max value for current view */
841 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
843 /* Don't display empty views if requested */
844 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
845 skip_current_view(out, &pos, group[i]);
848 /* Skip void graphs */
849 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
853 /* Translate to proper position for current activity */
854 printf("<g id=\"g%d-%d\" transform=\"translate(0,%d)\">\n",
857 SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
858 SVG_T_YSIZE * svg_p->graph_no);
862 /* Increment number of views actually displayed */
865 /* Compute top left position of view */
866 if (PACK_VIEWS(flags)) {
867 xv = (views_nr - 1) * SVG_T_XSIZE;
872 yv = (views_nr - 1) * SVG_T_YSIZE;
875 /* Graph background */
876 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
877 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
880 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
881 xv, 20 + yv, title[i]);
883 printf(" [%s]", item_name);
886 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
887 "(Min, Max values)</tspan>\n</text>\n",
888 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
891 * At least two samples are needed.
892 * And a min and max value should have been found.
894 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
895 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
897 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
898 xv, yv + SVG_M_YSIZE);
899 skip_current_view(out, &pos, group[i]);
904 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
905 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
906 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
907 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
909 /* Autoscaling graphs if needed */
910 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
913 for (j = 0; j < group[i]; j++) {
914 /* Set dp to TRUE (1) if current metric is based on integer values */
915 dp = (g_title[pos + j][0] == '~');
916 snprintf(val, 32, "x%u ", asfactor[j]);
917 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
918 "%s %s(%.*f, %.*f)</text>\n",
919 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
920 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
921 asfactor[j] == 1 ? "" : val,
922 !dp * 2, *(spmin + pos + j) * asfactor[j],
923 !dp * 2, *(spmax + pos + j) * asfactor[j]);
926 if (DISPLAY_INFO(flags)) {
927 /* Display additional info (hostname, date) */
928 printf("<text x=\"%d\" y=\"%d\" "
929 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
931 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
932 svg_p->file_hdr->sa_nodename);
934 /* Get report date */
935 set_report_date(localtime_r((const time_t *) &(svg_p->file_hdr->sa_ust_time), &rectime),
936 cur_date, sizeof(cur_date));
937 printf("<tspan x=\"%d\" y=\"%d\" "
938 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
939 "%s</tspan>\n</text>\n",
940 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
944 /* Translate to proper position for current graph within current activity */
945 printf("<g transform=\"translate(%d,%d)\">\n",
946 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
949 if (g_type[i] == SVG_LINE_GRAPH) {
950 /* For line graphs */
952 /* If all values are zero then set current max value to 1 */
958 /* Max value cannot be too small, else Y graduations will be meaningless */
959 if (lmax < SVG_H_GRIDNR * 0.01) {
960 lmax = SVG_H_GRIDNR * 0.01;
962 ypos = ygrid(lmax, &dp);
965 /* For bar graphs (used for %values) */
966 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
967 dp = 0; /* No decimals */
969 /* Max should be always 100% except for percentage values greater than 100% */
977 yfactor = (double) -SVG_G_YSIZE / lmax;
979 /* Display horizontal lines and graduations */
980 display_hgrid(ypos, yfactor, lmax, dp);
982 /* Set number of vertical lines to 12 when option "oneday" is used */
983 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
985 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
986 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
988 /* Display vertical lines and graduations */
989 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
991 /* Draw current graphs set */
992 for (j = 0; j < group[i]; j++) {
993 out_p = *(out + pos + j);
994 if (g_type[i] == SVG_LINE_GRAPH) {
996 printf("<path d=\"%s\" "
997 "style=\"vector-effect: non-scaling-stroke; "
998 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
999 "transform=\"scale(%f,%f)\"/>\n",
1001 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
1003 yfactor * asfactor[j]);
1005 else if (*out_p) { /* Ignore flat bars */
1007 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1008 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1009 printf("%s\n", out_p);
1020 /* For next row of views */
1021 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1028 ***************************************************************************
1029 * Display CPU statistics in SVG.
1032 * @a Activity structure with statistics.
1033 * @curr Index in array for current sample statistics.
1034 * @action Action expected from current function.
1035 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1036 * flag indicating that a restart record has been previously
1037 * found (.@restart), and time used for the X axis origin
1039 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1041 * @record_hdr Pointer on record header of current stats sample.
1042 ***************************************************************************
1044 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1045 unsigned long long itv, struct record_header *record_hdr)
1047 struct stats_cpu *scc, *scp;
1048 unsigned long long deltot_jiffies = 1;
1049 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1052 int g_type[] = {SVG_BAR_GRAPH};
1053 char *title[] = {"CPU utilization"};
1054 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1055 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1056 static double *spmin, *spmax;
1058 static int *outsize;
1063 if (action & F_BEGIN) {
1065 * Allocate arrays that will contain the graphs data
1066 * and the min/max values.
1068 out = allocate_graph_lines(10 * a->item_list_sz, &outsize, &spmin, &spmax);
1071 if (action & F_MAIN) {
1073 /* @nr[curr] cannot normally be greater than @nr_ini */
1074 if (a->nr[curr] > a->nr_ini) {
1075 a->nr_ini = a->nr[curr];
1079 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1080 * and look for offline CPU.
1082 if (a->nr_ini > 1) {
1083 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1084 flags, offline_cpu_bitmap);
1088 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1090 /* Should current CPU (including CPU "all") be displayed? */
1091 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1092 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1093 /* Don't display CPU */
1096 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1097 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1103 /* This is CPU "all" */
1104 if (a->nr_ini == 1) {
1106 * This is a UP machine. In this case
1107 * interval has still not been calculated.
1109 deltot_jiffies = get_per_cpu_interval(scc, scp);
1111 if (!deltot_jiffies) {
1112 /* CPU "all" cannot be tickless */
1118 * Recalculate interval for current proc.
1119 * If result is 0 then current CPU is a tickless one.
1121 deltot_jiffies = get_per_cpu_interval(scc, scp);
1123 if (!deltot_jiffies) { /* Current CPU is tickless */
1125 val = 100.0; /* Tickless CPU: %idle = 100% */
1127 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1130 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1134 /* Check min/max values for %user, etc. */
1135 for (k = 0; k < j; k++) {
1136 if (0.0 < *(spmin + pos + k)) {
1137 *(spmin + pos + k) = 0.0;
1139 if (0.0 > *(spmax + pos + k)) {
1140 *(spmax + pos + k) = 0.0;
1145 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1147 out + pos + j, outsize + pos + j, svg_p->dt,
1148 spmin + pos + j, spmax + pos + j);
1153 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1155 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1156 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1157 out + pos, outsize + pos, svg_p->dt,
1158 spmin + pos, spmax + pos);
1162 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1164 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1166 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1167 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1168 out + pos, outsize + pos, svg_p->dt,
1169 spmin + pos, spmax + pos);
1172 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1174 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1175 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1176 out + pos + 1, outsize + pos + 1, svg_p->dt,
1177 spmin + pos + 1, spmax + pos + 1);
1181 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1183 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1185 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1186 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1187 out + pos + 1, outsize + pos + 1, svg_p->dt,
1188 spmin + pos + 1, spmax + pos + 1);
1191 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1193 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1195 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1196 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1198 out + pos + 2, outsize + pos + 2, svg_p->dt,
1199 spmin + pos + 2, spmax + pos + 2);
1203 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1204 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1205 out + pos + 2, outsize + pos + 2, svg_p->dt,
1206 spmin + pos + 2, spmax + pos + 2);
1210 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1211 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1212 out + pos + 3, outsize + pos + 3, svg_p->dt,
1213 spmin + pos + 3, spmax + pos + 3);
1215 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1216 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1217 out + pos + 4, outsize + pos + 4, svg_p->dt,
1218 spmin + pos + 4, spmax + pos + 4);
1220 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1222 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1223 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1224 out + pos + 5, outsize + pos + 5, svg_p->dt,
1225 spmin + pos + 5, spmax + pos + 5);
1227 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1228 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1229 out + pos + 6, outsize + pos + 6, svg_p->dt,
1230 spmin + pos + 6, spmax + pos + 6);
1232 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1233 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1234 out + pos + 7, outsize + pos + 7, svg_p->dt,
1235 spmin + pos + 7, spmax + pos + 7);
1237 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1238 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1239 out + pos + 8, outsize + pos + 8, svg_p->dt,
1240 spmin + pos + 8, spmax + pos + 8);
1249 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1251 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1252 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1253 out + pos + j, outsize + pos + j, svg_p->dt,
1254 spmin + pos + j, spmax + pos + j);
1258 if (action & F_END) {
1259 int xid = 0, displayed;
1261 if (DISPLAY_IDLE(flags)) {
1262 /* Include additional %idle field */
1267 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
1269 /* Should current CPU (including CPU "all") be displayed? */
1270 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1276 /* This is CPU "all" */
1277 strcpy(item_name, "all");
1280 sprintf(item_name, "%d", i - 1);
1283 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1284 displayed = draw_activity_graphs(a->g_nr, g_type,
1285 title, g_title1, item_name, group1,
1286 spmin + pos, spmax + pos, out + pos, outsize + pos,
1287 svg_p, record_hdr, i, a->id, xid);
1290 displayed = draw_activity_graphs(a->g_nr, g_type,
1291 title, g_title2, item_name, group2,
1292 spmin + pos, spmax + pos, out + pos, outsize + pos,
1293 svg_p, record_hdr, i, a->id, xid);
1300 /* Free remaining structures */
1301 free_graphs(out, outsize, spmin, spmax);
1306 ***************************************************************************
1307 * Display task creation and context switch statistics in SVG.
1310 * @a Activity structure with statistics.
1311 * @curr Index in array for current sample statistics.
1312 * @action Action expected from current function.
1313 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1314 * flag indicating that a restart record has been previously
1315 * found (.@restart) and time used for the X axis origin
1317 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1318 * @record_hdr Pointer on record header of current stats sample.
1319 ***************************************************************************
1321 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1322 unsigned long long itv, struct record_header *record_hdr)
1325 *spc = (struct stats_pcsw *) a->buf[curr],
1326 *spp = (struct stats_pcsw *) a->buf[!curr];
1327 int group[] = {1, 1};
1328 int g_fields[] = {1, 0};
1329 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1330 char *title[] = {"Task creation", "Switching activity"};
1331 char *g_title[] = {"proc/s",
1333 static double *spmin, *spmax;
1335 static int *outsize;
1337 if (action & F_BEGIN) {
1339 * Allocate arrays that will contain the graphs data
1340 * and the min/max values.
1342 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1345 if (action & F_MAIN) {
1346 /* Check for min/max values */
1347 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1348 itv, spmin, spmax, g_fields);
1350 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1351 S_VALUE(spp->processes, spc->processes, itv),
1352 out, outsize, svg_p->restart);
1354 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1355 S_VALUE(spp->context_switch, spc->context_switch, itv),
1356 out + 1, outsize + 1, svg_p->restart);
1359 if (action & F_END) {
1360 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1361 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1363 /* Free remaining structures */
1364 free_graphs(out, outsize, spmin, spmax);
1369 ***************************************************************************
1370 * Display swap statistics in SVG.
1373 * @a Activity structure with statistics.
1374 * @curr Index in array for current sample statistics.
1375 * @action Action expected from current function.
1376 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1377 * flag indicating that a restart record has been previously
1378 * found (.@restart) and time used for the X axis origin
1380 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1381 * @record_hdr Pointer on record header of current stats sample.
1382 ***************************************************************************
1384 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1385 unsigned long long itv, struct record_header *record_hdr)
1388 *ssc = (struct stats_swap *) a->buf[curr],
1389 *ssp = (struct stats_swap *) a->buf[!curr];
1391 int g_type[] = {SVG_LINE_GRAPH};
1392 char *title[] = {"Swap activity"};
1393 char *g_title[] = {"pswpin/s", "pswpout/s" };
1394 int g_fields[] = {0, 1};
1395 static double *spmin, *spmax;
1397 static int *outsize;
1399 if (action & F_BEGIN) {
1401 * Allocate arrays that will contain the graphs data
1402 * and the min/max values.
1404 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1407 if (action & F_MAIN) {
1408 /* Check for min/max values */
1409 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1410 itv, spmin, spmax, g_fields);
1412 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1413 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1414 out, outsize, svg_p->restart);
1416 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1417 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1418 out + 1, outsize + 1, svg_p->restart);
1421 if (action & F_END) {
1422 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1423 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1425 /* Free remaining structures */
1426 free_graphs(out, outsize, spmin, spmax);
1431 ***************************************************************************
1432 * Display paging statistics in SVG.
1435 * @a Activity structure with statistics.
1436 * @curr Index in array for current sample statistics.
1437 * @action Action expected from current function.
1438 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1439 * flag indicating that a restart record has been previously
1440 * found (.@restart) and time used for the X axis origin
1442 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1443 * @record_hdr Pointer on record header of current stats sample.
1444 ***************************************************************************
1446 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1447 unsigned long long itv, struct record_header *record_hdr)
1450 *spc = (struct stats_paging *) a->buf[curr],
1451 *spp = (struct stats_paging *) a->buf[!curr];
1452 int group[] = {2, 2, 4};
1453 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1454 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1455 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1456 "fault/s", "majflt/s",
1457 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1458 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1459 static double *spmin, *spmax;
1461 static int *outsize;
1463 if (action & F_BEGIN) {
1465 * Allocate arrays that will contain the graphs data
1466 * and the min/max values.
1468 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1471 if (action & F_MAIN) {
1472 /* Check for min/max values */
1473 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1474 itv, spmin, spmax, g_fields);
1476 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1477 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1478 out, outsize, svg_p->restart);
1480 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1481 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1482 out + 1, outsize + 1, svg_p->restart);
1484 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1485 S_VALUE(spp->pgfault, spc->pgfault, itv),
1486 out + 2, outsize + 2, svg_p->restart);
1488 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1489 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1490 out + 3, outsize + 3, svg_p->restart);
1492 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1493 S_VALUE(spp->pgfree, spc->pgfree, itv),
1494 out + 4, outsize + 4, svg_p->restart);
1496 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1497 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1498 out + 5, outsize + 5, svg_p->restart);
1500 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1501 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1502 out + 6, outsize + 6, svg_p->restart);
1504 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1505 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1506 out + 7, outsize + 7, svg_p->restart);
1509 if (action & F_END) {
1510 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1511 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1513 /* Free remaining structures */
1514 free_graphs(out, outsize, spmin, spmax);
1519 ***************************************************************************
1520 * Display I/O and transfer rate statistics in SVG.
1523 * @a Activity structure with statistics.
1524 * @curr Index in array for current sample statistics.
1525 * @action Action expected from current function.
1526 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1527 * flag indicating that a restart record has been previously
1528 * found (.@restart) and time used for the X axis origin
1530 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1531 * @record_hdr Pointer on record header of current stats sample.
1532 ***************************************************************************
1534 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1535 unsigned long long itv, struct record_header *record_hdr)
1538 *sic = (struct stats_io *) a->buf[curr],
1539 *sip = (struct stats_io *) a->buf[!curr];
1540 int group[] = {3, 2};
1541 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1542 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1543 char *g_title[] = {"tps", "rtps", "wtps",
1544 "bread/s", "bwrtn/s"};
1545 int g_fields[] = {0, 1, 2, 3, 4};
1546 static double *spmin, *spmax;
1548 static int *outsize;
1550 if (action & F_BEGIN) {
1552 * Allocate arrays that will contain the graphs data
1553 * and the min/max values.
1555 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1558 if (action & F_MAIN) {
1559 /* Check for min/max values */
1560 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1561 itv, spmin, spmax, g_fields);
1564 * If we get negative values, this is probably because
1565 * one or more devices/filesystems have been unmounted.
1566 * We display 0.0 in this case though we should rather tell
1567 * the user that the value cannot be calculated here.
1570 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1571 sic->dk_drive < sip->dk_drive ? 0.0 :
1572 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1573 out, outsize, svg_p->restart);
1575 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1576 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1577 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1578 out + 1, outsize + 1, svg_p->restart);
1580 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1581 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1582 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1583 out + 2, outsize + 2, svg_p->restart);
1585 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1586 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1587 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1588 out + 3, outsize + 3, svg_p->restart);
1590 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1591 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1592 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1593 out + 4, outsize + 4, svg_p->restart);
1596 if (action & F_END) {
1597 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1598 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1600 /* Free remaining structures */
1601 free_graphs(out, outsize, spmin, spmax);
1606 ***************************************************************************
1607 * Display memory statistics in SVG.
1610 * @a Activity structure with statistics.
1611 * @curr Index in array for current sample statistics.
1612 * @action Action expected from current function.
1613 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1614 * flag indicating that a restart record has been previously
1615 * found (.@restart) and time used for the X axis origin
1617 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1618 * @record_hdr Pointer on record header of current stats sample.
1619 ***************************************************************************
1621 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1622 unsigned long long itv, struct record_header *record_hdr)
1625 *smc = (struct stats_memory *) a->buf[curr];
1626 int group1[] = {3, 1, 3, 1, 3, 5};
1627 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1628 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1629 int group2[] = {3, 1, 1};
1630 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1631 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1632 "Memory utilization (3)", "Memory utilization (4)",
1633 "Memory utilization (5)", "Memory utilization (6)"};
1634 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1635 "Swap utilization (3)"};
1636 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1637 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1638 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1640 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1642 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1643 static double *spmin, *spmax;
1645 static int *outsize;
1649 unsigned long long nousedmem;
1651 if (action & F_BEGIN) {
1653 * Allocate arrays that will contain the graphs data
1654 * and the min/max values.
1656 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1659 if (action & F_MAIN) {
1660 /* Check for min/max values */
1661 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1662 itv, spmin, spmax, g_fields);
1663 /* Compute %memused min/max values */
1664 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1665 if (nousedmem > smc->tlmkb) {
1666 nousedmem = smc->tlmkb;
1668 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1669 if (tval > *(spmax + 3)) {
1670 *(spmax + 3) = tval;
1672 if (tval < *(spmin + 3)) {
1673 *(spmin + 3) = tval;
1675 /* Compute %commit min/max values */
1676 tval = (smc->tlmkb + smc->tlskb) ?
1677 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1678 if (tval > *(spmax + 7)) {
1679 *(spmax + 7) = tval;
1681 if (tval < *(spmin + 7)) {
1682 *(spmin + 7) = tval;
1684 /* Compute %swpused min/max values */
1686 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1687 if (tval > *(spmax + 19)) {
1688 *(spmax + 19) = tval;
1690 if (tval < *(spmin + 19)) {
1691 *(spmin + 19) = tval;
1693 /* Compute %swpcad min/max values */
1694 tval = (smc->tlskb - smc->frskb) ?
1695 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1696 if (tval > *(spmax + 20)) {
1697 *(spmax + 20) = tval;
1699 if (tval < *(spmin + 20)) {
1700 *(spmin + 20) = tval;
1702 /* Compute memused min/max values in MB */
1703 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1704 if (tval > *(spmax + 2)) {
1705 *(spmax + 2) = tval;
1707 if (tval < *(spmin + 2)) {
1708 *(spmin + 2) = tval;
1710 /* Compute swpused min/max values in MB */
1711 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1712 if (tval > *(spmax + 17)) {
1713 *(spmax + 17) = tval;
1715 if (tval < *(spmin + 17)) {
1716 *(spmin + 17) = tval;
1720 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1721 ((double) smc->frmkb) / 1024,
1722 out, outsize, svg_p->restart);
1724 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1725 ((double) (smc->tlmkb - nousedmem)) / 1024,
1726 out + 2, outsize + 2, svg_p->restart);
1728 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1729 ((double) smc->availablekb) / 1024,
1730 out + 1, outsize + 1, svg_p->restart);
1732 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1733 ((double) smc->bufkb) / 1024,
1734 out + 4, outsize + 4, svg_p->restart);
1736 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1737 ((double) smc->camkb) / 1024,
1738 out + 5, outsize + 5, svg_p->restart);
1740 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1741 ((double) smc->frskb) / 1024,
1742 out + 16, outsize + 16, svg_p->restart);
1744 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1745 ((double) (smc->tlskb - smc->frskb)) / 1024,
1746 out + 17, outsize + 17, svg_p->restart);
1748 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1749 ((double) smc->caskb) / 1024,
1750 out + 18, outsize + 18, svg_p->restart);
1752 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1753 ((double) smc->comkb) / 1024,
1754 out + 6, outsize + 6, svg_p->restart);
1756 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1757 ((double) smc->activekb) / 1024,
1758 out + 8, outsize + 8, svg_p->restart);
1760 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1761 ((double) smc->inactkb) / 1024,
1762 out + 9, outsize + 9, svg_p->restart);
1764 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1765 ((double) smc->dirtykb) / 1024,
1766 out + 10, outsize + 10, svg_p->restart);
1768 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1769 ((double) smc->anonpgkb) / 1024,
1770 out + 11, outsize + 11, svg_p->restart);
1772 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1773 ((double) smc->slabkb) / 1024,
1774 out + 12, outsize + 12, svg_p->restart);
1776 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1777 ((double) smc->kstackkb) / 1024,
1778 out + 13, outsize + 13, svg_p->restart);
1780 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1781 ((double) smc->pgtblkb) / 1024,
1782 out + 14, outsize + 14, svg_p->restart);
1784 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1785 ((double) smc->vmusedkb) / 1024,
1786 out + 15, outsize + 15, svg_p->restart);
1788 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1791 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1792 out + 3, outsize + 3, svg_p->dt);
1794 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1796 (smc->tlmkb + smc->tlskb) ?
1797 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1798 out + 7, outsize + 7, svg_p->dt);
1800 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1803 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1804 out + 19, outsize + 19, svg_p->dt);
1806 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1808 (smc->tlskb - smc->frskb) ?
1809 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1810 out + 20, outsize + 20, svg_p->dt);
1813 if (action & F_END) {
1815 /* Conversion kB -> MB */
1816 for (i = 0; i < 17; i++) {
1817 *(spmin + g_fields[i]) /= 1024;
1818 *(spmax + g_fields[i]) /= 1024;
1821 if (DISPLAY_MEMORY(a->opt_flags)) {
1822 if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1823 g_type1, title1, g_title1, NULL, group1,
1824 spmin, spmax, out, outsize, svg_p, record_hdr,
1825 FALSE, a->id, xid)) {
1830 if (DISPLAY_SWAP(a->opt_flags)) {
1831 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1832 spmin + 16, spmax + 16, out + 16, outsize + 16,
1833 svg_p, record_hdr, FALSE, a->id, xid);
1836 /* Free remaining structures */
1837 free_graphs(out, outsize, spmin, spmax);
1842 ***************************************************************************
1843 * Display kernel tables statistics in SVG.
1846 * @a Activity structure with statistics.
1847 * @curr Index in array for current sample statistics.
1848 * @action Action expected from current function.
1849 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1850 * flag indicating that a restart record has been previously
1851 * found (.@restart) and time used for the X axis origin
1853 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1854 * @record_hdr Pointer on record header of current stats sample.
1855 ***************************************************************************
1857 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1858 unsigned long long itv, struct record_header *record_hdr)
1860 struct stats_ktables
1861 *skc = (struct stats_ktables *) a->buf[curr];
1862 int group[] = {3, 1};
1863 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1864 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1865 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1867 int g_fields[] = {1, 2, 0, 3};
1868 static double *spmin, *spmax;
1870 static int *outsize;
1872 if (action & F_BEGIN) {
1874 * Allocate arrays that will contain the graphs data
1875 * and the min/max values.
1877 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1880 if (action & F_MAIN) {
1881 /* Check for min/max values */
1882 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1883 itv, spmin, spmax, g_fields);
1885 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1886 (unsigned long long) skc->dentry_stat,
1887 out, outsize, svg_p->restart);
1889 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1890 (unsigned long long) skc->file_used,
1891 out + 1, outsize + 1, svg_p->restart);
1893 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1894 (unsigned long long) skc->inode_used,
1895 out + 2, outsize + 2, svg_p->restart);
1897 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1898 (unsigned long long) skc->pty_nr,
1899 out + 3, outsize + 3, svg_p->restart);
1902 if (action & F_END) {
1903 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1904 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1906 /* Free remaining structures */
1907 free_graphs(out, outsize, spmin, spmax);
1912 ***************************************************************************
1913 * Display queue and load statistics in SVG.
1916 * @a Activity structure with statistics.
1917 * @curr Index in array for current sample statistics.
1918 * @action Action expected from current function.
1919 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1920 * flag indicating that a restart record has been previously
1921 * found (.@restart) and time used for the X axis origin
1923 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1924 * @record_hdr Pointer on record header of current stats sample.
1925 ***************************************************************************
1927 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1928 unsigned long long itv, struct record_header *record_hdr)
1931 *sqc = (struct stats_queue *) a->buf[curr];
1932 int group[] = {2, 1, 3};
1933 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1934 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
1935 char *g_title[] = {"~runq-sz", "~blocked",
1937 "ldavg-1", "ldavg-5", "ldavg-15"};
1938 int g_fields[] = {0, 1, 2, 3, 4, 5};
1939 static double *spmin, *spmax;
1941 static int *outsize;
1943 if (action & F_BEGIN) {
1945 * Allocate arrays that will contain the graphs data
1946 * and the min/max values.
1948 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1951 if (action & F_MAIN) {
1952 /* Check for min/max values */
1953 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1954 itv, spmin, spmax, g_fields);
1956 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1957 (unsigned long long) sqc->nr_running,
1958 out, outsize, svg_p->restart);
1960 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1961 (unsigned long long) sqc->procs_blocked,
1962 out + 1, outsize + 1, svg_p->restart);
1964 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1965 (unsigned long long) sqc->nr_threads,
1966 out + 2, outsize + 2, svg_p->restart);
1968 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1969 (double) sqc->load_avg_1 / 100,
1970 out + 3, outsize + 3, svg_p->restart);
1972 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1973 (double) sqc->load_avg_5 / 100,
1974 out + 4, outsize + 4, svg_p->restart);
1976 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1977 (double) sqc->load_avg_15 / 100,
1978 out + 5, outsize + 5, svg_p->restart);
1981 if (action & F_END) {
1982 /* Fix min/max values for load average */
1983 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1984 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1985 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1987 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1988 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1990 /* Free remaining structures */
1991 free_graphs(out, outsize, spmin, spmax);
1996 ***************************************************************************
1997 * Display disk statistics in SVG.
2000 * @a Activity structure with statistics.
2001 * @curr Index in array for current sample statistics.
2002 * @action Action expected from current function.
2003 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2004 * flag indicating that a restart record has been previously
2005 * found (.@restart) and time used for the X axis origin
2007 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2008 * @record_hdr Pointer on record header of current stats sample.
2009 ***************************************************************************
2011 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2012 unsigned long long itv, struct record_header *record_hdr)
2014 struct stats_disk *sdc, *sdp, sdpzero;
2015 struct ext_disk_stats xds;
2016 int group[] = {1, 3, 2, 1, 1};
2017 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2018 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2019 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2020 "Block devices statistics (3)", "Block devices statistics (4)",
2021 "Block devices statistics (5)"};
2022 char *g_title[] = {"tps",
2023 "rkB/s", "wkB/s", "dkB/s",
2024 "areq-sz", "aqu-sz",
2027 int g_fields[] = {0, 1, 2};
2029 unsigned int local_types_nr[] = {1, 0, 0};
2030 static double *spmin, *spmax;
2032 static int *outsize;
2034 double rkB, wkB, dkB, aqusz;
2035 int i, j, k, pos, restart, *unregistered;
2037 if (action & F_BEGIN) {
2039 * Allocate arrays (#0..7) that will contain the graphs data
2040 * and the min/max values.
2041 * Also allocate one additional array (#8) for each disk device:
2042 * spmax + 8 will contain the device major number,
2043 * spmin + 8 will contain the device minor number,
2044 * outsize + 8 will contain a positive value (TRUE) if the device
2045 * has either still not been registered, or has been unregistered.
2047 out = allocate_graph_lines(nr_arrays * a->item_list_sz, &outsize, &spmin, &spmax);
2050 if (action & F_MAIN) {
2051 memset(&sdpzero, 0, STATS_DISK_SIZE);
2052 restart = svg_p->restart;
2054 * Mark previously registered devices as now
2055 * possibly unregistered for all graphs.
2057 for (k = 0; k < a->item_list_sz; k++) {
2058 unregistered = outsize + k * nr_arrays + 8;
2059 if (*unregistered == FALSE) {
2060 *unregistered = MAYBE;
2064 /* For each device structure */
2065 for (i = 0; i < a->nr[curr]; i++) {
2066 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2068 /* Get device name */
2069 item_name = get_sa_devname(sdc->major, sdc->minor, flags);
2071 if (a->item_list != NULL) {
2072 /* A list of devices has been entered on the command line */
2073 if (!search_list_item(a->item_list, item_name))
2074 /* Device not found */
2078 /* Look for corresponding graph */
2079 for (k = 0; k < a->item_list_sz; k++) {
2080 if ((sdc->major == *(spmax + k * nr_arrays + 8)) &&
2081 (sdc->minor == *(spmin + k * nr_arrays + 8)))
2085 if (k == a->item_list_sz) {
2086 /* Graph not found: Look for first free entry */
2087 for (k = 0; k < a->item_list_sz; k++) {
2088 if (*(spmax + k * nr_arrays + 8) == -DBL_MAX)
2091 if (k == a->item_list_sz) {
2092 /* No free graph entry: Ignore it (should never happen) */
2094 fprintf(stderr, "%s: Name=%s major=%d minor=%d\n",
2095 __FUNCTION__, item_name, sdc->major, sdc->minor);
2100 pos = k * nr_arrays;
2101 unregistered = outsize + pos + 8;
2104 * If current device was marked as previously unregistered,
2105 * then set restart variable to TRUE so that the graph will be
2106 * discontinuous, and mark it as now registered.
2108 if (*unregistered == TRUE) {
2111 *unregistered = FALSE;
2113 if (*(spmax + pos + 8) == -DBL_MAX) {
2114 /* Save device major and minor numbers (if not already done) */
2115 *(spmax + pos + 8) = sdc->major;
2116 *(spmin + pos + 8) = sdc->minor;
2119 j = check_disk_reg(a, curr, !curr, i);
2121 /* This is a newly registered interface. Previous stats are zero */
2125 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2128 /* Check for min/max values */
2129 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2130 itv, spmin + pos, spmax + pos, g_fields);
2132 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2133 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2134 dkB = S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2;
2135 if (rkB < *(spmin + pos + 1)) {
2136 *(spmin + pos + 1) = rkB;
2138 if (rkB > *(spmax + pos + 1)) {
2139 *(spmax + pos + 1) = rkB;
2141 if (wkB < *(spmin + pos + 2)) {
2142 *(spmin + pos + 2) = wkB;
2144 if (wkB > *(spmax + pos + 2)) {
2145 *(spmax + pos + 2) = wkB;
2147 if (dkB < *(spmin + pos + 3)) {
2148 *(spmin + pos + 3) = dkB;
2150 if (dkB > *(spmax + pos + 3)) {
2151 *(spmax + pos + 3) = dkB;
2154 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2155 if ((xds.arqsz / 2) < *(spmin + pos + 4)) {
2156 *(spmin + pos + 4) = xds.arqsz / 2;
2158 if ((xds.arqsz / 2) > *(spmax + pos + 4)) {
2159 *(spmax + pos + 4) = xds.arqsz / 2;
2161 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2162 if (aqusz < *(spmin + pos + 5)) {
2163 *(spmin + pos + 5) = aqusz;
2165 if (aqusz > *(spmax + pos + 5)) {
2166 *(spmax + pos + 5) = aqusz;
2168 if (xds.await < *(spmin + pos + 6)) {
2169 *(spmin + pos + 6) = xds.await;
2171 if (xds.await > *(spmax + pos + 6)) {
2172 *(spmax + pos + 6) = xds.await;
2174 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2175 *(spmin + pos + 7) = xds.util / 10.0;
2177 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2178 *(spmax + pos + 7) = xds.util / 10.0;
2182 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2183 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2184 out + pos, outsize + pos, restart);
2186 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2187 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2188 out + pos + 1, outsize + pos + 1, restart);
2190 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2191 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2192 out + pos + 2, outsize + pos + 2, restart);
2194 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2195 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2196 out + pos + 3, outsize + pos + 3, restart);
2198 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2200 out + pos + 4, outsize + pos + 4, restart);
2202 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2204 out + pos + 5, outsize + pos + 5, restart);
2206 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2208 out + pos + 6, outsize + pos + 6, restart);
2210 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2211 0.0, xds.util / 10.0,
2212 out + pos + 7, outsize + pos + 7, svg_p->dt);
2215 /* Mark devices not seen here as now unregistered */
2216 for (k = 0; k < a->item_list_sz; k++) {
2217 unregistered = outsize + k * nr_arrays + 8;
2218 if (*unregistered != FALSE) {
2219 *unregistered = TRUE;
2224 if (action & F_END) {
2227 for (i = 0; i < a->item_list_sz; i++) {
2228 /* Check if there is something to display */
2229 pos = i * nr_arrays;
2233 /* Get device name */
2234 item_name = get_sa_devname(*(spmax + pos + 8), *(spmin + pos + 8), flags);
2236 if (draw_activity_graphs(a->g_nr, g_type,
2237 title, g_title, item_name, group,
2238 spmin + pos, spmax + pos, out + pos, outsize + pos,
2239 svg_p, record_hdr, FALSE, a->id, xid)) {
2244 /* Free remaining structures */
2245 free_graphs(out, outsize, spmin, spmax);
2250 ***************************************************************************
2251 * Display network interfaces statistics in SVG.
2254 * @a Activity structure with statistics.
2255 * @curr Index in array for current sample statistics.
2256 * @action Action expected from current function.
2257 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2258 * flag indicating that a restart record has been previously
2259 * found (.@restart) and time used for the X axis origin
2261 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2262 * @record_hdr Pointer on record header of current stats sample.
2263 ***************************************************************************
2265 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2266 unsigned long long itv, struct record_header *record_hdr)
2268 struct stats_net_dev *sndc, *sndp, sndzero;
2269 int group[] = {2, 2, 3, 1};
2270 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2272 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2273 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2274 char *g_title[] = {"rxpck/s", "txpck/s",
2276 "rxcmp/s", "txcmp/s", "rxmcst/s",
2278 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2279 unsigned int local_types_nr[] = {7, 0, 0};
2280 static double *spmin, *spmax;
2282 static int *outsize;
2284 double rxkb, txkb, ifutil;
2285 int i, j, k, pos, restart, *unregistered;
2287 if (action & F_BEGIN) {
2289 * Allocate arrays (#0..7) that will contain the graphs data
2290 * and the min/max values.
2291 * Also allocate one additional array (#8) for each interface:
2292 * out + 8 will contain the interface name,
2293 * outsize + 8 will contain a positive value (TRUE) if the interface
2294 * has either still not been registered, or has been unregistered.
2296 out = allocate_graph_lines(9 * a->item_list_sz, &outsize, &spmin, &spmax);
2299 if (action & F_MAIN) {
2300 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2301 restart = svg_p->restart;
2303 * Mark previously registered interfaces as now
2304 * possibly unregistered for all graphs.
2306 for (k = 0; k < a->item_list_sz; k++) {
2307 unregistered = outsize + k * 9 + 8;
2308 if (*unregistered == FALSE) {
2309 *unregistered = MAYBE;
2313 /* For each network interfaces structure */
2314 for (i = 0; i < a->nr[curr]; i++) {
2315 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2317 if (a->item_list != NULL) {
2318 /* A list of devices has been entered on the command line */
2319 if (!search_list_item(a->item_list, sndc->interface))
2320 /* Device not found */
2324 /* Look for corresponding graph */
2325 for (k = 0; k < a->item_list_sz; k++) {
2326 item_name = *(out + k * 9 + 8);
2327 if (!strcmp(sndc->interface, item_name))
2331 if (k == a->item_list_sz) {
2332 /* Graph not found: Look for first free entry */
2333 for (k = 0; k < a->item_list_sz; k++) {
2334 item_name = *(out + k * 9 + 8);
2335 if (!strcmp(item_name, ""))
2338 if (k == a->item_list_sz) {
2339 /* No free graph entry: Ignore it (should never happen) */
2341 fprintf(stderr, "%s: Name=%s\n",
2342 __FUNCTION__, sndc->interface);
2348 unregistered = outsize + pos + 8;
2350 j = check_net_dev_reg(a, curr, !curr, i);
2352 /* This is a newly registered interface. Previous stats are zero */
2356 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2360 * If current interface was marked as previously unregistered,
2361 * then set restart variable to TRUE so that the graph will be
2362 * discontinuous, and mark it as now registered.
2364 if (*unregistered == TRUE) {
2367 *unregistered = FALSE;
2369 item_name = *(out + pos + 8);
2370 if (!item_name[0]) {
2371 /* Save network interface name (if not already done) */
2372 strncpy(item_name, sndc->interface, CHUNKSIZE);
2373 item_name[CHUNKSIZE - 1] = '\0';
2376 /* Check for min/max values */
2377 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2378 itv, spmin + pos, spmax + pos, g_fields);
2380 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2381 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2382 ifutil = compute_ifutil(sndc, rxkb, txkb);
2383 if (ifutil < *(spmin + pos + 7)) {
2384 *(spmin + pos + 7) = ifutil;
2386 if (ifutil > *(spmax + pos + 7)) {
2387 *(spmax + pos + 7) = ifutil;
2391 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2392 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2393 out + pos, outsize + pos, restart);
2395 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2396 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2397 out + pos + 1, outsize + pos + 1, restart);
2399 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2401 out + pos + 2, outsize + pos + 2, restart);
2403 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2405 out + pos + 3, outsize + pos + 3, restart);
2407 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2408 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2409 out + pos + 4, outsize + pos + 4, restart);
2411 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2412 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2413 out + pos + 5, outsize + pos + 5, restart);
2415 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2416 S_VALUE(sndp->multicast, sndc->multicast, itv),
2417 out + pos + 6, outsize + pos + 6, restart);
2419 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2421 out + pos + 7, outsize + pos + 7, svg_p->dt);
2424 /* Mark interfaces not seen here as now unregistered */
2425 for (k = 0; k < a->item_list_sz; k++) {
2426 unregistered = outsize + k * 9 + 8;
2427 if (*unregistered != FALSE) {
2428 *unregistered = TRUE;
2433 if (action & F_END) {
2436 for (i = 0; i < a->item_list_sz; i++) {
2438 * Check if there is something to display.
2439 * Don't test sndc->interface because maybe the network
2440 * interface has been registered later.
2446 /* Recalculate min and max values in kB, not in B */
2447 *(spmin + pos + 2) /= 1024;
2448 *(spmax + pos + 2) /= 1024;
2449 *(spmin + pos + 3) /= 1024;
2450 *(spmax + pos + 3) /= 1024;
2452 item_name = *(out + pos + 8);
2453 if (draw_activity_graphs(a->g_nr, g_type,
2454 title, g_title, item_name, group,
2455 spmin + pos, spmax + pos, out + pos, outsize + pos,
2456 svg_p, record_hdr, FALSE, a->id, xid)) {
2461 /* Free remaining structures */
2462 free_graphs(out, outsize, spmin, spmax);
2467 ***************************************************************************
2468 * Display network interfaces errors statistics in SVG.
2471 * @a Activity structure with statistics.
2472 * @curr Index in array for current sample statistics.
2473 * @action Action expected from current function.
2474 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2475 * flag indicating that a restart record has been previously
2476 * found (.@restart) and time used for the X axis origin
2478 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2479 * @record_hdr Pointer on record header of current stats sample.
2480 ***************************************************************************
2482 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2483 unsigned long long itv, struct record_header *record_hdr)
2485 struct stats_net_edev *snedc, *snedp, snedzero;
2486 int group[] = {2, 2, 2, 3};
2487 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2489 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2490 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2491 char *g_title[] = {"rxerr/s", "txerr/s",
2492 "rxdrop/s", "txdrop/s",
2493 "rxfifo/s", "txfifo/s",
2494 "coll/s", "txcarr/s", "rxfram/s"};
2495 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2496 static double *spmin, *spmax;
2498 static int *outsize;
2500 int i, j, k, pos, restart, *unregistered;
2502 if (action & F_BEGIN) {
2504 * Allocate arrays (#0..8) that will contain the graphs data
2505 * and the min/max values.
2506 * Also allocate one additional array (#9) for each interface:
2507 * out + 9 will contain the interface name,
2508 * outsize + 9 will contain a positive value (TRUE) if the interface
2509 * has either still not been registered, or has been unregistered.
2511 out = allocate_graph_lines(10 * a->item_list_sz, &outsize, &spmin, &spmax);
2514 if (action & F_MAIN) {
2515 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2516 restart = svg_p->restart;
2518 * Mark previously registered interfaces as now
2519 * possibly unregistered for all graphs.
2521 for (k = 0; k < a->item_list_sz; k++) {
2522 unregistered = outsize + k * 10 + 9;
2523 if (*unregistered == FALSE) {
2524 *unregistered = MAYBE;
2528 /* For each network interfaces structure */
2529 for (i = 0; i < a->nr[curr]; i++) {
2530 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2531 if (!strcmp(snedc->interface, ""))
2532 /* Empty structure: This is the end of the list */
2535 if (a->item_list != NULL) {
2536 /* A list of devices has been entered on the command line */
2537 if (!search_list_item(a->item_list, snedc->interface))
2538 /* Device not found */
2542 /* Look for corresponding graph */
2543 for (k = 0; k < a->item_list_sz; k++) {
2544 item_name = *(out + k * 10 + 9);
2545 if (!strcmp(snedc->interface, item_name))
2549 if (k == a->item_list_sz) {
2550 /* Graph not found: Look for first free entry */
2551 for (k = 0; k < a->item_list_sz; k++) {
2552 item_name = *(out + k * 10 + 9);
2553 if (!strcmp(item_name, ""))
2556 if (k == a->item_list_sz) {
2557 /* No free graph entry: Ignore it (should never happen) */
2559 fprintf(stderr, "%s: Name=%s\n",
2560 __FUNCTION__, snedc->interface);
2567 unregistered = outsize + pos + 9;
2569 j = check_net_edev_reg(a, curr, !curr, i);
2571 /* This is a newly registered interface. Previous stats are zero */
2575 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2579 * If current interface was marked as previously unregistered,
2580 * then set restart variable to TRUE so that the graph will be
2581 * discontinuous, and mark it as now registered.
2583 if (*unregistered == TRUE) {
2586 *unregistered = FALSE;
2588 item_name = *(out + pos + 9);
2589 if (!item_name[0]) {
2590 /* Save network interface name (if not already done) */
2591 strncpy(item_name, snedc->interface, CHUNKSIZE);
2592 item_name[CHUNKSIZE - 1] = '\0';
2595 /* Check for min/max values */
2596 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2597 itv, spmin + pos, spmax + pos, g_fields);
2600 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2601 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2602 out + pos, outsize + pos, restart);
2604 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2605 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2606 out + pos + 1, outsize + pos + 1, restart);
2608 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2609 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2610 out + pos + 2, outsize + pos + 2, restart);
2612 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2613 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2614 out + pos + 3, outsize + pos + 3, restart);
2616 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2617 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2618 out + pos + 4, outsize + pos + 4, restart);
2620 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2621 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2622 out + pos + 5, outsize + pos + 5, restart);
2624 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2625 S_VALUE(snedp->collisions, snedc->collisions, itv),
2626 out + pos + 6, outsize + pos + 6, restart);
2628 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2629 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2630 out + pos + 7, outsize + pos + 7, restart);
2632 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2633 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2634 out + pos + 8, outsize + pos + 8, restart);
2637 /* Mark interfaces not seen here as now unregistered */
2638 for (k = 0; k < a->item_list_sz; k++) {
2639 unregistered = outsize + k * 10 + 9;
2640 if (*unregistered != FALSE) {
2641 *unregistered = TRUE;
2646 if (action & F_END) {
2649 for (i = 0; i < a->item_list_sz; i++) {
2651 * Check if there is something to display.
2652 * Don't test snedc->interface because maybe the network
2653 * interface has been registered later.
2659 item_name = *(out + pos + 9);
2660 if (draw_activity_graphs(a->g_nr, g_type,
2661 title, g_title, item_name, group,
2662 spmin + pos, spmax + pos, out + pos, outsize + pos,
2663 svg_p, record_hdr, FALSE, a->id, xid)) {
2668 /* Free remaining structures */
2669 free_graphs(out, outsize, spmin, spmax);
2674 ***************************************************************************
2675 * Display NFS client statistics in SVG.
2678 * @a Activity structure with statistics.
2679 * @curr Index in array for current sample statistics.
2680 * @action Action expected from current function.
2681 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2682 * flag indicating that a restart record has been previously
2683 * found (.@restart) and time used for the X axis origin
2685 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2686 * @record_hdr Pointer on record header of current stats sample.
2687 ***************************************************************************
2689 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2690 unsigned long long itv, struct record_header *record_hdr)
2692 struct stats_net_nfs
2693 *snnc = (struct stats_net_nfs *) a->buf[curr],
2694 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2695 int group[] = {2, 2, 2};
2696 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2697 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2698 "NFS client statistics (3)"};
2699 char *g_title[] = {"call/s", "retrans/s",
2700 "read/s", "write/s",
2701 "access/s", "getatt/s"};
2702 int g_fields[] = {0, 1, 2, 3, 4, 5};
2703 static double *spmin, *spmax;
2705 static int *outsize;
2707 if (action & F_BEGIN) {
2709 * Allocate arrays that will contain the graphs data
2710 * and the min/max values.
2712 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2715 if (action & F_MAIN) {
2716 /* Check for min/max values */
2717 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2718 itv, spmin, spmax, g_fields);
2721 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2722 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2723 out, outsize, svg_p->restart);
2725 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2726 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2727 out + 1, outsize + 1, svg_p->restart);
2729 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2730 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2731 out + 2, outsize + 2, svg_p->restart);
2733 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2734 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2735 out + 3, outsize + 3, svg_p->restart);
2737 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2738 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2739 out + 4, outsize + 4, svg_p->restart);
2741 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2742 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2743 out + 5, outsize + 5, svg_p->restart);
2746 if (action & F_END) {
2747 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2748 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2750 /* Free remaining structures */
2751 free_graphs(out, outsize, spmin, spmax);
2756 ***************************************************************************
2757 * Display NFS server statistics in SVG.
2760 * @a Activity structure with statistics.
2761 * @curr Index in array for current sample statistics.
2762 * @action Action expected from current function.
2763 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2764 * flag indicating that a restart record has been previously
2765 * found (.@restart) and time used for the X axis origin
2767 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2768 * @record_hdr Pointer on record header of current stats sample.
2769 ***************************************************************************
2771 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2772 unsigned long long itv, struct record_header *record_hdr)
2774 struct stats_net_nfsd
2775 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2776 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2777 int group[] = {2, 3, 2, 2, 2};
2778 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2779 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2780 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2781 "NFS server statistics (3)", "NFS server statistics (4)",
2782 "NFS server statistics (5)"};
2783 char *g_title[] = {"scall/s", "badcall/s",
2784 "packet/s", "udp/s", "tcp/s",
2786 "sread/s", "swrite/s",
2787 "saccess/s", "sgetatt/s"};
2788 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2789 static double *spmin, *spmax;
2791 static int *outsize;
2793 if (action & F_BEGIN) {
2795 * Allocate arrays that will contain the graphs data
2796 * and the min/max values.
2798 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2801 if (action & F_MAIN) {
2802 /* Check for min/max values */
2803 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2804 itv, spmin, spmax, g_fields);
2807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2808 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2809 out, outsize, svg_p->restart);
2811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2812 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2813 out + 1, outsize + 1, svg_p->restart);
2815 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2816 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2817 out + 2, outsize + 2, svg_p->restart);
2819 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2820 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2821 out + 3, outsize + 3, svg_p->restart);
2823 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2824 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2825 out + 4, outsize + 4, svg_p->restart);
2827 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2828 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2829 out + 5, outsize + 5, svg_p->restart);
2831 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2832 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2833 out + 6, outsize + 6, svg_p->restart);
2835 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2836 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2837 out + 7, outsize + 7, svg_p->restart);
2839 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2840 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2841 out + 8, outsize + 8, svg_p->restart);
2843 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2844 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2845 out + 9, outsize + 9, svg_p->restart);
2847 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2848 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2849 out + 10, outsize + 10, svg_p->restart);
2852 if (action & F_END) {
2853 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2854 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2856 /* Free remaining structures */
2857 free_graphs(out, outsize, spmin, spmax);
2862 ***************************************************************************
2863 * Display socket statistics in SVG.
2866 * @a Activity structure with statistics.
2867 * @curr Index in array for current sample statistics.
2868 * @action Action expected from current function.
2869 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2870 * flag indicating that a restart record has been previously
2871 * found (.@restart) and time used for the X axis origin
2873 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2874 * @record_hdr Pointer on record header of current stats sample.
2875 ***************************************************************************
2877 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2878 unsigned long long itv, struct record_header *record_hdr)
2880 struct stats_net_sock
2881 *snsc = (struct stats_net_sock *) a->buf[curr];
2882 int group[] = {1, 5};
2883 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2884 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2885 char *g_title[] = {"~totsck",
2886 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2887 int g_fields[] = {0, 1, 5, 2, 3, 4};
2888 static double *spmin, *spmax;
2890 static int *outsize;
2892 if (action & F_BEGIN) {
2894 * Allocate arrays that will contain the graphs data
2895 * and the min/max values.
2897 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2900 if (action & F_MAIN) {
2901 /* Check for min/max values */
2902 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2903 itv, spmin, spmax, g_fields);
2905 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2906 (unsigned long long) snsc->sock_inuse,
2907 out, outsize, svg_p->restart);
2909 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2910 (unsigned long long) snsc->tcp_inuse,
2911 out + 1, outsize + 1, svg_p->restart);
2913 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2914 (unsigned long long) snsc->udp_inuse,
2915 out + 2, outsize + 2, svg_p->restart);
2917 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2918 (unsigned long long) snsc->raw_inuse,
2919 out + 3, outsize + 3, svg_p->restart);
2921 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2922 (unsigned long long) snsc->frag_inuse,
2923 out + 4, outsize + 4, svg_p->restart);
2925 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2926 (unsigned long long) snsc->tcp_tw,
2927 out + 5, outsize + 5, svg_p->restart);
2930 if (action & F_END) {
2931 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2932 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2934 /* Free remaining structures */
2935 free_graphs(out, outsize, spmin, spmax);
2940 ***************************************************************************
2941 * Display IPv4 traffic statistics in SVG.
2944 * @a Activity structure with statistics.
2945 * @curr Index in array for current sample statistics.
2946 * @action Action expected from current function.
2947 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2948 * flag indicating that a restart record has been previously
2949 * found (.@restart) and time used for the X axis origin
2951 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2952 * @record_hdr Pointer on record header of current stats sample.
2953 ***************************************************************************
2955 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2956 unsigned long long itv, struct record_header *record_hdr)
2959 *snic = (struct stats_net_ip *) a->buf[curr],
2960 *snip = (struct stats_net_ip *) a->buf[!curr];
2961 int group[] = {4, 2, 2};
2962 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2963 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
2964 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2965 "asmrq/s", "asmok/s",
2966 "fragok/s", "fragcrt/s"};
2967 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2968 static double *spmin, *spmax;
2970 static int *outsize;
2972 if (action & F_BEGIN) {
2974 * Allocate arrays that will contain the graphs data
2975 * and the min/max values.
2977 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2980 if (action & F_MAIN) {
2981 /* Check for min/max values */
2982 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2983 itv, spmin, spmax, g_fields);
2986 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2987 S_VALUE(snip->InReceives, snic->InReceives, itv),
2988 out, outsize, svg_p->restart);
2990 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2991 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2992 out + 1, outsize + 1, svg_p->restart);
2994 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2995 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2996 out + 2, outsize + 2, svg_p->restart);
2998 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2999 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3000 out + 3, outsize + 3, svg_p->restart);
3002 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3003 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3004 out + 4, outsize + 4, svg_p->restart);
3006 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3007 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3008 out + 5, outsize + 5, svg_p->restart);
3010 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3011 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3012 out + 6, outsize + 6, svg_p->restart);
3014 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3015 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3016 out + 7, outsize + 7, svg_p->restart);
3019 if (action & F_END) {
3020 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3021 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3023 /* Free remaining structures */
3024 free_graphs(out, outsize, spmin, spmax);
3029 ***************************************************************************
3030 * Display IPv4 traffic errors statistics in SVG.
3033 * @a Activity structure with statistics.
3034 * @curr Index in array for current sample statistics.
3035 * @action Action expected from current function.
3036 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3037 * flag indicating that a restart record has been previously
3038 * found (.@restart) and time used for the X axis origin
3040 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3041 * @record_hdr Pointer on record header of current stats sample.
3042 ***************************************************************************
3044 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3045 unsigned long long itv, struct record_header *record_hdr)
3047 struct stats_net_eip
3048 *sneic = (struct stats_net_eip *) a->buf[curr],
3049 *sneip = (struct stats_net_eip *) a->buf[!curr];
3050 int group[] = {3, 2, 3};
3051 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3052 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3053 "IPv4 traffic errors statistics (3)"};
3054 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3055 "idisc/s", "odisc/s",
3056 "onort/s", "asmf/s", "fragf/s"};
3057 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3058 static double *spmin, *spmax;
3060 static int *outsize;
3062 if (action & F_BEGIN) {
3064 * Allocate arrays that will contain the graphs data
3065 * and the min/max values.
3067 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3070 if (action & F_MAIN) {
3071 /* Check for min/max values */
3072 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3073 itv, spmin, spmax, g_fields);
3076 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3077 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3078 out, outsize, svg_p->restart);
3080 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3081 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3082 out + 1, outsize + 1, svg_p->restart);
3084 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3085 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3086 out + 2, outsize + 2, svg_p->restart);
3088 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3089 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3090 out + 3, outsize + 3, svg_p->restart);
3092 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3093 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3094 out + 4, outsize + 4, svg_p->restart);
3096 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3097 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3098 out + 5, outsize + 5, svg_p->restart);
3100 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3101 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3102 out + 6, outsize + 6, svg_p->restart);
3104 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3105 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3106 out + 7, outsize + 7, svg_p->restart);
3109 if (action & F_END) {
3110 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3111 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3113 /* Free remaining structures */
3114 free_graphs(out, outsize, spmin, spmax);
3119 ***************************************************************************
3120 * Display ICMPv4 traffic statistics in SVG.
3123 * @a Activity structure with statistics.
3124 * @curr Index in array for current sample statistics.
3125 * @action Action expected from current function.
3126 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3127 * flag indicating that a restart record has been previously
3128 * found (.@restart) and time used for the X axis origin
3130 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3131 * @record_hdr Pointer on record header of current stats sample.
3132 ***************************************************************************
3134 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3135 unsigned long long itv, struct record_header *record_hdr)
3137 struct stats_net_icmp
3138 *snic = (struct stats_net_icmp *) a->buf[curr],
3139 *snip = (struct stats_net_icmp *) a->buf[!curr];
3140 int group[] = {2, 4, 4, 4};
3141 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3143 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3144 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3145 char *g_title[] = {"imsg/s", "omsg/s",
3146 "iech/s", "iechr/s", "oech/s", "oechr/s",
3147 "itm/s", "itmr/s", "otm/s", "otmr/s",
3148 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3149 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3150 static double *spmin, *spmax;
3152 static int *outsize;
3154 if (action & F_BEGIN) {
3156 * Allocate arrays that will contain the graphs data
3157 * and the min/max values.
3159 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3162 if (action & F_MAIN) {
3163 /* Check for min/max values */
3164 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3165 itv, spmin, spmax, g_fields);
3168 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3169 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3170 out, outsize, svg_p->restart);
3172 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3173 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3174 out + 1, outsize + 1, svg_p->restart);
3176 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3177 S_VALUE(snip->InEchos, snic->InEchos, itv),
3178 out + 2, outsize + 2, svg_p->restart);
3180 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3181 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3182 out + 3, outsize + 3, svg_p->restart);
3184 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3185 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3186 out + 4, outsize + 4, svg_p->restart);
3188 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3189 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3190 out + 5, outsize + 5, svg_p->restart);
3192 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3193 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3194 out + 6, outsize + 6, svg_p->restart);
3196 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3197 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3198 out + 7, outsize + 7, svg_p->restart);
3200 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3201 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3202 out + 8, outsize + 8, svg_p->restart);
3204 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3205 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3206 out + 9, outsize + 9, svg_p->restart);
3208 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3209 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3210 out + 10, outsize + 10, svg_p->restart);
3212 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3213 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3214 out + 11, outsize + 11, svg_p->restart);
3216 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3217 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3218 out + 12, outsize + 12, svg_p->restart);
3220 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3221 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3222 out + 13, outsize + 13, svg_p->restart);
3225 if (action & F_END) {
3226 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3227 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3229 /* Free remaining structures */
3230 free_graphs(out, outsize, spmin, spmax);
3235 ***************************************************************************
3236 * Display ICMPv4 traffic errors statistics in SVG.
3239 * @a Activity structure with statistics.
3240 * @curr Index in array for current sample statistics.
3241 * @action Action expected from current function.
3242 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3243 * flag indicating that a restart record has been previously
3244 * found (.@restart) and time used for the X axis origin
3246 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3247 * @record_hdr Pointer on record header of current stats sample.
3248 ***************************************************************************
3250 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3251 unsigned long long itv, struct record_header *record_hdr)
3253 struct stats_net_eicmp
3254 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3255 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3256 int group[] = {2, 2, 2, 2, 2, 2};
3257 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3258 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3259 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3260 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3261 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3262 char *g_title[] = {"ierr/s", "oerr/s",
3263 "idstunr/s", "odstunr/s",
3264 "itmex/s", "otmex/s",
3265 "iparmpb/s", "oparmpb/s",
3266 "isrcq/s", "osrcq/s",
3267 "iredir/s", "oredir/s"};
3268 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3269 static double *spmin, *spmax;
3271 static int *outsize;
3273 if (action & F_BEGIN) {
3275 * Allocate arrays that will contain the graphs data
3276 * and the min/max values.
3278 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3281 if (action & F_MAIN) {
3282 /* Check for min/max values */
3283 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3284 itv, spmin, spmax, g_fields);
3287 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3288 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3289 out, outsize, svg_p->restart);
3291 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3292 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3293 out + 1, outsize + 1, svg_p->restart);
3295 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3296 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3297 out + 2, outsize + 2, svg_p->restart);
3299 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3300 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3301 out + 3, outsize + 3, svg_p->restart);
3303 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3304 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3305 out + 4, outsize + 4, svg_p->restart);
3307 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3308 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3309 out + 5, outsize + 5, svg_p->restart);
3311 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3312 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3313 out + 6, outsize + 6, svg_p->restart);
3315 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3316 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3317 out + 7, outsize + 7, svg_p->restart);
3319 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3320 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3321 out + 8, outsize + 8, svg_p->restart);
3323 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3324 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3325 out + 9, outsize + 9, svg_p->restart);
3327 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3328 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3329 out + 10, outsize + 10, svg_p->restart);
3331 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3332 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3333 out + 11, outsize + 11, svg_p->restart);
3336 if (action & F_END) {
3337 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3338 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3340 /* Free remaining structures */
3341 free_graphs(out, outsize, spmin, spmax);
3346 ***************************************************************************
3347 * Display TCPv4 traffic statistics in SVG.
3350 * @a Activity structure with statistics.
3351 * @curr Index in array for current sample statistics.
3352 * @action Action expected from current function.
3353 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3354 * flag indicating that a restart record has been previously
3355 * found (.@restart) and time used for the X axis origin
3357 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3358 * @record_hdr Pointer on record header of current stats sample.
3359 ***************************************************************************
3361 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3362 unsigned long long itv, struct record_header *record_hdr)
3364 struct stats_net_tcp
3365 *sntc = (struct stats_net_tcp *) a->buf[curr],
3366 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3367 int group[] = {2, 2};
3368 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3369 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3370 char *g_title[] = {"active/s", "passive/s",
3371 "iseg/s", "oseg/s"};
3372 int g_fields[] = {0, 1, 2, 3};
3373 static double *spmin, *spmax;
3375 static int *outsize;
3377 if (action & F_BEGIN) {
3379 * Allocate arrays that will contain the graphs data
3380 * and the min/max values.
3382 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3385 if (action & F_MAIN) {
3386 /* Check for min/max values */
3387 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3388 itv, spmin, spmax, g_fields);
3391 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3392 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3393 out, outsize, svg_p->restart);
3395 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3396 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3397 out + 1, outsize + 1, svg_p->restart);
3399 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3400 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3401 out + 2, outsize + 2, svg_p->restart);
3403 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3404 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3405 out + 3, outsize + 3, svg_p->restart);
3408 if (action & F_END) {
3409 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3410 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3412 /* Free remaining structures */
3413 free_graphs(out, outsize, spmin, spmax);
3418 ***************************************************************************
3419 * Display TCPv4 traffic errors statistics in SVG.
3422 * @a Activity structure with statistics.
3423 * @curr Index in array for current sample statistics.
3424 * @action Action expected from current function.
3425 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3426 * flag indicating that a restart record has been previously
3427 * found (.@restart) and time used for the X axis origin
3429 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3430 * @record_hdr Pointer on record header of current stats sample.
3431 ***************************************************************************
3433 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3434 unsigned long long itv, struct record_header *record_hdr)
3436 struct stats_net_etcp
3437 *snetc = (struct stats_net_etcp *) a->buf[curr],
3438 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3439 int group[] = {2, 3};
3440 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3441 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3442 char *g_title[] = {"atmptf/s", "estres/s",
3443 "retrans/s", "isegerr/s", "orsts/s"};
3444 int g_fields[] = {0, 1, 2, 3, 4};
3445 static double *spmin, *spmax;
3447 static int *outsize;
3449 if (action & F_BEGIN) {
3451 * Allocate arrays that will contain the graphs data
3452 * and the min/max values.
3454 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3457 if (action & F_MAIN) {
3458 /* Check for min/max values */
3459 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3460 itv, spmin, spmax, g_fields);
3463 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3464 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3465 out, outsize, svg_p->restart);
3467 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3468 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3469 out + 1, outsize + 1, svg_p->restart);
3471 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3472 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3473 out + 2, outsize + 2, svg_p->restart);
3475 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3476 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3477 out + 3, outsize + 3, svg_p->restart);
3479 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3480 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3481 out + 4, outsize + 4, svg_p->restart);
3484 if (action & F_END) {
3485 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3486 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3488 /* Free remaining structures */
3489 free_graphs(out, outsize, spmin, spmax);
3494 ***************************************************************************
3495 * Display UDPv4 traffic statistics in SVG.
3498 * @a Activity structure with statistics.
3499 * @curr Index in array for current sample statistics.
3500 * @action Action expected from current function.
3501 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3502 * flag indicating that a restart record has been previously
3503 * found (.@restart) and time used for the X axis origin
3505 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3506 * @record_hdr Pointer on record header of current stats sample.
3507 ***************************************************************************
3509 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3510 unsigned long long itv, struct record_header *record_hdr)
3512 struct stats_net_udp
3513 *snuc = (struct stats_net_udp *) a->buf[curr],
3514 *snup = (struct stats_net_udp *) a->buf[!curr];
3515 int group[] = {2, 2};
3516 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3517 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3518 char *g_title[] = {"idgm/s", "odgm/s",
3519 "noport/s", "idgmerr/s"};
3520 int g_fields[] = {0, 1, 2, 3};
3521 static double *spmin, *spmax;
3523 static int *outsize;
3525 if (action & F_BEGIN) {
3527 * Allocate arrays that will contain the graphs data
3528 * and the min/max values.
3530 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3533 if (action & F_MAIN) {
3534 /* Check for min/max values */
3535 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3536 itv, spmin, spmax, g_fields);
3539 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3540 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3541 out, outsize, svg_p->restart);
3543 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3544 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3545 out + 1, outsize + 1, svg_p->restart);
3547 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3548 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3549 out + 2, outsize + 2, svg_p->restart);
3551 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3552 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3553 out + 3, outsize + 3, svg_p->restart);
3556 if (action & F_END) {
3557 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3558 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3560 /* Free remaining structures */
3561 free_graphs(out, outsize, spmin, spmax);
3566 ***************************************************************************
3567 * Display IPV6 socket statistics in SVG.
3570 * @a Activity structure with statistics.
3571 * @curr Index in array for current sample statistics.
3572 * @action Action expected from current function.
3573 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3574 * flag indicating that a restart record has been previously
3575 * found (.@restart) and time used for the X axis origin
3577 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3578 * @record_hdr Pointer on record header of current stats sample.
3579 ***************************************************************************
3581 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3582 unsigned long long itv, struct record_header *record_hdr)
3584 struct stats_net_sock6
3585 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3587 int g_type[] = {SVG_LINE_GRAPH};
3588 char *title[] = {"IPv6 sockets statistics"};
3589 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3590 int g_fields[] = {0, 1, 2, 3};
3591 static double *spmin, *spmax;
3593 static int *outsize;
3595 if (action & F_BEGIN) {
3597 * Allocate arrays that will contain the graphs data
3598 * and the min/max values.
3600 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3603 if (action & F_MAIN) {
3604 /* Check for min/max values */
3605 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3606 itv, spmin, spmax, g_fields);
3608 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3609 (unsigned long long) snsc->tcp6_inuse,
3610 out, outsize, svg_p->restart);
3612 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3613 (unsigned long long) snsc->udp6_inuse,
3614 out + 1, outsize + 1, svg_p->restart);
3616 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3617 (unsigned long long) snsc->raw6_inuse,
3618 out + 2, outsize + 2, svg_p->restart);
3620 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3621 (unsigned long long) snsc->frag6_inuse,
3622 out + 3, outsize + 3, svg_p->restart);
3625 if (action & F_END) {
3626 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3627 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3629 /* Free remaining structures */
3630 free_graphs(out, outsize, spmin, spmax);
3635 ***************************************************************************
3636 * Display IPv6 traffic statistics in SVG.
3639 * @a Activity structure with statistics.
3640 * @curr Index in array for current sample statistics.
3641 * @action Action expected from current function.
3642 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3643 * flag indicating that a restart record has been previously
3644 * found (.@restart) and time used for the X axis origin
3646 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3647 * @record_hdr Pointer on record header of current stats sample.
3648 ***************************************************************************
3650 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3651 unsigned long long itv, struct record_header *record_hdr)
3653 struct stats_net_ip6
3654 *snic = (struct stats_net_ip6 *) a->buf[curr],
3655 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3656 int group[] = {4, 2, 2, 2};
3657 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3659 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3660 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3661 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3662 "asmrq6/s", "asmok6/s",
3663 "imcpck6/s", "omcpck6/s",
3664 "fragok6/s", "fragcr6/s"};
3665 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3666 static double *spmin, *spmax;
3668 static int *outsize;
3670 if (action & F_BEGIN) {
3672 * Allocate arrays that will contain the graphs data
3673 * and the min/max values.
3675 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3678 if (action & F_MAIN) {
3679 /* Check for min/max values */
3680 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3681 itv, spmin, spmax, g_fields);
3684 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3685 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3686 out, outsize, svg_p->restart);
3688 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3689 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3690 out + 1, outsize + 1, svg_p->restart);
3692 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3693 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3694 out + 2, outsize + 2, svg_p->restart);
3696 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3697 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3698 out + 3, outsize + 3, svg_p->restart);
3700 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3701 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3702 out + 4, outsize + 4, svg_p->restart);
3704 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3705 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3706 out + 5, outsize + 5, svg_p->restart);
3708 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3709 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3710 out + 6, outsize + 6, svg_p->restart);
3712 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3713 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3714 out + 7, outsize + 7, svg_p->restart);
3716 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3717 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3718 out + 8, outsize + 8, svg_p->restart);
3720 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3721 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3722 out + 9, outsize + 9, svg_p->restart);
3725 if (action & F_END) {
3726 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3727 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3729 /* Free remaining structures */
3730 free_graphs(out, outsize, spmin, spmax);
3735 ***************************************************************************
3736 * Display IPv6 traffic errors statistics in SVG.
3739 * @a Activity structure with statistics.
3740 * @curr Index in array for current sample statistics.
3741 * @action Action expected from current function.
3742 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3743 * flag indicating that a restart record has been previously
3744 * found (.@restart) and time used for the X axis origin
3746 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3747 * @record_hdr Pointer on record header of current stats sample.
3748 ***************************************************************************
3750 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3751 unsigned long long itv, struct record_header *record_hdr)
3753 struct stats_net_eip6
3754 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3755 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3756 int group[] = {4, 2, 2, 3};
3757 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3759 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3760 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3761 "IPv6 traffic errors statistics (5)"};
3762 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3763 "idisc6/s", "odisc6/s",
3764 "inort6/s", "onort6/s",
3765 "asmf6/s", "fragf6/s", "itrpck6/s"};
3766 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3767 static double *spmin, *spmax;
3769 static int *outsize;
3771 if (action & F_BEGIN) {
3773 * Allocate arrays that will contain the graphs data
3774 * and the min/max values.
3776 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3779 if (action & F_MAIN) {
3780 /* Check for min/max values */
3781 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3782 itv, spmin, spmax, g_fields);
3785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3786 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3787 out, outsize, svg_p->restart);
3789 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3790 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3791 out + 1, outsize + 1, svg_p->restart);
3793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3794 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3795 out + 2, outsize + 2, svg_p->restart);
3797 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3798 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3799 out + 3, outsize + 3, svg_p->restart);
3801 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3802 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3803 out + 4, outsize + 4, svg_p->restart);
3805 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3806 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3807 out + 5, outsize + 5, svg_p->restart);
3809 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3810 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3811 out + 6, outsize + 6, svg_p->restart);
3813 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3814 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3815 out + 7, outsize + 7, svg_p->restart);
3817 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3818 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3819 out + 8, outsize + 8, svg_p->restart);
3821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3822 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3823 out + 9, outsize + 9, svg_p->restart);
3825 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3826 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3827 out + 10, outsize + 10, svg_p->restart);
3830 if (action & F_END) {
3831 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3832 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3834 /* Free remaining structures */
3835 free_graphs(out, outsize, spmin, spmax);
3840 ***************************************************************************
3841 * Display ICMPv6 traffic statistics in SVG.
3844 * @a Activity structure with statistics.
3845 * @curr Index in array for current sample statistics.
3846 * @action Action expected from current function.
3847 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3848 * flag indicating that a restart record has been previously
3849 * found (.@restart) and time used for the X axis origin
3851 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3852 * @record_hdr Pointer on record header of current stats sample.
3853 ***************************************************************************
3855 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3856 unsigned long long itv, struct record_header *record_hdr)
3858 struct stats_net_icmp6
3859 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3860 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3861 int group[] = {2, 3, 5, 3, 4};
3862 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3863 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3864 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3865 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3866 "ICMPv6 traffic statistics (5)"};
3867 char *g_title[] = {"imsg6/s", "omsg6/s",
3868 "iech6/s", "iechr6/s", "oechr6/s",
3869 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3870 "irtsol6/s", "ortsol6/s", "irtad6/s",
3871 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3872 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3873 static double *spmin, *spmax;
3875 static int *outsize;
3877 if (action & F_BEGIN) {
3879 * Allocate arrays that will contain the graphs data
3880 * and the min/max values.
3882 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3885 if (action & F_MAIN) {
3886 /* Check for min/max values */
3887 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3888 itv, spmin, spmax, g_fields);
3891 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3892 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3893 out, outsize, svg_p->restart);
3895 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3896 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3897 out + 1, outsize + 1, svg_p->restart);
3899 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3900 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3901 out + 2, outsize + 2, svg_p->restart);
3903 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3904 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3905 out + 3, outsize + 3, svg_p->restart);
3907 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3908 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3909 out + 4, outsize + 4, svg_p->restart);
3911 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3912 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3913 out + 5, outsize + 5, svg_p->restart);
3915 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3916 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3917 out + 6, outsize + 6, svg_p->restart);
3919 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3920 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3921 out + 7, outsize + 7, svg_p->restart);
3923 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3924 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3925 out + 8, outsize + 8, svg_p->restart);
3927 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3928 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3929 out + 9, outsize + 9, svg_p->restart);
3931 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3932 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3933 out + 10, outsize + 10, svg_p->restart);
3935 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3936 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3937 out + 11, outsize + 11, svg_p->restart);
3939 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3940 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3941 out + 12, outsize + 12, svg_p->restart);
3943 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3944 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
3945 out + 13, outsize + 13, svg_p->restart);
3947 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3948 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3949 out + 14, outsize + 14, svg_p->restart);
3951 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3952 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3953 out + 15, outsize + 15, svg_p->restart);
3955 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3956 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3957 out + 16, outsize + 16, svg_p->restart);
3960 if (action & F_END) {
3961 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3962 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3964 /* Free remaining structures */
3965 free_graphs(out, outsize, spmin, spmax);
3970 ***************************************************************************
3971 * Display ICMPv6 traffic errors statistics in SVG.
3974 * @a Activity structure with statistics.
3975 * @curr Index in array for current sample statistics.
3976 * @action Action expected from current function.
3977 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3978 * flag indicating that a restart record has been previously
3979 * found (.@restart) and time used for the X axis origin
3981 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3982 * @record_hdr Pointer on record header of current stats sample.
3983 ***************************************************************************
3985 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3986 unsigned long long itv, struct record_header *record_hdr)
3988 struct stats_net_eicmp6
3989 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3990 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3991 int group[] = {1, 2, 2, 2, 2, 2};
3992 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3993 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3994 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
3995 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
3996 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
3997 char *g_title[] = {"ierr6/s",
3998 "idtunr6/s", "odtunr6/s",
3999 "itmex6/s", "otmex6/s",
4000 "iprmpb6/s", "oprmpb6/s",
4001 "iredir6/s", "oredir6/s",
4002 "ipck2b6/s", "opck2b6/s"};
4003 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4004 static double *spmin, *spmax;
4006 static int *outsize;
4008 if (action & F_BEGIN) {
4010 * Allocate arrays that will contain the graphs data
4011 * and the min/max values.
4013 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4016 if (action & F_MAIN) {
4017 /* Check for min/max values */
4018 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4019 itv, spmin, spmax, g_fields);
4022 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4023 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4024 out, outsize, svg_p->restart);
4026 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4027 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4028 out + 1, outsize + 1, svg_p->restart);
4030 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4031 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4032 out + 2, outsize + 2, svg_p->restart);
4034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4035 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4036 out + 3, outsize + 3, svg_p->restart);
4038 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4039 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4040 out + 4, outsize + 4, svg_p->restart);
4042 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4043 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4044 out + 5, outsize + 5, svg_p->restart);
4046 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4047 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4048 out + 6, outsize + 6, svg_p->restart);
4050 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4051 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4052 out + 7, outsize + 7, svg_p->restart);
4054 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4055 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4056 out + 8, outsize + 8, svg_p->restart);
4058 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4059 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4060 out + 9, outsize + 9, svg_p->restart);
4062 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4063 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4064 out + 10, outsize + 10, svg_p->restart);
4067 if (action & F_END) {
4068 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4069 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4071 /* Free remaining structures */
4072 free_graphs(out, outsize, spmin, spmax);
4077 ***************************************************************************
4078 * Display UDPv6 traffic statistics in SVG.
4081 * @a Activity structure with statistics.
4082 * @curr Index in array for current sample statistics.
4083 * @action Action expected from current function.
4084 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4085 * flag indicating that a restart record has been previously
4086 * found (.@restart) and time used for the X axis origin
4088 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4089 * @record_hdr Pointer on record header of current stats sample.
4090 ***************************************************************************
4092 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4093 unsigned long long itv, struct record_header *record_hdr)
4095 struct stats_net_udp6
4096 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4097 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4098 int group[] = {2, 2};
4099 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4100 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4101 char *g_title[] = {"idgm6/s", "odgm6/s",
4102 "noport6/s", "idgmer6/s"};
4103 int g_fields[] = {0, 1, 2, 3};
4104 static double *spmin, *spmax;
4106 static int *outsize;
4108 if (action & F_BEGIN) {
4110 * Allocate arrays that will contain the graphs data
4111 * and the min/max values.
4113 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4116 if (action & F_MAIN) {
4117 /* Check for min/max values */
4118 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4119 itv, spmin, spmax, g_fields);
4122 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4123 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4124 out, outsize, svg_p->restart);
4126 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4127 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4128 out + 1, outsize + 1, svg_p->restart);
4130 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4131 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4132 out + 2, outsize + 2, svg_p->restart);
4134 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4135 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4136 out + 3, outsize + 3, svg_p->restart);
4139 if (action & F_END) {
4140 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4141 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4143 /* Free remaining structures */
4144 free_graphs(out, outsize, spmin, spmax);
4149 ***************************************************************************
4150 * Display CPU frequency statistics in SVG.
4153 * @a Activity structure with statistics.
4154 * @curr Index in array for current sample statistics.
4155 * @action Action expected from current function.
4156 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4157 * flag indicating that a restart record has been previously
4158 * found (.@restart) and time used for the X axis origin
4160 * @itv Interval of time in 1/100th of a second (unused here).
4161 * @record_hdr Pointer on record header of current stats sample.
4162 ***************************************************************************
4164 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4165 unsigned long long itv, struct record_header *record_hdr)
4167 struct stats_pwr_cpufreq *spc, *spp;
4169 int g_type[] = {SVG_LINE_GRAPH};
4170 char *title[] = {"CPU clock frequency"};
4171 char *g_title[] = {"MHz"};
4172 static double *spmin, *spmax;
4174 static int *outsize;
4178 if (action & F_BEGIN) {
4180 * Allocate arrays that will contain the graphs data
4181 * and the min/max values.
4183 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4186 if (action & F_MAIN) {
4188 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4190 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4191 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4193 /* Should current CPU (including CPU "all") be displayed? */
4194 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4199 * Note: Don't skip offline CPU here as it is needed
4200 * to make the graph go though 0.
4204 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4205 ((double) spp->cpufreq) / 100,
4206 ((double) spc->cpufreq) / 100,
4207 out + i, outsize + i, svg_p->restart, svg_p->dt,
4208 spmin + i, spmax + i);
4212 if (action & F_END) {
4215 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
4217 /* Should current CPU (including CPU "all") be displayed? */
4218 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4223 /* This is CPU "all" */
4224 strcpy(item_name, "all");
4228 * If the maximum frequency reached by the CPU is 0, then
4229 * the CPU has been offline on the whole period.
4230 * => Don't display it.
4232 if (*(spmax + i) == 0)
4235 sprintf(item_name, "%d", i - 1);
4238 if (draw_activity_graphs(a->g_nr, g_type,
4239 title, g_title, item_name, group,
4240 spmin + i, spmax + i, out + i, outsize + i,
4241 svg_p, record_hdr, i, a->id, xid)) {
4246 /* Free remaining structures */
4247 free_graphs(out, outsize, spmin, spmax);
4252 ***************************************************************************
4253 * Display fan statistics in SVG.
4256 * @a Activity structure with statistics.
4257 * @curr Index in array for current sample statistics.
4258 * @action Action expected from current function.
4259 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4260 * flag indicating that a restart record has been previously
4261 * found (.@restart) and time used for the X axis origin
4263 * @itv Interval of time in 1/100th of a second (unused here).
4264 * @record_hdr Pointer on record header of current stats sample.
4265 ***************************************************************************
4267 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4268 unsigned long long itv, struct record_header *record_hdr)
4270 struct stats_pwr_fan *spc, *spp;
4272 int g_type[] = {SVG_LINE_GRAPH};
4273 char *title[] = {"Fans speed"};
4274 char *g_title[] = {"~rpm"};
4275 static double *spmin, *spmax;
4277 static int *outsize;
4278 char item_name[MAX_SENSORS_DEV_LEN + 8];
4281 if (action & F_BEGIN) {
4283 * Allocate arrays that will contain the graphs data
4284 * and the min/max values.
4286 out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
4289 if (action & F_MAIN) {
4291 for (i = 0; i < a->nr[curr]; i++) {
4293 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4294 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4297 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4300 out + i, outsize + i, svg_p->restart, svg_p->dt,
4301 spmin + i, spmax + i);
4305 if (action & F_END) {
4308 for (i = 0; i < a->item_list_sz; i++) {
4310 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4312 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4313 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4315 if (draw_activity_graphs(a->g_nr, g_type,
4316 title, g_title, item_name, group,
4317 spmin + i, spmax + i, out + i, outsize + i,
4318 svg_p, record_hdr, FALSE, a->id, xid)) {
4323 /* Free remaining structures */
4324 free_graphs(out, outsize, spmin, spmax);
4329 ***************************************************************************
4330 * Display temperature statistics in SVG.
4333 * @a Activity structure with statistics.
4334 * @curr Index in array for current sample statistics.
4335 * @action Action expected from current function.
4336 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4337 * flag indicating that a restart record has been previously
4338 * found (.@restart) and time used for the X axis origin
4340 * @itv Interval of time in 1/100th of a second (unused here).
4341 * @record_hdr Pointer on record header of current stats sample.
4342 ***************************************************************************
4344 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4345 unsigned long long itv, struct record_header *record_hdr)
4347 struct stats_pwr_temp *spc;
4348 int group[] = {1, 1};
4349 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4350 char *title[] = {"Devices temperature (1)",
4351 "Devices temperature (2)"};
4352 char *g_title[] = {"~degC",
4354 static double *spmin, *spmax;
4356 static int *outsize;
4357 char item_name[MAX_SENSORS_DEV_LEN + 8];
4361 if (action & F_BEGIN) {
4363 * Allocate arrays that will contain the graphs data
4364 * and the min/max values.
4366 out = allocate_graph_lines(2 * a->item_list_sz, &outsize, &spmin, &spmax);
4369 if (action & F_MAIN) {
4370 /* For each temperature sensor */
4371 for (i = 0; i < a->nr[curr]; i++) {
4373 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4375 /* Look for min/max values */
4376 if (spc->temp < *(spmin + 2 * i)) {
4377 *(spmin + 2 * i) = spc->temp;
4379 if (spc->temp > *(spmax + 2 * i)) {
4380 *(spmax + 2 * i) = spc->temp;
4382 tval = (spc->temp_max - spc->temp_min) ?
4383 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4385 if (tval < *(spmin + 2 * i + 1)) {
4386 *(spmin + 2 * i + 1) = tval;
4388 if (tval > *(spmax + 2 * i + 1)) {
4389 *(spmax + 2 * i + 1) = tval;
4393 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4395 out + 2 * i, outsize + 2 * i, svg_p->restart);
4397 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4399 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4403 if (action & F_END) {
4406 for (i = 0; i < a->item_list_sz; i++) {
4408 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4410 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4411 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4413 if (draw_activity_graphs(a->g_nr, g_type,
4414 title, g_title, item_name, group,
4415 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4416 svg_p, record_hdr, FALSE, a->id, xid)) {
4421 /* Free remaining structures */
4422 free_graphs(out, outsize, spmin, spmax);
4427 ***************************************************************************
4428 * Display voltage inputs statistics in SVG.
4431 * @a Activity structure with statistics.
4432 * @curr Index in array for current sample statistics.
4433 * @action Action expected from current function.
4434 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4435 * flag indicating that a restart record has been previously
4436 * found (.@restart) and time used for the X axis origin
4438 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4439 * @record_hdr Pointer on record header of current stats sample.
4440 ***************************************************************************
4442 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4443 unsigned long long itv, struct record_header *record_hdr)
4445 struct stats_pwr_in *spc;
4446 int group[] = {1, 1};
4447 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4448 char *title[] = {"Voltage inputs statistics (1)",
4449 "Voltage inputs statistics (2)"};
4450 char *g_title[] = {"inV",
4452 static double *spmin, *spmax;
4454 static int *outsize;
4455 char item_name[MAX_SENSORS_DEV_LEN + 8];
4459 if (action & F_BEGIN) {
4461 * Allocate arrays that will contain the graphs data
4462 * and the min/max values.
4464 out = allocate_graph_lines(2 * a->item_list_sz, &outsize, &spmin, &spmax);
4467 if (action & F_MAIN) {
4468 /* For each voltage input sensor */
4469 for (i = 0; i < a->nr[curr]; i++) {
4471 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4473 /* Look for min/max values */
4474 if (spc->in < *(spmin + 2 * i)) {
4475 *(spmin + 2 * i) = spc->in;
4477 if (spc->in > *(spmax + 2 * i)) {
4478 *(spmax + 2 * i) = spc->in;
4480 tval = (spc->in_max - spc->in_min) ?
4481 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4483 if (tval < *(spmin + 2 * i + 1)) {
4484 *(spmin + 2 * i + 1) = tval;
4486 if (tval > *(spmax + 2 * i + 1)) {
4487 *(spmax + 2 * i + 1) = tval;
4491 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4493 out + 2 * i, outsize + 2 * i, svg_p->restart);
4495 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4497 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4501 if (action & F_END) {
4504 for (i = 0; i < a->item_list_sz; i++) {
4506 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4508 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4509 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4511 if (draw_activity_graphs(a->g_nr, g_type,
4512 title, g_title, item_name, group,
4513 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4514 svg_p, record_hdr, FALSE, a->id, xid)) {
4519 /* Free remaining structures */
4520 free_graphs(out, outsize, spmin, spmax);
4525 ***************************************************************************
4526 * Display huge pages statistics in SVG.
4529 * @a Activity structure with statistics.
4530 * @curr Index in array for current sample statistics.
4531 * @action Action expected from current function.
4532 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4533 * flag indicating that a restart record has been previously
4534 * found (.@restart) and time used for the X axis origin
4536 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4537 * @record_hdr Pointer on record header of current stats sample.
4538 ***************************************************************************
4540 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4541 unsigned long long itv, struct record_header *record_hdr)
4544 *smc = (struct stats_huge *) a->buf[curr];
4545 int group[] = {4, 1};
4546 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4547 char *title[] = {"Huge pages utilization (1)",
4548 "Huge pages utilization (2)"};
4549 char *g_title[] = {"~kbhugfree", "~kbhugused", "~kbhugrsvd", "~kbhugsurp",
4551 int g_fields[] = {0, 5, 2, 3};
4552 static double *spmin, *spmax;
4554 static int *outsize;
4557 if (action & F_BEGIN) {
4559 * Allocate arrays that will contain the graphs data
4560 * and the min/max values.
4561 * Allocate one additional array (#5) to save min/max
4562 * values for tlhkb (unused).
4564 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
4567 if (action & F_MAIN) {
4568 /* Check for min/max values */
4569 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
4570 itv, spmin, spmax, g_fields);
4572 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4573 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4575 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4576 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4578 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4579 if (tval < *(spmin + 4)) {
4580 *(spmin + 4) = tval;
4582 if (tval > *(spmax + 4)) {
4583 *(spmax + 4) = tval;
4587 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4588 (unsigned long long) smc->frhkb,
4589 out, outsize, svg_p->restart);
4591 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4592 (unsigned long long) smc->tlhkb - smc->frhkb,
4593 out + 1, outsize + 1, svg_p->restart);
4595 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4596 (unsigned long long) smc->rsvdhkb,
4597 out + 2, outsize + 2, svg_p->restart);
4599 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4600 (unsigned long long) smc->surphkb,
4601 out + 3, outsize + 3, svg_p->restart);
4603 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4605 out + 4, outsize + 4, svg_p->dt);
4608 if (action & F_END) {
4609 draw_activity_graphs(a->g_nr, g_type,
4610 title, g_title, NULL, group,
4611 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4613 /* Free remaining structures */
4614 free_graphs(out, outsize, spmin, spmax);
4619 ***************************************************************************
4620 * Display filesystem statistics in SVG.
4623 * @a Activity structure with statistics.
4624 * @curr Index in array for current sample statistics.
4625 * @action Action expected from current function.
4626 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4627 * flag indicating that a restart record has been previously
4628 * found (.@restart) and time used for the X axis origin
4630 * @itv Interval of time in 1/100th of a second (unused here).
4631 * @record_hdr Pointer on record header of current stats sample.
4632 ***************************************************************************
4634 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4635 unsigned long long itv, struct record_header *record_hdr)
4637 struct stats_filesystem *sfc, *sfp;
4638 int group[] = {2, 2, 2, 1};
4639 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4640 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4641 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4642 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4643 char *g_title[] = {"~MBfsfree", "~MBfsused",
4644 "%ufsused", "%fsused",
4645 "Ifree/1000", "Iused/1000",
4647 static double *spmin, *spmax;
4649 static int *outsize;
4652 int i, k, pos, restart;
4654 if (action & F_BEGIN) {
4656 * Allocate arrays (#0..6) that will contain the graphs data
4657 * and the min/max values.
4658 * Also allocate two additional arrays (#7..8) for each filesystem:
4659 * out + 7 will contain the filesystem name,
4660 * out + 8 will contain the mount point.
4662 out = allocate_graph_lines(9 * a->item_list_sz, &outsize, &spmin, &spmax);
4665 if (action & F_MAIN) {
4666 /* For each filesystem structure */
4667 for (i = 0; i < a->nr[curr]; i++) {
4668 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4670 if (a->item_list != NULL) {
4671 /* A list of devices has been entered on the command line */
4672 if (!search_list_item(a->item_list,
4673 DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name))
4674 /* Device not found */
4678 /* Look for corresponding graph */
4679 for (k = 0; k < a->item_list_sz; k++) {
4680 item_name = *(out + k * 9 + 7);
4681 if (!strcmp(sfc->fs_name, item_name))
4686 if (k == a->item_list_sz) {
4687 /* Graph not found: Look for first free entry */
4688 for (k = 0; k < a->item_list_sz; k++) {
4689 item_name = *(out + k * 9 + 7);
4690 if (!strcmp(item_name, ""))
4693 if (k == a->item_list_sz) {
4694 /* No free graph entry: Ignore it (should never happen) */
4696 fprintf(stderr, "%s: Name=%s\n",
4697 __FUNCTION__, sfc->fs_name);
4705 item_name = *(out + pos + 7);
4706 if (!item_name[0]) {
4707 /* Save filesystem name and mount point (if not already done) */
4708 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4709 item_name[CHUNKSIZE - 1] = '\0';
4710 item_name = *(out + pos + 8);
4711 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4712 item_name[CHUNKSIZE - 1] = '\0';
4716 for (k = 0; k < a->nr[!curr]; k++) {
4717 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4718 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4719 /* Filesystem found in previous sample */
4720 restart = svg_p->restart;
4724 /* Check for min/max values */
4726 /* Compute fsfree min/max values */
4727 tval = (double) sfc->f_bfree;
4728 if (tval > *(spmax + pos)) {
4729 *(spmax + pos) = tval;
4731 if (tval < *(spmin + pos)) {
4732 *(spmin + pos) = tval;
4734 /* Compute fsused min/max values */
4735 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4736 if (tval > *(spmax + pos + 1)) {
4737 *(spmax + pos + 1) = tval;
4739 if (tval < *(spmin + pos + 1)) {
4740 *(spmin + pos + 1) = tval;
4742 /* Compute %ufsused min/max values */
4743 tval = sfc->f_blocks ?
4744 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4745 if (tval > *(spmax + pos + 2)) {
4746 *(spmax + pos + 2) = tval;
4748 if (tval < *(spmin + pos + 2)) {
4749 *(spmin + pos + 2) = tval;
4751 /* Compute %fsused min/max values */
4752 tval = sfc->f_blocks ?
4753 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4754 if (tval > *(spmax + pos + 3)) {
4755 *(spmax + pos + 3) = tval;
4757 if (tval < *(spmin + pos + 3)) {
4758 *(spmin + pos + 3) = tval;
4760 /* Compute Ifree min/max values */
4761 tval = (double) sfc->f_ffree;
4762 if (tval > *(spmax + pos + 4)) {
4763 *(spmax + pos + 4) = tval;
4765 if (tval < *(spmin + pos + 4)) {
4766 *(spmin + pos + 4) = tval;
4768 /* Compute Iused min/max values */
4769 tval = (double) (sfc->f_files - sfc->f_ffree);
4770 if (tval > *(spmax + pos + 5)) {
4771 *(spmax + pos + 5) = tval;
4773 if (tval < *(spmin + pos + 5)) {
4774 *(spmin + pos + 5) = tval;
4776 /* Compute %Iused min/max values */
4777 tval = sfc->f_files ?
4778 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4779 if (tval > *(spmax + pos + 6)) {
4780 *(spmax + pos + 6) = tval;
4782 if (tval < *(spmin + pos + 6)) {
4783 *(spmin + pos + 6) = tval;
4787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4788 (double) sfc->f_bfree / 1024 / 1024,
4789 out + pos, outsize + pos, restart);
4791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4792 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4793 out + pos + 1, outsize + pos + 1, restart);
4795 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4798 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4799 out + pos + 2, outsize + pos + 2, svg_p->dt);
4801 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4804 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4805 out + pos + 3, outsize + pos + 3, svg_p->dt);
4807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4808 ((double) sfc->f_ffree) / 1000,
4809 out + pos + 4, outsize + pos + 4, restart);
4811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4812 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4813 out + pos + 5, outsize + pos + 5, restart);
4815 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4818 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4819 out + pos + 6, outsize + pos + 6, svg_p->dt);
4823 if (action & F_END) {
4826 for (i = 0; i < a->item_list_sz; i++) {
4828 /* Check if there is something to display */
4833 /* Conversion B -> MB and inodes/1000 */
4834 for (k = 0; k < 2; k++) {
4835 *(spmin + pos + k) /= (1024 * 1024);
4836 *(spmax + pos + k) /= (1024 * 1024);
4837 *(spmin + pos + 4 + k) /= 1000;
4838 *(spmax + pos + 4 + k) /= 1000;
4841 if (DISPLAY_MOUNT(a->opt_flags)) {
4842 item_name = *(out + pos + 8);
4845 item_name = *(out + pos + 7);
4848 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4849 spmin + pos, spmax + pos, out + pos, outsize + pos,
4850 svg_p, record_hdr, FALSE, a->id, xid)) {
4855 /* Free remaining structures */
4856 free_graphs(out, outsize, spmin, spmax);
4861 ***************************************************************************
4862 * Display Fibre Channel HBA statistics in SVG.
4865 * @a Activity structure with statistics.
4866 * @curr Index in array for current sample statistics.
4867 * @action Action expected from current function.
4868 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4869 * flag indicating that a restart record has been previously
4870 * found (.@restart) and time used for the X axis origin
4872 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4873 * @record_hdr Pointer on record header of current stats sample.
4874 ***************************************************************************
4876 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4877 unsigned long long itv, struct record_header *record_hdr)
4879 struct stats_fchost *sfcc, *sfcp;
4880 int group[] = {2, 2};
4881 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4882 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4883 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4884 "fch_rxw/s", "fch_txw/s"};
4885 int g_fields[] = {0, 1, 2, 3};
4886 static double *spmin, *spmax;
4888 static int *outsize;
4890 int i, j, j0, k, found, pos, restart, *unregistered;
4892 if (action & F_BEGIN) {
4894 * Allocate arrays (#0..3) that will contain the graphs data
4895 * and the min/max values.
4896 * Also allocate one additional array (#4) that will contain
4897 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4898 * has either still not been registered, or has been unregistered
4901 out = allocate_graph_lines(5 * a->item_list_sz, &outsize, &spmin, &spmax);
4904 if (action & F_MAIN) {
4905 restart = svg_p->restart;
4907 * Mark previously registered interfaces as now
4908 * possibly unregistered for all graphs.
4910 for (k = 0; k < a->item_list_sz; k++) {
4911 unregistered = outsize + k * 5 + 4;
4912 if (*unregistered == FALSE) {
4913 *unregistered = MAYBE;
4917 /* For each FC HBA */
4918 for (i = 0; i < a->nr[curr]; i++) {
4922 if (a->nr[!curr] > 0) {
4923 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4925 /* Look for corresponding graph */
4926 for (k = 0; k < a->item_list_sz; k++) {
4927 item_name = *(out + k * 5 + 4);
4928 if (!strcmp(sfcc->fchost_name, item_name))
4932 if (k == a->item_list_sz) {
4933 /* Graph not found: Look for first free entry */
4934 for (k = 0; k < a->item_list_sz; k++) {
4935 item_name = *(out + k * 5 + 4);
4936 if (!strcmp(item_name, ""))
4939 if (k == a->item_list_sz) {
4940 /* No free graph entry: Ignore it (should never happen) */
4942 fprintf(stderr, "%s: Name=%s\n",
4943 __FUNCTION__, sfcc->fchost_name);
4950 unregistered = outsize + pos + 4;
4952 /* Look for corresponding structure in previous iteration */
4955 if (j >= a->nr[!curr]) {
4956 j = a->nr[!curr] - 1;
4962 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4963 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4967 if (++j >= a->nr[!curr]) {
4978 * If current interface was marked as previously unregistered,
4979 * then set restart variable to TRUE so that the graph will be
4980 * discontinuous, and mark it as now registered.
4982 if (*unregistered == TRUE) {
4985 *unregistered = FALSE;
4987 item_name = *(out + pos + 4);
4988 if (!item_name[0]) {
4989 /* Save FC HBA name */
4990 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4991 item_name[CHUNKSIZE - 1] = '\0';
4994 /* Look for min/max values */
4995 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4996 itv, spmin + pos, spmax + pos, g_fields);
4999 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5000 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5001 out + pos, outsize + pos, restart);
5003 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5004 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5005 out + pos + 1, outsize + pos + 1, restart);
5007 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5008 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5009 out + pos + 2, outsize + pos + 2, restart);
5011 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5012 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5013 out + pos + 3, outsize + pos + 3, restart);
5016 /* Mark interfaces not seen here as now unregistered */
5017 for (k = 0; k < a->item_list_sz; k++) {
5018 unregistered = outsize + k * 5 + 4;
5019 if (*unregistered != FALSE) {
5020 *unregistered = TRUE;
5025 if (action & F_END) {
5026 for (i = 0; i < a->item_list_sz; i++) {
5028 /* Check if there is something to display */
5033 item_name = *(out + pos + 4);
5034 draw_activity_graphs(a->g_nr, g_type,
5035 title, g_title, item_name, group,
5036 spmin + pos, spmax + pos, out + pos, outsize + pos,
5037 svg_p, record_hdr, FALSE, a->id, i);
5040 /* Free remaining structures */
5041 free_graphs(out, outsize, spmin, spmax);
5046 ***************************************************************************
5047 * Display softnet statistics in SVG.
5050 * @a Activity structure with statistics.
5051 * @curr Index in array for current sample statistics.
5052 * @action Action expected from current function.
5053 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5054 * flag indicating that a restart record has been previously
5055 * found (.@restart) and time used for the X axis origin
5057 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5058 * @record_hdr Pointer on record header of current stats sample.
5059 ***************************************************************************
5061 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5062 unsigned long long itv, struct record_header *record_hdr)
5064 struct stats_softnet *ssnc, *ssnp, ssnczero;
5065 int group[] = {2, 3};
5066 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5067 char *title[] = {"Software-based network processing statistics (1)",
5068 "Software-based network processing statistics (2)"};
5069 char *g_title[] = {"total/s", "dropd/s",
5070 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5071 int g_fields[] = {0, 1, 2, 3, 4};
5072 static double *spmin, *spmax;
5074 static int *outsize;
5076 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5077 int i, pos, restart;
5079 if (action & F_BEGIN) {
5081 * Allocate arrays that will contain the graphs data
5082 * and the min/max values.
5084 out = allocate_graph_lines(5 * a->item_list_sz, &outsize, &spmin, &spmax);
5087 if (action & F_MAIN) {
5088 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5090 /* @nr[curr] cannot normally be greater than @nr_ini */
5091 if (a->nr[curr] > a->nr_ini) {
5092 a->nr_ini = a->nr[curr];
5095 /* Compute statistics for CPU "all" */
5096 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5099 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5100 restart = svg_p->restart;
5102 /* Should current CPU (including CPU "all") be displayed? */
5103 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5107 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5108 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5110 /* Is current CPU marked offline? */
5111 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5113 * Yes and it doesn't follow a RESTART record.
5114 * To add a discontinuity in graph, we simulate
5118 if (svg_p->restart) {
5120 * CPU is offline and it follows a real
5121 * RESTART record. Ignore its current value
5122 * (no previous sample).
5129 /* Check for min/max values */
5130 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5131 itv, spmin + pos, spmax + pos, g_fields);
5134 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5135 S_VALUE(ssnp->processed, ssnc->processed, itv),
5136 out + pos, outsize + pos, restart);
5138 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5139 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5140 out + pos + 1, outsize + pos + 1, restart);
5142 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5143 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5144 out + pos + 2, outsize + pos + 2, restart);
5146 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5147 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5148 out + pos + 3, outsize + pos + 3, restart);
5150 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5151 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5152 out + pos + 4, outsize + pos + 4, restart);
5156 if (action & F_END) {
5157 for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
5159 /* Should current CPU (including CPU "all") be displayed? */
5160 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5167 /* This is CPU "all" */
5168 strcpy(item_name, "all");
5171 sprintf(item_name, "%d", i - 1);
5174 draw_activity_graphs(a->g_nr, g_type,
5175 title, g_title, item_name, group,
5176 spmin + pos, spmax + pos, out + pos, outsize + pos,
5177 svg_p, record_hdr, FALSE, a->id, i);
5180 /* Free remaining structures */
5181 free_graphs(out, outsize, spmin, spmax);