2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016-2018 by Sebastien GODARD (sysstat <at> orange.fr)
5 ***************************************************************************
6 * This program is free software; you can redistribute it and/or modify it *
7 * under the terms of the GNU General Public License as published by the *
8 * Free Software Foundation; either version 2 of the License, or (at your *
9 * option) any later version. *
11 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * You should have received a copy of the GNU General Public License along *
17 * with this program; if not, write to the Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *
19 ***************************************************************************
30 #include "svg_stats.h"
35 #define _(string) gettext(string)
37 #define _(string) (string)
40 extern unsigned int flags;
41 extern struct sa_dlist *st_iface_list;
42 extern struct sa_dlist *st_dev_list;
43 extern struct sa_dlist *st_fs_list;
44 extern int dlst_iface_idx;
45 extern int dlst_dev_idx;
46 extern int dlst_fs_idx;
48 unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
49 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
50 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
51 0xcc3300, 0x50040f, 0xffffbf, 0x193d55};
52 #define SVG_COLORS_IDX_MASK 0x0f
55 ***************************************************************************
56 * Compare the values of a statistics sample with the max and min values
57 * already found in previous samples for this same activity. If some new
58 * min or max values are found, then save them.
59 * Assume values cannot be negative.
60 * The structure containing the statistics sample is composed of @llu_nr
61 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
62 * followed by @u_nr unsigned int fields.
65 * @types_nr Number of fields whose type is "long long", "long" and "int"
66 * composing the structure.
67 * @cs Pointer on current sample statistics structure.
68 * @ps Pointer on previous sample statistics structure (may be NULL).
69 * @itv Interval of time in 1/100th of a second.
70 * @spmin Array containing min values already found for this activity.
71 * @spmax Array containing max values already found for this activity.
72 * @g_fields Index in spmin/spmax arrays where extrema values for each
73 * activity metric will be saved. As a consequence spmin/spmax
74 * arrays may contain values in a different order than that of
75 * the fields in the statistics structure.
78 * @spmin Array containg the possible new min values for current activity.
79 * @spmax Array containg the possible new max values for current activity.
80 ***************************************************************************
82 void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
83 double *spmin, double *spmax, int g_fields[])
85 unsigned long long *lluc, *llup;
86 unsigned long *luc, *lup;
87 unsigned int *uc, *up;
91 /* Compare unsigned long long fields */
92 lluc = (unsigned long long *) cs;
93 llup = (unsigned long long *) ps;
94 for (i = 0; i < types_nr[0]; i++, m++) {
96 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
100 * If no pointer on previous sample has been given
101 * then the value is not a per-second one.
103 val = (double) *lluc;
105 if (val < *(spmin + g_fields[m])) {
106 *(spmin + g_fields[m]) = val;
108 if (val > *(spmax + g_fields[m])) {
109 *(spmax + g_fields[m]) = val;
111 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
113 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
117 /* Compare unsigned long fields */
118 luc = (unsigned long *) lluc;
119 lup = (unsigned long *) llup;
120 for (i = 0; i < types_nr[1]; i++, m++) {
122 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
127 if (val < *(spmin + g_fields[m])) {
128 *(spmin + g_fields[m]) = val;
130 if (val > *(spmax + g_fields[m])) {
131 *(spmax + g_fields[m]) = val;
133 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
135 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
139 /* Compare unsigned int fields */
140 uc = (unsigned int *) luc;
141 up = (unsigned int *) lup;
142 for (i = 0; i < types_nr[2]; i++, m++) {
144 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
149 if (val < *(spmin + g_fields[m])) {
150 *(spmin + g_fields[m]) = val;
152 if (val > *(spmax + g_fields[m])) {
153 *(spmax + g_fields[m]) = val;
155 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
157 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
163 ***************************************************************************
164 * Find the min and max values of all the graphs that will be drawn in the
165 * same view. The graphs have their own min and max values in
166 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
169 * @pos Position in array for the first graph extrema value.
170 * @n Number of graphs to scan.
171 * @spmin Array containing min values for graphs.
172 * @spmax Array containing max values for graphs.
175 * @gmin Global min value found.
176 * @gmax Global max value found.
177 ***************************************************************************
179 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
180 double *gmin, double *gmax)
184 *gmin = *(spmin + pos);
185 *gmax = *(spmax + pos);
187 for (i = 1; i < n; i++) {
188 if (*(spmin + pos + i) < *gmin) {
189 *gmin = *(spmin + pos + i);
191 if (*(spmax + pos + i) > *gmax) {
192 *gmax = *(spmax + pos + i);
198 ***************************************************************************
199 * Allocate arrays used to save graphs data, min and max values.
200 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
201 * array is returned. This is equivalent to "char data[][n]" where each
202 * element is of indeterminate size and will contain the graph data (eg.
203 * << path d="M12,14 L13,16..." ... >>.
204 * The size of element data[i] is given by outsize[i].
205 * Also allocate an array to save min values (equivalent to "double spmin[n]")
206 * and an array for max values (equivalent to "double spmax[n]").
209 * @n Number of graphs to draw for current activity.
212 * @outsize Array that will contain the sizes of each element in array
213 * of chars. Equivalent to "int outsize[n]" with
214 * outsize[n] = sizeof(data[][n]).
215 * @spmin Array that will contain min values for current activity.
216 * @spmax Array that will contain max values for current activity.
219 * Pointer on array of arrays of chars that will contain the graphs data.
221 * NB: @min and @max arrays contain values in the same order as the fields
222 * in the statistics structure.
223 ***************************************************************************
225 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
232 * Allocate an array of pointers. Each of these pointers will
233 * be an array of chars.
235 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
239 /* Allocate array that will contain the size of each array of chars */
240 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
244 /* Allocate array that will contain the min value of each graph */
245 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
249 /* Allocate array that will contain the max value of each graph */
250 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
254 /* Allocate arrays of chars that will contain graphs data */
255 for (i = 0; i < n; i++) {
256 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
261 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
262 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
263 *(*spmin + i) = DBL_MAX; /* Init min and max values */
264 *(*spmax + i) = -DBL_MAX;
271 ***************************************************************************
272 * Reallocate all the arrays used to save graphs data, min and max values.
273 * The new size is the double of the original one.
276 * @n Number of slots currently allocated.
277 * @out Current pointer on arrays containing the graphs data.
278 * @outsize Current pointer on array containing the size of each element
280 * @spmin Current pointer on array containing min values.
281 * @spmax Current pointer on array containing max values.
284 * @out New pointer on arrays containing the graphs data.
285 * @outsize New pointer on array containing the size of each element
287 * @spmin New pointer on array containing min values.
288 * @spmax New pointer on array containing max values.
289 ***************************************************************************
291 void reallocate_all_graph_lines(int n, char ***out, int **outsize,
292 double **spmin, double **spmax)
297 /* Reallocate all the arrays */
298 SREALLOC(*out, char *, n * sizeof(char *) * 2);
299 SREALLOC(*outsize, int, n * sizeof(int) * 2);
300 SREALLOC(*spmin, double, n * sizeof(double) * 2);
301 SREALLOC(*spmax, double, n * sizeof(double) * 2);
303 /* Allocate arrays of chars that will contain graphs data for the newly allocated slots */
304 for (i = 0; i < n; i++) {
305 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
309 *(*out + n + i) = out_p;
311 *(*outsize + n + i) = CHUNKSIZE;
312 *(*spmin + n + i) = DBL_MAX;
313 *(*spmax + n + i) = -DBL_MAX;
318 ***************************************************************************
319 * Save SVG code for current graph.
322 * @data SVG code to append to current graph definition.
323 * @out Pointer on array of chars for current graph definition.
324 * @outsize Size of array of chars for current graph definition.
327 * @out Pointer on array of chars for current graph definition that
328 * has been updated with the addition of current sample data.
329 * @outsize Array that containing the (possibly new) sizes of each
330 * element in array of chars.
331 ***************************************************************************
333 void save_svg_data(char *data, char **out, int *outsize)
339 /* Determine space left in array */
340 len = *outsize - strlen(out_p) - 1;
341 if (strlen(data) >= len) {
343 * If current array of chars doesn't have enough space left
344 * then reallocate it with CHUNKSIZE more bytes.
346 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
348 *outsize += CHUNKSIZE;
351 strncat(out_p, data, len);
355 ***************************************************************************
356 * Update line graph definition by appending current X,Y coordinates.
359 * @timetag Timestamp in seconds since the epoch for current sample
360 * stats. Will be used as X coordinate.
361 * @value Value of current sample metric. Will be used as Y coordinate.
362 * @out Pointer on array of chars for current graph definition.
363 * @outsize Size of array of chars for current graph definition.
364 * @restart Set to TRUE if a RESTART record has been read since the last
368 * @out Pointer on array of chars for current graph definition that
369 * has been updated with the addition of current sample data.
370 * @outsize Array that containing the (possibly new) sizes of each
371 * element in array of chars.
372 ***************************************************************************
374 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
379 /* Prepare additional graph definition data */
380 snprintf(data, 128, " %c%llu,%.2f", restart ? 'M' : 'L', timetag, value);
383 save_svg_data(data, out, outsize);
387 ***************************************************************************
388 * Update line graph definition by appending current X,Y coordinates. Use
389 * (unsigned long) integer values here.
392 * @timetag Timestamp in seconds since the epoch for current sample
393 * stats. Will be used as X coordinate.
394 * @value Value of current sample metric. Will be used as Y coordinate.
395 * @out Pointer on array of chars for current graph definition.
396 * @outsize Size of array of chars for current graph definition.
397 * @restart Set to TRUE if a RESTART record has been read since the last
401 * @out Pointer on array of chars for current graph definition that
402 * has been updated with the addition of current sample data.
403 * @outsize Array that containing the (possibly new) sizes of each
404 * element in array of chars.
405 ***************************************************************************
407 void lniappend(unsigned long long timetag, unsigned long long value, char **out,
408 int *outsize, int restart)
412 /* Prepare additional graph definition data */
413 snprintf(data, 128, " %c%llu,%llu", restart ? 'M' : 'L', timetag, value);
416 save_svg_data(data, out, outsize);
420 ***************************************************************************
421 * Update bar graph definition by adding a new rectangle.
424 * @timetag Timestamp in seconds since the epoch for current sample
425 * stats. Will be used as X coordinate.
426 * @value Value of current sample metric. Will be used as rectangle
428 * @offset Offset for Y coordinate.
429 * @out Pointer on array of chars for current graph definition.
430 * @outsize Size of array of chars for current graph definition.
431 * @dt Interval of time in seconds between current and previous
435 * @out Pointer on array of chars for current graph definition that
436 * has been updated with the addition of current sample data.
437 * @outsize Array that containing the (possibly new) sizes of each
438 * element in array of chars.
439 ***************************************************************************
441 void brappend(unsigned long long timetag, double offset, double value, char **out,
442 int *outsize, unsigned long long dt)
446 /* Prepare additional graph definition data */
447 if ((value == 0.0) || (dt == 0))
448 /* Don't draw a flat rectangle! */
451 snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
452 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
455 save_svg_data(data, out, outsize);
460 ***************************************************************************
461 * Update CPU graph and min/max values for each metric.
464 * @timetag Timestamp in seconds since the epoch for current sample
465 * stats. Will be used as X coordinate.
466 * @offset Offset for Y coordinate.
467 * @value Value of current CPU metric. Will be used as rectangle
469 * @out Pointer on array of chars for current graph definition.
470 * @outsize Size of array of chars for current graph definition.
471 * @dt Interval of time in seconds between current and previous
473 * @spmin Min value already found for this CPU metric.
474 * @spmax Max value already found for this CPU metric.
477 * @offset New offset value, to use to draw next rectangle
478 * @out Pointer on array of chars for current graph definition that
479 * has been updated with the addition of current sample data.
480 * @outsize Array that containing the (possibly new) sizes of each
481 * element in array of chars.
482 ***************************************************************************
484 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
485 int *outsize, unsigned long long dt, double *spmin, double *spmax)
487 /* Save min and max values */
488 if (value < *spmin) {
491 if (value > *spmax) {
494 /* Prepare additional graph definition data */
495 brappend(timetag, *offset, value, out, outsize, dt);
501 ***************************************************************************
502 * Update rectangular graph and min/max values.
505 * @timetag Timestamp in seconds since the epoch for current sample
506 * stats. Will be used as X coordinate.
507 * @p_value Metric value for previous sample
508 * @value Metric value for current sample.
509 * @out Pointer on array of chars for current graph definition.
510 * @outsize Size of array of chars for current graph definition.
511 * @restart Set to TRUE if a RESTART record has been read since the last
513 * @dt Interval of time in seconds between current and previous
515 * @spmin Min value already found for this metric.
516 * @spmax Max value already found for this metric.
519 * @out Pointer on array of chars for current graph definition that
520 * has been updated with the addition of current sample data.
521 * @outsize Array that containing the (possibly new) sizes of each
522 * element in array of chars.
523 * @spmin Min value for this metric.
524 * @spmax Max value for this metric.
525 ***************************************************************************
527 void recappend(unsigned long long timetag, double p_value, double value, char **out,
528 int *outsize, int restart, unsigned long long dt,
529 double *spmin, double *spmax)
531 char data[128], data1[128], data2[128];
533 /* Save min and max values */
534 if (value < *spmin) {
537 if (value > *spmax) {
540 /* Prepare additional graph definition data */
542 snprintf(data1, 128, " M%llu,%.2f", timetag - dt, p_value);
545 if (p_value != value) {
546 snprintf(data2, 128, " L%llu,%.2f", timetag, value);
549 snprintf(data, 128, "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
550 p_value != value ? data2 : "");
553 save_svg_data(data, out, outsize);
557 ***************************************************************************
558 * Calculate 10 raised to the power of n.
561 * @n Power number to use.
564 * 10 raised to the power of n.
565 ***************************************************************************
567 unsigned int pwr10(int n)
572 for (i = 0; i < n; i++) {
580 ***************************************************************************
581 * Autoscale graphs of a given view.
584 * @asf_nr (Maximum) number of autoscale factors.
585 * @group Number of graphs in current view.
586 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
587 * @pos Position in array for the first graph in view.
588 * @gmax Global max value for all graphs in view.
589 * @spmax Array containing max values for graphs.
592 * @asfactor Autoscale factors (one for each graph).
593 ***************************************************************************
595 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
596 double gmax, double *spmax)
601 for (j = 0; j < asf_nr; j++) {
602 /* Init autoscale factors */
606 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
608 for (j = 0; (j < group) && (j < asf_nr); j++) {
609 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
612 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
613 if (strlen(val) > 0) {
614 asfactor[j] = pwr10(strlen(val) - 1);
621 ***************************************************************************
622 * Display background grid (horizontal lines) and corresponding graduations.
625 * @ypos Gap between two horizontal lines.
626 * @yfactor Scaling factor on Y axis.
627 * @lmax Max value for current view.
628 * @dp Number of decimal places for graduations.
629 ***************************************************************************
631 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
637 /* Display horizontal lines (except on X axis) */
639 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
640 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
641 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
645 * Display graduations.
646 * Use same rounded value for graduation numbers as for grid lines
647 * to make sure they are properly aligned.
649 sprintf(stmp, "%.2f", ypos * j);
650 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
651 "text-anchor: end\">%.*f.</text>\n",
652 (long) (atof(stmp) * yfactor), dp, ypos * j);
655 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
659 ***************************************************************************
660 * Display background grid (vertical lines) and corresponding graduations.
663 * @xpos Gap between two vertical lines.
664 * @xfactor Scaling factor on X axis.
665 * @v_gridnr Default number of vertical lines to display. The actual
666 * number may vary between this value and 2 times this value.
667 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
668 ***************************************************************************
670 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
672 struct record_header stamp;
674 char cur_time[TIMESTAMP_LEN];
677 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
680 * What really matters to know when we should stop drawing vertical lines
681 * is the time end. v_gridnr is only informative and used to calculate
682 * the gap between two lines.
684 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
686 /* Display vertical lines */
687 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
688 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
689 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
690 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
691 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
693 * Display graduations.
694 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
695 * In this case, we should rather display the exact time instead of only the hour.
697 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
698 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
699 "text-anchor: start\">%2d:00</text>\n",
700 (long) (xpos * j * xfactor) - 15, rectime.tm_hour);
703 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
704 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
705 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
707 stamp.ust_time += xpos;
710 if (!PRINT_LOCAL_TIME(flags)) {
711 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
712 "text-anchor: end\">UTC</text>\n");
717 ***************************************************************************
718 * Calculate the value on the Y axis between two horizontal lines that will
719 * make the graph background grid.
722 * @lmax Max value reached for this graph.
725 * @dp Number of decimal places for Y graduations.
728 * Value between two horizontal lines.
729 ***************************************************************************
731 double ygrid(double lmax, int *dp)
742 n = (long) (lmax / SVG_H_GRIDNR);
745 return (lmax / SVG_H_GRIDNR);
747 snprintf(val, 32, "%ld", n);
754 return ((double) (((long) (n / e)) * e));
758 ***************************************************************************
759 * Calculate the value on the X axis between two vertical lines that will
760 * make the graph background grid.
763 * @timestart First data timestamp (X coordinate of the first data point).
764 * @timeend Last data timestamp (X coordinate of the last data point).
765 * @v_gridnr Number of vertical lines to display. Its value is normally
766 * SVG_V_GRIDNR, except when option "oneday" is used, in which
767 * case it is set to 12.
770 * Value between two vertical lines.
771 ***************************************************************************
773 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
775 if ((timeend - timestart) <= v_gridnr)
778 return ((timeend - timestart) / v_gridnr);
782 ***************************************************************************
783 * Free global graphs structures.
786 * @out Pointer on array of chars for each graph definition.
787 * @outsize Size of array of chars for each graph definition.
788 * @spmin Array containing min values for graphs.
789 * @spmax Array containing max values for graphs.
790 ***************************************************************************
792 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
809 ***************************************************************************
810 * Skip current view where all graphs have only zero values. This function
811 * is called when option "skipempty" has been used, or when "No data" have
812 * been found for current view.
815 * @out Pointer on array of chars for each graph definition.
816 * @pos Position of current view in the array of graphs definitions.
817 * @group Number of graphs in current view.
820 * @pos Position of next view in the array of graphs definitions.
821 ***************************************************************************
823 void skip_current_view(char **out, int *pos, int group)
828 for (j = 0; j < group; j++) {
829 out_p = *(out + *pos + j);
831 /* Even if not displayed, current graph data have to be freed */
839 ***************************************************************************
840 * Display all graphs for current activity.
843 * @g_nr Number of views to display.
844 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
845 * @title Titles for each set of graphs.
846 * @g_title Titles for each graph.
847 * @item_name Item (network interface, etc.) name.
848 * @group Indicate how graphs are grouped together to make sets.
849 * @spmin Array containing min values for graphs.
850 * @spmax Array containing max values for graphs.
851 * @out Pointer on array of chars for each graph definition.
852 * @outsize Size of array of chars for each graph definition.
853 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
854 * time for the first sample of stats (.@ust_time_first), and
855 * times used as start and end values on the X axis
856 * (.@ust_time_ref and .@ust_time_end).
857 * @record_hdr Pointer on record header of current stats sample.
858 * @skip_void Set to <> 0 if graphs with no data should be skipped.
859 * This is typicallly used to not display CPU offline on the
861 * @id Current activity id.
862 * @xid Current activity extra id number.
865 * TRUE if at least one graph has been displayed.
866 ***************************************************************************
868 int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
869 int group[], double *spmin, double *spmax, char **out, int *outsize,
870 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
871 unsigned int id, unsigned int xid)
874 int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE;
875 int v_gridnr, xv, yv;
876 unsigned int asfactor[16];
878 double lmax, xfactor, yfactor, ypos, gmin, gmax;
879 char val[32], cur_date[TIMESTAMP_LEN];
881 /* For each view which is part of current activity */
882 for (i = 0; i < g_nr; i++) {
884 /* Get global min and max value for current view */
885 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
887 /* Don't display empty views if requested */
888 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
889 skip_current_view(out, &pos, group[i]);
892 /* Skip void graphs */
893 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
897 /* Translate to proper position for current activity */
898 printf("<g id=\"g%d-%d\" transform=\"translate(0,%d)\">\n",
901 SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
902 SVG_T_YSIZE * svg_p->graph_no);
906 /* Increment number of views actually displayed */
909 /* Compute top left position of view */
910 if (PACK_VIEWS(flags)) {
911 xv = (views_nr - 1) * SVG_T_XSIZE;
916 yv = (views_nr - 1) * SVG_T_YSIZE;
919 /* Graph background */
920 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
921 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
924 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
925 xv, 20 + yv, title[i]);
927 printf(" [%s]", item_name);
930 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
931 "(Min, Max values)</tspan>\n</text>\n",
932 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
935 * At least two samples are needed.
936 * And a min and max value should have been found.
938 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
939 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
941 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
942 xv, yv + SVG_M_YSIZE);
943 skip_current_view(out, &pos, group[i]);
948 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
949 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
950 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
951 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
953 /* Autoscaling graphs if needed */
954 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
957 for (j = 0; j < group[i]; j++) {
958 /* Set dp to TRUE (1) if current metric is based on integer values */
959 dp = (g_title[pos + j][0] == '~');
960 snprintf(val, 32, "x%u ", asfactor[j]);
961 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
962 "%s %s(%.*f, %.*f)</text>\n",
963 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
964 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
965 asfactor[j] == 1 ? "" : val,
966 !dp * 2, *(spmin + pos + j) * asfactor[j],
967 !dp * 2, *(spmax + pos + j) * asfactor[j]);
970 if (DISPLAY_INFO(flags)) {
971 /* Display additional info (hostname, date) */
972 printf("<text x=\"%d\" y=\"%d\" "
973 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
975 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
976 svg_p->file_hdr->sa_nodename);
978 /* Get report date */
979 set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
980 cur_date, sizeof(cur_date));
981 printf("<tspan x=\"%d\" y=\"%d\" "
982 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
983 "%s</tspan>\n</text>\n",
984 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
988 /* Translate to proper position for current graph within current activity */
989 printf("<g transform=\"translate(%d,%d)\">\n",
990 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
993 if (g_type[i] == SVG_LINE_GRAPH) {
994 /* For line graphs */
996 /* If all values are zero then set current max value to 1 */
1002 /* Max value cannot be too small, else Y graduations will be meaningless */
1003 if (lmax < SVG_H_GRIDNR * 0.01) {
1004 lmax = SVG_H_GRIDNR * 0.01;
1006 ypos = ygrid(lmax, &dp);
1009 /* For bar graphs (used for %values) */
1010 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
1011 dp = 0; /* No decimals */
1013 /* Max should be always 100% except for percentage values greater than 100% */
1021 yfactor = (double) -SVG_G_YSIZE / lmax;
1023 /* Display horizontal lines and graduations */
1024 display_hgrid(ypos, yfactor, lmax, dp);
1026 /* Set number of vertical lines to 12 when option "oneday" is used */
1027 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1029 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1030 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1032 /* Display vertical lines and graduations */
1033 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1035 /* Draw current graphs set */
1036 for (j = 0; j < group[i]; j++) {
1037 out_p = *(out + pos + j);
1038 if (g_type[i] == SVG_LINE_GRAPH) {
1040 printf("<path d=\"%s\" "
1041 "style=\"vector-effect: non-scaling-stroke; "
1042 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1043 "transform=\"scale(%f,%f)\"/>\n",
1045 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
1047 yfactor * asfactor[j]);
1049 else if (*out_p) { /* Ignore flat bars */
1051 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1052 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1053 printf("%s\n", out_p);
1065 /* For next row of views */
1066 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1072 ***************************************************************************
1073 * Display CPU statistics in SVG.
1076 * @a Activity structure with statistics.
1077 * @curr Index in array for current sample statistics.
1078 * @action Action expected from current function.
1079 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1080 * flag indicating that a restart record has been previously
1081 * found (.@restart), and time used for the X axis origin
1083 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1085 * @record_hdr Pointer on record header of current stats sample.
1086 ***************************************************************************
1088 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1089 unsigned long long itv, struct record_header *record_hdr)
1091 struct stats_cpu *scc, *scp;
1092 unsigned long long deltot_jiffies = 1;
1093 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1096 int g_type[] = {SVG_BAR_GRAPH};
1097 char *title[] = {"CPU utilization"};
1098 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1099 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1100 static double *spmin, *spmax;
1102 static int *outsize;
1107 if (action & F_BEGIN) {
1109 * Allocate arrays that will contain the graphs data
1110 * and the min/max values.
1112 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
1115 if (action & F_MAIN) {
1117 /* @nr[curr] cannot normally be greater than @nr_ini */
1118 if (a->nr[curr] > a->nr_ini) {
1119 a->nr_ini = a->nr[curr];
1123 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1124 * and look for offline CPU.
1126 if (a->nr_ini > 1) {
1127 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1128 flags, offline_cpu_bitmap);
1132 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1134 /* Should current CPU (including CPU "all") be displayed? */
1135 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1136 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1137 /* Don't display CPU */
1140 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1141 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1147 /* This is CPU "all" */
1148 if (a->nr_ini == 1) {
1150 * This is a UP machine. In this case
1151 * interval has still not been calculated.
1153 deltot_jiffies = get_per_cpu_interval(scc, scp);
1155 if (!deltot_jiffies) {
1156 /* CPU "all" cannot be tickless */
1162 * Recalculate interval for current proc.
1163 * If result is 0 then current CPU is a tickless one.
1165 deltot_jiffies = get_per_cpu_interval(scc, scp);
1167 if (!deltot_jiffies) { /* Current CPU is tickless */
1169 val = 100.0; /* Tickless CPU: %idle = 100% */
1171 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1174 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1178 /* Check min/max values for %user, etc. */
1179 for (k = 0; k < j; k++) {
1180 if (0.0 < *(spmin + pos + k)) {
1181 *(spmin + pos + k) = 0.0;
1183 if (0.0 > *(spmax + pos + k)) {
1184 *(spmax + pos + k) = 0.0;
1189 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1191 out + pos + j, outsize + pos + j, svg_p->dt,
1192 spmin + pos + j, spmax + pos + j);
1197 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1199 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1200 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1201 out + pos, outsize + pos, svg_p->dt,
1202 spmin + pos, spmax + pos);
1206 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1208 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1210 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1211 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1212 out + pos, outsize + pos, svg_p->dt,
1213 spmin + pos, spmax + pos);
1216 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1218 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1219 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1220 out + pos + 1, outsize + pos + 1, svg_p->dt,
1221 spmin + pos + 1, spmax + pos + 1);
1225 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1227 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1229 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1230 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1231 out + pos + 1, outsize + pos + 1, svg_p->dt,
1232 spmin + pos + 1, spmax + pos + 1);
1235 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1237 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1239 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1240 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1242 out + pos + 2, outsize + pos + 2, svg_p->dt,
1243 spmin + pos + 2, spmax + pos + 2);
1247 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1248 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1249 out + pos + 2, outsize + pos + 2, svg_p->dt,
1250 spmin + pos + 2, spmax + pos + 2);
1254 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1255 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1256 out + pos + 3, outsize + pos + 3, svg_p->dt,
1257 spmin + pos + 3, spmax + pos + 3);
1259 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1260 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1261 out + pos + 4, outsize + pos + 4, svg_p->dt,
1262 spmin + pos + 4, spmax + pos + 4);
1264 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1266 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1267 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1268 out + pos + 5, outsize + pos + 5, svg_p->dt,
1269 spmin + pos + 5, spmax + pos + 5);
1271 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1272 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1273 out + pos + 6, outsize + pos + 6, svg_p->dt,
1274 spmin + pos + 6, spmax + pos + 6);
1276 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1277 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1278 out + pos + 7, outsize + pos + 7, svg_p->dt,
1279 spmin + pos + 7, spmax + pos + 7);
1281 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1282 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1283 out + pos + 8, outsize + pos + 8, svg_p->dt,
1284 spmin + pos + 8, spmax + pos + 8);
1293 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1295 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1296 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1297 out + pos + j, outsize + pos + j, svg_p->dt,
1298 spmin + pos + j, spmax + pos + j);
1302 if (action & F_END) {
1303 int xid = 0, displayed;
1305 if (DISPLAY_IDLE(flags)) {
1306 /* Include additional %idle field */
1311 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
1313 /* Should current CPU (including CPU "all") be displayed? */
1314 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1320 /* This is CPU "all" */
1321 strcpy(item_name, "all");
1324 sprintf(item_name, "%d", i - 1);
1327 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1328 displayed = draw_activity_graphs(a->g_nr, g_type,
1329 title, g_title1, item_name, group1,
1330 spmin + pos, spmax + pos, out + pos, outsize + pos,
1331 svg_p, record_hdr, i, a->id, xid);
1334 displayed = draw_activity_graphs(a->g_nr, g_type,
1335 title, g_title2, item_name, group2,
1336 spmin + pos, spmax + pos, out + pos, outsize + pos,
1337 svg_p, record_hdr, i, a->id, xid);
1344 /* Free remaining structures */
1345 free_graphs(out, outsize, spmin, spmax);
1350 ***************************************************************************
1351 * Display task creation and context switch statistics in SVG.
1354 * @a Activity structure with statistics.
1355 * @curr Index in array for current sample statistics.
1356 * @action Action expected from current function.
1357 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1358 * flag indicating that a restart record has been previously
1359 * found (.@restart) and time used for the X axis origin
1361 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1362 * @record_hdr Pointer on record header of current stats sample.
1363 ***************************************************************************
1365 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1366 unsigned long long itv, struct record_header *record_hdr)
1369 *spc = (struct stats_pcsw *) a->buf[curr],
1370 *spp = (struct stats_pcsw *) a->buf[!curr];
1371 int group[] = {1, 1};
1372 int g_fields[] = {1, 0};
1373 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1374 char *title[] = {"Task creation", "Switching activity"};
1375 char *g_title[] = {"proc/s",
1377 static double *spmin, *spmax;
1379 static int *outsize;
1381 if (action & F_BEGIN) {
1383 * Allocate arrays that will contain the graphs data
1384 * and the min/max values.
1386 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1389 if (action & F_MAIN) {
1390 /* Check for min/max values */
1391 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1392 itv, spmin, spmax, g_fields);
1394 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1395 S_VALUE(spp->processes, spc->processes, itv),
1396 out, outsize, svg_p->restart);
1398 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1399 S_VALUE(spp->context_switch, spc->context_switch, itv),
1400 out + 1, outsize + 1, svg_p->restart);
1403 if (action & F_END) {
1404 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1405 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1407 /* Free remaining structures */
1408 free_graphs(out, outsize, spmin, spmax);
1413 ***************************************************************************
1414 * Display swap statistics in SVG.
1417 * @a Activity structure with statistics.
1418 * @curr Index in array for current sample statistics.
1419 * @action Action expected from current function.
1420 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1421 * flag indicating that a restart record has been previously
1422 * found (.@restart) and time used for the X axis origin
1424 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1425 * @record_hdr Pointer on record header of current stats sample.
1426 ***************************************************************************
1428 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1429 unsigned long long itv, struct record_header *record_hdr)
1432 *ssc = (struct stats_swap *) a->buf[curr],
1433 *ssp = (struct stats_swap *) a->buf[!curr];
1435 int g_type[] = {SVG_LINE_GRAPH};
1436 char *title[] = {"Swap activity"};
1437 char *g_title[] = {"pswpin/s", "pswpout/s" };
1438 int g_fields[] = {0, 1};
1439 static double *spmin, *spmax;
1441 static int *outsize;
1443 if (action & F_BEGIN) {
1445 * Allocate arrays that will contain the graphs data
1446 * and the min/max values.
1448 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1451 if (action & F_MAIN) {
1452 /* Check for min/max values */
1453 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1454 itv, spmin, spmax, g_fields);
1456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1457 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1458 out, outsize, svg_p->restart);
1460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1461 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1462 out + 1, outsize + 1, svg_p->restart);
1465 if (action & F_END) {
1466 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1467 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1469 /* Free remaining structures */
1470 free_graphs(out, outsize, spmin, spmax);
1475 ***************************************************************************
1476 * Display paging statistics in SVG.
1479 * @a Activity structure with statistics.
1480 * @curr Index in array for current sample statistics.
1481 * @action Action expected from current function.
1482 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1483 * flag indicating that a restart record has been previously
1484 * found (.@restart) and time used for the X axis origin
1486 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1487 * @record_hdr Pointer on record header of current stats sample.
1488 ***************************************************************************
1490 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1491 unsigned long long itv, struct record_header *record_hdr)
1494 *spc = (struct stats_paging *) a->buf[curr],
1495 *spp = (struct stats_paging *) a->buf[!curr];
1496 int group[] = {2, 2, 4};
1497 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1498 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1499 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1500 "fault/s", "majflt/s",
1501 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1502 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1503 static double *spmin, *spmax;
1505 static int *outsize;
1507 if (action & F_BEGIN) {
1509 * Allocate arrays that will contain the graphs data
1510 * and the min/max values.
1512 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1515 if (action & F_MAIN) {
1516 /* Check for min/max values */
1517 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1518 itv, spmin, spmax, g_fields);
1520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1521 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1522 out, outsize, svg_p->restart);
1524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1525 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1526 out + 1, outsize + 1, svg_p->restart);
1528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1529 S_VALUE(spp->pgfault, spc->pgfault, itv),
1530 out + 2, outsize + 2, svg_p->restart);
1532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1533 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1534 out + 3, outsize + 3, svg_p->restart);
1536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1537 S_VALUE(spp->pgfree, spc->pgfree, itv),
1538 out + 4, outsize + 4, svg_p->restart);
1540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1541 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1542 out + 5, outsize + 5, svg_p->restart);
1544 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1545 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1546 out + 6, outsize + 6, svg_p->restart);
1548 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1549 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1550 out + 7, outsize + 7, svg_p->restart);
1553 if (action & F_END) {
1554 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1555 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1557 /* Free remaining structures */
1558 free_graphs(out, outsize, spmin, spmax);
1563 ***************************************************************************
1564 * Display I/O and transfer rate statistics in SVG.
1567 * @a Activity structure with statistics.
1568 * @curr Index in array for current sample statistics.
1569 * @action Action expected from current function.
1570 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1571 * flag indicating that a restart record has been previously
1572 * found (.@restart) and time used for the X axis origin
1574 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1575 * @record_hdr Pointer on record header of current stats sample.
1576 ***************************************************************************
1578 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1579 unsigned long long itv, struct record_header *record_hdr)
1582 *sic = (struct stats_io *) a->buf[curr],
1583 *sip = (struct stats_io *) a->buf[!curr];
1584 int group[] = {3, 2};
1585 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1586 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1587 char *g_title[] = {"tps", "rtps", "wtps",
1588 "bread/s", "bwrtn/s"};
1589 int g_fields[] = {0, 1, 2, 3, 4};
1590 static double *spmin, *spmax;
1592 static int *outsize;
1594 if (action & F_BEGIN) {
1596 * Allocate arrays that will contain the graphs data
1597 * and the min/max values.
1599 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1602 if (action & F_MAIN) {
1603 /* Check for min/max values */
1604 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1605 itv, spmin, spmax, g_fields);
1608 * If we get negative values, this is probably because
1609 * one or more devices/filesystems have been unmounted.
1610 * We display 0.0 in this case though we should rather tell
1611 * the user that the value cannot be calculated here.
1614 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1615 sic->dk_drive < sip->dk_drive ? 0.0 :
1616 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1617 out, outsize, svg_p->restart);
1619 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1620 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1621 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1622 out + 1, outsize + 1, svg_p->restart);
1624 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1625 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1626 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1627 out + 2, outsize + 2, svg_p->restart);
1629 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1630 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1631 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1632 out + 3, outsize + 3, svg_p->restart);
1634 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1635 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1636 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1637 out + 4, outsize + 4, svg_p->restart);
1640 if (action & F_END) {
1641 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1642 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1644 /* Free remaining structures */
1645 free_graphs(out, outsize, spmin, spmax);
1650 ***************************************************************************
1651 * Display memory statistics in SVG.
1654 * @a Activity structure with statistics.
1655 * @curr Index in array for current sample statistics.
1656 * @action Action expected from current function.
1657 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1658 * flag indicating that a restart record has been previously
1659 * found (.@restart) and time used for the X axis origin
1661 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1662 * @record_hdr Pointer on record header of current stats sample.
1663 ***************************************************************************
1665 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1666 unsigned long long itv, struct record_header *record_hdr)
1669 *smc = (struct stats_memory *) a->buf[curr];
1670 int group1[] = {3, 1, 3, 1, 3, 5};
1671 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1672 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1673 int group2[] = {3, 1, 1};
1674 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1675 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1676 "Memory utilization (3)", "Memory utilization (4)",
1677 "Memory utilization (5)", "Memory utilization (6)"};
1678 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1679 "Swap utilization (3)"};
1680 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1681 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1682 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1684 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1686 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1687 static double *spmin, *spmax;
1689 static int *outsize;
1692 unsigned long long nousedmem;
1694 if (action & F_BEGIN) {
1696 * Allocate arrays that will contain the graphs data
1697 * and the min/max values.
1699 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1702 if (action & F_MAIN) {
1703 /* Check for min/max values */
1704 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1705 itv, spmin, spmax, g_fields);
1706 /* Compute %memused min/max values */
1707 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1708 if (nousedmem > smc->tlmkb) {
1709 nousedmem = smc->tlmkb;
1711 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1712 if (tval > *(spmax + 3)) {
1713 *(spmax + 3) = tval;
1715 if (tval < *(spmin + 3)) {
1716 *(spmin + 3) = tval;
1718 /* Compute %commit min/max values */
1719 tval = (smc->tlmkb + smc->tlskb) ?
1720 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1721 if (tval > *(spmax + 7)) {
1722 *(spmax + 7) = tval;
1724 if (tval < *(spmin + 7)) {
1725 *(spmin + 7) = tval;
1727 /* Compute %swpused min/max values */
1729 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1730 if (tval > *(spmax + 19)) {
1731 *(spmax + 19) = tval;
1733 if (tval < *(spmin + 19)) {
1734 *(spmin + 19) = tval;
1736 /* Compute %swpcad min/max values */
1737 tval = (smc->tlskb - smc->frskb) ?
1738 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1739 if (tval > *(spmax + 20)) {
1740 *(spmax + 20) = tval;
1742 if (tval < *(spmin + 20)) {
1743 *(spmin + 20) = tval;
1745 /* Compute memused min/max values in MB */
1746 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1747 if (tval > *(spmax + 2)) {
1748 *(spmax + 2) = tval;
1750 if (tval < *(spmin + 2)) {
1751 *(spmin + 2) = tval;
1753 /* Compute swpused min/max values in MB */
1754 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1755 if (tval > *(spmax + 17)) {
1756 *(spmax + 17) = tval;
1758 if (tval < *(spmin + 17)) {
1759 *(spmin + 17) = tval;
1763 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1764 ((double) smc->frmkb) / 1024,
1765 out, outsize, svg_p->restart);
1767 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1768 ((double) (smc->tlmkb - nousedmem)) / 1024,
1769 out + 2, outsize + 2, svg_p->restart);
1771 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1772 ((double) smc->availablekb) / 1024,
1773 out + 1, outsize + 1, svg_p->restart);
1775 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1776 ((double) smc->bufkb) / 1024,
1777 out + 4, outsize + 4, svg_p->restart);
1779 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1780 ((double) smc->camkb) / 1024,
1781 out + 5, outsize + 5, svg_p->restart);
1783 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1784 ((double) smc->frskb) / 1024,
1785 out + 16, outsize + 16, svg_p->restart);
1787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1788 ((double) (smc->tlskb - smc->frskb)) / 1024,
1789 out + 17, outsize + 17, svg_p->restart);
1791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1792 ((double) smc->caskb) / 1024,
1793 out + 18, outsize + 18, svg_p->restart);
1795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1796 ((double) smc->comkb) / 1024,
1797 out + 6, outsize + 6, svg_p->restart);
1799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1800 ((double) smc->activekb) / 1024,
1801 out + 8, outsize + 8, svg_p->restart);
1803 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1804 ((double) smc->inactkb) / 1024,
1805 out + 9, outsize + 9, svg_p->restart);
1807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1808 ((double) smc->dirtykb) / 1024,
1809 out + 10, outsize + 10, svg_p->restart);
1811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1812 ((double) smc->anonpgkb) / 1024,
1813 out + 11, outsize + 11, svg_p->restart);
1815 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1816 ((double) smc->slabkb) / 1024,
1817 out + 12, outsize + 12, svg_p->restart);
1819 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1820 ((double) smc->kstackkb) / 1024,
1821 out + 13, outsize + 13, svg_p->restart);
1823 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1824 ((double) smc->pgtblkb) / 1024,
1825 out + 14, outsize + 14, svg_p->restart);
1827 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1828 ((double) smc->vmusedkb) / 1024,
1829 out + 15, outsize + 15, svg_p->restart);
1831 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1834 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1835 out + 3, outsize + 3, svg_p->dt);
1837 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1839 (smc->tlmkb + smc->tlskb) ?
1840 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1841 out + 7, outsize + 7, svg_p->dt);
1843 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1846 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1847 out + 19, outsize + 19, svg_p->dt);
1849 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1851 (smc->tlskb - smc->frskb) ?
1852 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1853 out + 20, outsize + 20, svg_p->dt);
1856 if (action & F_END) {
1858 /* Conversion kB -> MB */
1859 for (i = 0; i < 17; i++) {
1860 *(spmin + g_fields[i]) /= 1024;
1861 *(spmax + g_fields[i]) /= 1024;
1864 if (DISPLAY_MEMORY(a->opt_flags)) {
1865 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1866 g_type1, title1, g_title1, NULL, group1,
1867 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1870 if (DISPLAY_SWAP(a->opt_flags)) {
1871 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1872 spmin + 16, spmax + 16, out + 16, outsize + 16,
1873 svg_p, record_hdr, FALSE, a->id, 1);
1876 /* Free remaining structures */
1877 free_graphs(out, outsize, spmin, spmax);
1882 ***************************************************************************
1883 * Display kernel tables statistics in SVG.
1886 * @a Activity structure with statistics.
1887 * @curr Index in array for current sample statistics.
1888 * @action Action expected from current function.
1889 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1890 * flag indicating that a restart record has been previously
1891 * found (.@restart) and time used for the X axis origin
1893 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1894 * @record_hdr Pointer on record header of current stats sample.
1895 ***************************************************************************
1897 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1898 unsigned long long itv, struct record_header *record_hdr)
1900 struct stats_ktables
1901 *skc = (struct stats_ktables *) a->buf[curr];
1902 int group[] = {3, 1};
1903 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1904 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1905 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1907 int g_fields[] = {1, 2, 0, 3};
1908 static double *spmin, *spmax;
1910 static int *outsize;
1912 if (action & F_BEGIN) {
1914 * Allocate arrays that will contain the graphs data
1915 * and the min/max values.
1917 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1920 if (action & F_MAIN) {
1921 /* Check for min/max values */
1922 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1923 itv, spmin, spmax, g_fields);
1925 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1926 (unsigned long long) skc->dentry_stat,
1927 out, outsize, svg_p->restart);
1929 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1930 (unsigned long long) skc->file_used,
1931 out + 1, outsize + 1, svg_p->restart);
1933 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1934 (unsigned long long) skc->inode_used,
1935 out + 2, outsize + 2, svg_p->restart);
1937 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1938 (unsigned long long) skc->pty_nr,
1939 out + 3, outsize + 3, svg_p->restart);
1942 if (action & F_END) {
1943 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1944 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1946 /* Free remaining structures */
1947 free_graphs(out, outsize, spmin, spmax);
1952 ***************************************************************************
1953 * Display queue and load statistics in SVG.
1956 * @a Activity structure with statistics.
1957 * @curr Index in array for current sample statistics.
1958 * @action Action expected from current function.
1959 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1960 * flag indicating that a restart record has been previously
1961 * found (.@restart) and time used for the X axis origin
1963 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1964 * @record_hdr Pointer on record header of current stats sample.
1965 ***************************************************************************
1967 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1968 unsigned long long itv, struct record_header *record_hdr)
1971 *sqc = (struct stats_queue *) a->buf[curr];
1972 int group[] = {2, 1, 3};
1973 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1974 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
1975 char *g_title[] = {"~runq-sz", "~blocked",
1977 "ldavg-1", "ldavg-5", "ldavg-15"};
1978 int g_fields[] = {0, 1, 2, 3, 4, 5};
1979 static double *spmin, *spmax;
1981 static int *outsize;
1983 if (action & F_BEGIN) {
1985 * Allocate arrays that will contain the graphs data
1986 * and the min/max values.
1988 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1991 if (action & F_MAIN) {
1992 /* Check for min/max values */
1993 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1994 itv, spmin, spmax, g_fields);
1996 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1997 (unsigned long long) sqc->nr_running,
1998 out, outsize, svg_p->restart);
2000 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2001 (unsigned long long) sqc->procs_blocked,
2002 out + 1, outsize + 1, svg_p->restart);
2004 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2005 (unsigned long long) sqc->nr_threads,
2006 out + 2, outsize + 2, svg_p->restart);
2008 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2009 (double) sqc->load_avg_1 / 100,
2010 out + 3, outsize + 3, svg_p->restart);
2012 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2013 (double) sqc->load_avg_5 / 100,
2014 out + 4, outsize + 4, svg_p->restart);
2016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2017 (double) sqc->load_avg_15 / 100,
2018 out + 5, outsize + 5, svg_p->restart);
2021 if (action & F_END) {
2022 /* Fix min/max values for load average */
2023 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2024 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2025 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2027 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2028 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2030 /* Free remaining structures */
2031 free_graphs(out, outsize, spmin, spmax);
2036 ***************************************************************************
2037 * Display disk statistics in SVG.
2040 * @a Activity structure with statistics.
2041 * @curr Index in array for current sample statistics.
2042 * @action Action expected from current function.
2043 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2044 * flag indicating that a restart record has been previously
2045 * found (.@restart) and time used for the X axis origin
2047 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2048 * @record_hdr Pointer on record header of current stats sample.
2049 ***************************************************************************
2051 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2052 unsigned long long itv, struct record_header *record_hdr)
2054 struct stats_disk *sdc, *sdp, sdpzero;
2055 struct ext_disk_stats xds;
2056 int group[] = {1, 2, 2, 2, 1};
2057 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2058 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2059 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2060 "Block devices statistics (3)", "Block devices statistics (4)",
2061 "Block devices statistics (5)"};
2062 char *g_title[] = {"tps",
2064 "areq-sz", "aqu-sz",
2067 int g_fields[] = {0, 1, 2};
2068 unsigned int local_types_nr[] = {1, 0, 0};
2069 static double *spmin, *spmax;
2071 static int *outsize;
2073 double rkB, wkB, aqusz;
2074 int i, j, k, pos, restart, *unregistered;
2076 if (action & F_BEGIN) {
2078 * Allocate arrays (#0..7) that will contain the graphs data
2079 * and the min/max values.
2080 * Also allocate one additional array (#8) for each disk device:
2081 * spmax + 8 will contain the device major number,
2082 * spmin + 8 will contain the device minor number,
2083 * outsize + 8 will contain a positive value (TRUE) if the device
2084 * has either still not been registered, or has been unregistered.
2086 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2089 if (action & F_MAIN) {
2090 memset(&sdpzero, 0, STATS_DISK_SIZE);
2091 restart = svg_p->restart;
2093 * Mark previously registered devices as now
2094 * possibly unregistered for all graphs.
2096 for (k = 0; k < svg_p->nr_max; k++) {
2097 unregistered = outsize + k * 9 + 8;
2098 if (*unregistered == FALSE) {
2099 *unregistered = MAYBE;
2103 /* For each device structure */
2104 for (i = 0; i < a->nr[curr]; i++) {
2105 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2107 /* Get device name */
2108 item_name = get_sa_devname(sdc->major, sdc->minor, flags);
2111 /* A list of devices has been entered on the command line */
2112 if (!search_sa_dlist(st_dev_list, dlst_dev_idx, item_name))
2113 /* Device not found */
2117 /* Look for corresponding graph */
2118 for (k = 0; k < svg_p->nr_max; k++) {
2119 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2120 (sdc->minor == *(spmin + k * 9 + 8)))
2124 if (k == svg_p->nr_max) {
2125 /* Graph not found: Look for first free entry */
2126 for (k = 0; k < svg_p->nr_max; k++) {
2127 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2130 if (k == svg_p->nr_max) {
2131 /* No free graph entry: Extend all buffers */
2132 reallocate_all_graph_lines(svg_p->nr_max,
2133 &out, &outsize, &spmin, &spmax);
2138 unregistered = outsize + pos + 8;
2141 * If current device was marked as previously unregistered,
2142 * then set restart variable to TRUE so that the graph will be
2143 * discontinuous, and mark it as now registered.
2145 if (*unregistered == TRUE) {
2148 *unregistered = FALSE;
2150 if (*(spmax + pos + 8) == -DBL_MAX) {
2151 /* Save device major and minor numbers (if not already done) */
2152 *(spmax + pos + 8) = sdc->major;
2153 *(spmin + pos + 8) = sdc->minor;
2156 j = check_disk_reg(a, curr, !curr, i);
2158 /* This is a newly registered interface. Previous stats are zero */
2162 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2165 /* Check for min/max values */
2166 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2167 itv, spmin + pos, spmax + pos, g_fields);
2169 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2170 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2171 if (rkB < *(spmin + pos + 1)) {
2172 *(spmin + pos + 1) = rkB;
2174 if (rkB > *(spmax + pos + 1)) {
2175 *(spmax + pos + 1) = rkB;
2177 if (wkB < *(spmin + pos + 2)) {
2178 *(spmin + pos + 2) = wkB;
2180 if (wkB > *(spmax + pos + 2)) {
2181 *(spmax + pos + 2) = wkB;
2184 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2185 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2186 *(spmin + pos + 3) = xds.arqsz / 2;
2188 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2189 *(spmax + pos + 3) = xds.arqsz / 2;
2191 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2192 if (aqusz < *(spmin + pos + 4)) {
2193 *(spmin + pos + 4) = aqusz;
2195 if (aqusz > *(spmax + pos + 4)) {
2196 *(spmax + pos + 4) = aqusz;
2198 if (xds.await < *(spmin + pos + 5)) {
2199 *(spmin + pos + 5) = xds.await;
2201 if (xds.await > *(spmax + pos + 5)) {
2202 *(spmax + pos + 5) = xds.await;
2204 if (xds.svctm < *(spmin + pos + 6)) {
2205 *(spmin + pos + 6) = xds.svctm;
2207 if (xds.svctm > *(spmax + pos + 6)) {
2208 *(spmax + pos + 6) = xds.svctm;
2210 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2211 *(spmin + pos + 7) = xds.util / 10.0;
2213 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2214 *(spmax + pos + 7) = xds.util / 10.0;
2218 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2219 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2220 out + pos, outsize + pos, restart);
2222 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2223 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2224 out + pos + 1, outsize + pos + 1, restart);
2226 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2227 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2228 out + pos + 2, outsize + pos + 2, restart);
2230 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2232 out + pos + 3, outsize + pos + 3, restart);
2234 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2236 out + pos + 4, outsize + pos + 4, restart);
2238 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2240 out + pos + 5, outsize + pos + 5, restart);
2242 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2244 out + pos + 6, outsize + pos + 6, restart);
2246 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2247 0.0, xds.util / 10.0,
2248 out + pos + 7, outsize + pos + 7, svg_p->dt);
2251 /* Mark devices not seen here as now unregistered */
2252 for (k = 0; k < svg_p->nr_max; k++) {
2253 unregistered = outsize + k * 9 + 8;
2254 if (*unregistered != FALSE) {
2255 *unregistered = TRUE;
2260 if (action & F_END) {
2263 for (i = 0; i < svg_p->nr_max; i++) {
2264 /* Check if there is something to display */
2269 /* Get device name */
2270 item_name = get_sa_devname(*(spmax + pos + 8), *(spmin + pos + 8), flags);
2272 if (draw_activity_graphs(a->g_nr, g_type,
2273 title, g_title, item_name, group,
2274 spmin + pos, spmax + pos, out + pos, outsize + pos,
2275 svg_p, record_hdr, FALSE, a->id, xid)) {
2280 /* Free remaining structures */
2281 free_graphs(out, outsize, spmin, spmax);
2286 ***************************************************************************
2287 * Display network interfaces statistics in SVG.
2290 * @a Activity structure with statistics.
2291 * @curr Index in array for current sample statistics.
2292 * @action Action expected from current function.
2293 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2294 * flag indicating that a restart record has been previously
2295 * found (.@restart) and time used for the X axis origin
2297 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2298 * @record_hdr Pointer on record header of current stats sample.
2299 ***************************************************************************
2301 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2302 unsigned long long itv, struct record_header *record_hdr)
2304 struct stats_net_dev *sndc, *sndp, sndzero;
2305 int group[] = {2, 2, 3, 1};
2306 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2308 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2309 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2310 char *g_title[] = {"rxpck/s", "txpck/s",
2312 "rxcmp/s", "txcmp/s", "rxmcst/s",
2314 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2315 unsigned int local_types_nr[] = {7, 0, 0};
2316 static double *spmin, *spmax;
2318 static int *outsize;
2320 double rxkb, txkb, ifutil;
2321 int i, j, k, pos, restart, *unregistered;
2323 if (action & F_BEGIN) {
2325 * Allocate arrays (#0..7) that will contain the graphs data
2326 * and the min/max values.
2327 * Also allocate one additional array (#8) for each interface:
2328 * out + 8 will contain the interface name,
2329 * outsize + 8 will contain a positive value (TRUE) if the interface
2330 * has either still not been registered, or has been unregistered.
2332 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2335 if (action & F_MAIN) {
2336 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2337 restart = svg_p->restart;
2339 * Mark previously registered interfaces as now
2340 * possibly unregistered for all graphs.
2342 for (k = 0; k < svg_p->nr_max; k++) {
2343 unregistered = outsize + k * 9 + 8;
2344 if (*unregistered == FALSE) {
2345 *unregistered = MAYBE;
2349 /* For each network interfaces structure */
2350 for (i = 0; i < a->nr[curr]; i++) {
2351 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2353 if (dlst_iface_idx) {
2354 /* A list of devices has been entered on the command line */
2355 if (!search_sa_dlist(st_iface_list, dlst_iface_idx, sndc->interface))
2356 /* Device not found */
2360 /* Look for corresponding graph */
2361 for (k = 0; k < svg_p->nr_max; k++) {
2362 item_name = *(out + k * 9 + 8);
2363 if (!strcmp(sndc->interface, item_name))
2367 if (k == svg_p->nr_max) {
2368 /* Graph not found: Look for first free entry */
2369 for (k = 0; k < svg_p->nr_max; k++) {
2370 item_name = *(out + k * 9 + 8);
2371 if (!strcmp(item_name, ""))
2374 if (k == svg_p->nr_max) {
2375 /* No free graph entry: Extend all buffers */
2376 reallocate_all_graph_lines(svg_p->nr_max,
2377 &out, &outsize, &spmin, &spmax);
2383 unregistered = outsize + pos + 8;
2385 j = check_net_dev_reg(a, curr, !curr, i);
2387 /* This is a newly registered interface. Previous stats are zero */
2391 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2395 * If current interface was marked as previously unregistered,
2396 * then set restart variable to TRUE so that the graph will be
2397 * discontinuous, and mark it as now registered.
2399 if (*unregistered == TRUE) {
2402 *unregistered = FALSE;
2404 if (!item_name[0]) {
2405 /* Save network interface name (if not already done) */
2406 strncpy(item_name, sndc->interface, CHUNKSIZE);
2407 item_name[CHUNKSIZE - 1] = '\0';
2410 /* Check for min/max values */
2411 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2412 itv, spmin + pos, spmax + pos, g_fields);
2414 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2415 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2416 ifutil = compute_ifutil(sndc, rxkb, txkb);
2417 if (ifutil < *(spmin + pos + 7)) {
2418 *(spmin + pos + 7) = ifutil;
2420 if (ifutil > *(spmax + pos + 7)) {
2421 *(spmax + pos + 7) = ifutil;
2425 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2426 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2427 out + pos, outsize + pos, restart);
2429 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2430 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2431 out + pos + 1, outsize + pos + 1, restart);
2433 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2435 out + pos + 2, outsize + pos + 2, restart);
2437 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2439 out + pos + 3, outsize + pos + 3, restart);
2441 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2442 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2443 out + pos + 4, outsize + pos + 4, restart);
2445 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2446 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2447 out + pos + 5, outsize + pos + 5, restart);
2449 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2450 S_VALUE(sndp->multicast, sndc->multicast, itv),
2451 out + pos + 6, outsize + pos + 6, restart);
2453 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2455 out + pos + 7, outsize + pos + 7, svg_p->dt);
2458 /* Mark interfaces not seen here as now unregistered */
2459 for (k = 0; k < svg_p->nr_max; k++) {
2460 unregistered = outsize + k * 9 + 8;
2461 if (*unregistered != FALSE) {
2462 *unregistered = TRUE;
2467 if (action & F_END) {
2470 for (i = 0; i < svg_p->nr_max; i++) {
2472 * Check if there is something to display.
2473 * Don't test sndc->interface because maybe the network
2474 * interface has been registered later.
2480 /* Recalculate min and max values in kB, not in B */
2481 *(spmin + pos + 2) /= 1024;
2482 *(spmax + pos + 2) /= 1024;
2483 *(spmin + pos + 3) /= 1024;
2484 *(spmax + pos + 3) /= 1024;
2486 item_name = *(out + pos + 8);
2487 if (draw_activity_graphs(a->g_nr, g_type,
2488 title, g_title, item_name, group,
2489 spmin + pos, spmax + pos, out + pos, outsize + pos,
2490 svg_p, record_hdr, FALSE, a->id, xid)) {
2495 /* Free remaining structures */
2496 free_graphs(out, outsize, spmin, spmax);
2501 ***************************************************************************
2502 * Display network interfaces errors statistics in SVG.
2505 * @a Activity structure with statistics.
2506 * @curr Index in array for current sample statistics.
2507 * @action Action expected from current function.
2508 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2509 * flag indicating that a restart record has been previously
2510 * found (.@restart) and time used for the X axis origin
2512 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2513 * @record_hdr Pointer on record header of current stats sample.
2514 ***************************************************************************
2516 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2517 unsigned long long itv, struct record_header *record_hdr)
2519 struct stats_net_edev *snedc, *snedp, snedzero;
2520 int group[] = {2, 2, 2, 3};
2521 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2523 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2524 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2525 char *g_title[] = {"rxerr/s", "txerr/s",
2526 "rxdrop/s", "txdrop/s",
2527 "rxfifo/s", "txfifo/s",
2528 "coll/s", "txcarr/s", "rxfram/s"};
2529 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2530 static double *spmin, *spmax;
2532 static int *outsize;
2534 int i, j, k, pos, restart, *unregistered;
2536 if (action & F_BEGIN) {
2538 * Allocate arrays (#0..8) that will contain the graphs data
2539 * and the min/max values.
2540 * Also allocate one additional array (#9) for each interface:
2541 * out + 9 will contain the interface name,
2542 * outsize + 9 will contain a positive value (TRUE) if the interface
2543 * has either still not been registered, or has been unregistered.
2545 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
2548 if (action & F_MAIN) {
2549 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2550 restart = svg_p->restart;
2552 * Mark previously registered interfaces as now
2553 * possibly unregistered for all graphs.
2555 for (k = 0; k < svg_p->nr_max; k++) {
2556 unregistered = outsize + k * 10 + 9;
2557 if (*unregistered == FALSE) {
2558 *unregistered = MAYBE;
2562 /* For each network interfaces structure */
2563 for (i = 0; i < a->nr[curr]; i++) {
2564 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2565 if (!strcmp(snedc->interface, ""))
2566 /* Empty structure: This is the end of the list */
2569 if (dlst_iface_idx) {
2570 /* A list of devices has been entered on the command line */
2571 if (!search_sa_dlist(st_iface_list, dlst_iface_idx, snedc->interface))
2572 /* Device not found */
2576 /* Look for corresponding graph */
2577 for (k = 0; k < svg_p->nr_max; k++) {
2578 item_name = *(out + k * 10 + 9);
2579 if (!strcmp(snedc->interface, item_name))
2583 if (k == svg_p->nr_max) {
2584 /* Graph not found: Look for first free entry */
2585 for (k = 0; k < svg_p->nr_max; k++) {
2586 item_name = *(out + k * 10 + 9);
2587 if (!strcmp(item_name, ""))
2590 if (k == svg_p->nr_max) {
2591 /* No free graph entry: Extend all buffers */
2592 reallocate_all_graph_lines(svg_p->nr_max,
2593 &out, &outsize, &spmin, &spmax);
2599 unregistered = outsize + pos + 9;
2601 j = check_net_edev_reg(a, curr, !curr, i);
2603 /* This is a newly registered interface. Previous stats are zero */
2607 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2611 * If current interface was marked as previously unregistered,
2612 * then set restart variable to TRUE so that the graph will be
2613 * discontinuous, and mark it as now registered.
2615 if (*unregistered == TRUE) {
2618 *unregistered = FALSE;
2620 if (!item_name[0]) {
2621 /* Save network interface name (if not already done) */
2622 strncpy(item_name, snedc->interface, CHUNKSIZE);
2623 item_name[CHUNKSIZE - 1] = '\0';
2626 /* Check for min/max values */
2627 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2628 itv, spmin + pos, spmax + pos, g_fields);
2631 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2632 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2633 out + pos, outsize + pos, restart);
2635 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2636 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2637 out + pos + 1, outsize + pos + 1, restart);
2639 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2640 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2641 out + pos + 2, outsize + pos + 2, restart);
2643 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2644 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2645 out + pos + 3, outsize + pos + 3, restart);
2647 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2648 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2649 out + pos + 4, outsize + pos + 4, restart);
2651 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2652 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2653 out + pos + 5, outsize + pos + 5, restart);
2655 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2656 S_VALUE(snedp->collisions, snedc->collisions, itv),
2657 out + pos + 6, outsize + pos + 6, restart);
2659 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2660 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2661 out + pos + 7, outsize + pos + 7, restart);
2663 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2664 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2665 out + pos + 8, outsize + pos + 8, restart);
2668 /* Mark interfaces not seen here as now unregistered */
2669 for (k = 0; k < svg_p->nr_max; k++) {
2670 unregistered = outsize + k * 10 + 9;
2671 if (*unregistered != FALSE) {
2672 *unregistered = TRUE;
2677 if (action & F_END) {
2680 for (i = 0; i < svg_p->nr_max; i++) {
2682 * Check if there is something to display.
2683 * Don't test snedc->interface because maybe the network
2684 * interface has been registered later.
2690 item_name = *(out + pos + 9);
2691 if (draw_activity_graphs(a->g_nr, g_type,
2692 title, g_title, item_name, group,
2693 spmin + pos, spmax + pos, out + pos, outsize + pos,
2694 svg_p, record_hdr, FALSE, a->id, xid)) {
2699 /* Free remaining structures */
2700 free_graphs(out, outsize, spmin, spmax);
2705 ***************************************************************************
2706 * Display NFS client statistics in SVG.
2709 * @a Activity structure with statistics.
2710 * @curr Index in array for current sample statistics.
2711 * @action Action expected from current function.
2712 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2713 * flag indicating that a restart record has been previously
2714 * found (.@restart) and time used for the X axis origin
2716 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2717 * @record_hdr Pointer on record header of current stats sample.
2718 ***************************************************************************
2720 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2721 unsigned long long itv, struct record_header *record_hdr)
2723 struct stats_net_nfs
2724 *snnc = (struct stats_net_nfs *) a->buf[curr],
2725 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2726 int group[] = {2, 2, 2};
2727 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2728 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2729 "NFS client statistics (3)"};
2730 char *g_title[] = {"call/s", "retrans/s",
2731 "read/s", "write/s",
2732 "access/s", "getatt/s"};
2733 int g_fields[] = {0, 1, 2, 3, 4, 5};
2734 static double *spmin, *spmax;
2736 static int *outsize;
2738 if (action & F_BEGIN) {
2740 * Allocate arrays that will contain the graphs data
2741 * and the min/max values.
2743 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2746 if (action & F_MAIN) {
2747 /* Check for min/max values */
2748 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2749 itv, spmin, spmax, g_fields);
2752 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2753 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2754 out, outsize, svg_p->restart);
2756 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2757 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2758 out + 1, outsize + 1, svg_p->restart);
2760 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2761 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2762 out + 2, outsize + 2, svg_p->restart);
2764 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2765 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2766 out + 3, outsize + 3, svg_p->restart);
2768 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2769 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2770 out + 4, outsize + 4, svg_p->restart);
2772 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2773 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2774 out + 5, outsize + 5, svg_p->restart);
2777 if (action & F_END) {
2778 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2779 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2781 /* Free remaining structures */
2782 free_graphs(out, outsize, spmin, spmax);
2787 ***************************************************************************
2788 * Display NFS server statistics in SVG.
2791 * @a Activity structure with statistics.
2792 * @curr Index in array for current sample statistics.
2793 * @action Action expected from current function.
2794 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2795 * flag indicating that a restart record has been previously
2796 * found (.@restart) and time used for the X axis origin
2798 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2799 * @record_hdr Pointer on record header of current stats sample.
2800 ***************************************************************************
2802 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2803 unsigned long long itv, struct record_header *record_hdr)
2805 struct stats_net_nfsd
2806 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2807 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2808 int group[] = {2, 3, 2, 2, 2};
2809 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2810 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2811 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2812 "NFS server statistics (3)", "NFS server statistics (4)",
2813 "NFS server statistics (5)"};
2814 char *g_title[] = {"scall/s", "badcall/s",
2815 "packet/s", "udp/s", "tcp/s",
2817 "sread/s", "swrite/s",
2818 "saccess/s", "sgetatt/s"};
2819 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2820 static double *spmin, *spmax;
2822 static int *outsize;
2824 if (action & F_BEGIN) {
2826 * Allocate arrays that will contain the graphs data
2827 * and the min/max values.
2829 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2832 if (action & F_MAIN) {
2833 /* Check for min/max values */
2834 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2835 itv, spmin, spmax, g_fields);
2838 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2839 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2840 out, outsize, svg_p->restart);
2842 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2843 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2844 out + 1, outsize + 1, svg_p->restart);
2846 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2847 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2848 out + 2, outsize + 2, svg_p->restart);
2850 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2851 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2852 out + 3, outsize + 3, svg_p->restart);
2854 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2855 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2856 out + 4, outsize + 4, svg_p->restart);
2858 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2859 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2860 out + 5, outsize + 5, svg_p->restart);
2862 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2863 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2864 out + 6, outsize + 6, svg_p->restart);
2866 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2867 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2868 out + 7, outsize + 7, svg_p->restart);
2870 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2871 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2872 out + 8, outsize + 8, svg_p->restart);
2874 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2875 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2876 out + 9, outsize + 9, svg_p->restart);
2878 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2879 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2880 out + 10, outsize + 10, svg_p->restart);
2883 if (action & F_END) {
2884 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2885 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2887 /* Free remaining structures */
2888 free_graphs(out, outsize, spmin, spmax);
2893 ***************************************************************************
2894 * Display socket statistics in SVG.
2897 * @a Activity structure with statistics.
2898 * @curr Index in array for current sample statistics.
2899 * @action Action expected from current function.
2900 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2901 * flag indicating that a restart record has been previously
2902 * found (.@restart) and time used for the X axis origin
2904 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2905 * @record_hdr Pointer on record header of current stats sample.
2906 ***************************************************************************
2908 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2909 unsigned long long itv, struct record_header *record_hdr)
2911 struct stats_net_sock
2912 *snsc = (struct stats_net_sock *) a->buf[curr];
2913 int group[] = {1, 5};
2914 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2915 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2916 char *g_title[] = {"~totsck",
2917 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2918 int g_fields[] = {0, 1, 5, 2, 3, 4};
2919 static double *spmin, *spmax;
2921 static int *outsize;
2923 if (action & F_BEGIN) {
2925 * Allocate arrays that will contain the graphs data
2926 * and the min/max values.
2928 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2931 if (action & F_MAIN) {
2932 /* Check for min/max values */
2933 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2934 itv, spmin, spmax, g_fields);
2936 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2937 (unsigned long long) snsc->sock_inuse,
2938 out, outsize, svg_p->restart);
2940 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2941 (unsigned long long) snsc->tcp_inuse,
2942 out + 1, outsize + 1, svg_p->restart);
2944 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2945 (unsigned long long) snsc->udp_inuse,
2946 out + 2, outsize + 2, svg_p->restart);
2948 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2949 (unsigned long long) snsc->raw_inuse,
2950 out + 3, outsize + 3, svg_p->restart);
2952 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2953 (unsigned long long) snsc->frag_inuse,
2954 out + 4, outsize + 4, svg_p->restart);
2956 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2957 (unsigned long long) snsc->tcp_tw,
2958 out + 5, outsize + 5, svg_p->restart);
2961 if (action & F_END) {
2962 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2963 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2965 /* Free remaining structures */
2966 free_graphs(out, outsize, spmin, spmax);
2971 ***************************************************************************
2972 * Display IPv4 traffic statistics in SVG.
2975 * @a Activity structure with statistics.
2976 * @curr Index in array for current sample statistics.
2977 * @action Action expected from current function.
2978 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2979 * flag indicating that a restart record has been previously
2980 * found (.@restart) and time used for the X axis origin
2982 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2983 * @record_hdr Pointer on record header of current stats sample.
2984 ***************************************************************************
2986 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2987 unsigned long long itv, struct record_header *record_hdr)
2990 *snic = (struct stats_net_ip *) a->buf[curr],
2991 *snip = (struct stats_net_ip *) a->buf[!curr];
2992 int group[] = {4, 2, 2};
2993 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2994 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
2995 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2996 "asmrq/s", "asmok/s",
2997 "fragok/s", "fragcrt/s"};
2998 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2999 static double *spmin, *spmax;
3001 static int *outsize;
3003 if (action & F_BEGIN) {
3005 * Allocate arrays that will contain the graphs data
3006 * and the min/max values.
3008 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3011 if (action & F_MAIN) {
3012 /* Check for min/max values */
3013 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3014 itv, spmin, spmax, g_fields);
3017 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3018 S_VALUE(snip->InReceives, snic->InReceives, itv),
3019 out, outsize, svg_p->restart);
3021 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3022 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
3023 out + 1, outsize + 1, svg_p->restart);
3025 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3026 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
3027 out + 2, outsize + 2, svg_p->restart);
3029 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3030 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3031 out + 3, outsize + 3, svg_p->restart);
3033 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3034 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3035 out + 4, outsize + 4, svg_p->restart);
3037 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3038 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3039 out + 5, outsize + 5, svg_p->restart);
3041 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3042 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3043 out + 6, outsize + 6, svg_p->restart);
3045 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3046 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3047 out + 7, outsize + 7, svg_p->restart);
3050 if (action & F_END) {
3051 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3052 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3054 /* Free remaining structures */
3055 free_graphs(out, outsize, spmin, spmax);
3060 ***************************************************************************
3061 * Display IPv4 traffic errors statistics in SVG.
3064 * @a Activity structure with statistics.
3065 * @curr Index in array for current sample statistics.
3066 * @action Action expected from current function.
3067 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3068 * flag indicating that a restart record has been previously
3069 * found (.@restart) and time used for the X axis origin
3071 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3072 * @record_hdr Pointer on record header of current stats sample.
3073 ***************************************************************************
3075 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3076 unsigned long long itv, struct record_header *record_hdr)
3078 struct stats_net_eip
3079 *sneic = (struct stats_net_eip *) a->buf[curr],
3080 *sneip = (struct stats_net_eip *) a->buf[!curr];
3081 int group[] = {3, 2, 3};
3082 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3083 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3084 "IPv4 traffic errors statistics (3)"};
3085 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3086 "idisc/s", "odisc/s",
3087 "onort/s", "asmf/s", "fragf/s"};
3088 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3089 static double *spmin, *spmax;
3091 static int *outsize;
3093 if (action & F_BEGIN) {
3095 * Allocate arrays that will contain the graphs data
3096 * and the min/max values.
3098 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3101 if (action & F_MAIN) {
3102 /* Check for min/max values */
3103 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3104 itv, spmin, spmax, g_fields);
3107 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3108 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3109 out, outsize, svg_p->restart);
3111 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3112 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3113 out + 1, outsize + 1, svg_p->restart);
3115 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3116 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3117 out + 2, outsize + 2, svg_p->restart);
3119 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3120 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3121 out + 3, outsize + 3, svg_p->restart);
3123 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3124 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3125 out + 4, outsize + 4, svg_p->restart);
3127 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3128 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3129 out + 5, outsize + 5, svg_p->restart);
3131 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3132 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3133 out + 6, outsize + 6, svg_p->restart);
3135 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3136 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3137 out + 7, outsize + 7, svg_p->restart);
3140 if (action & F_END) {
3141 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3142 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3144 /* Free remaining structures */
3145 free_graphs(out, outsize, spmin, spmax);
3150 ***************************************************************************
3151 * Display ICMPv4 traffic statistics in SVG.
3154 * @a Activity structure with statistics.
3155 * @curr Index in array for current sample statistics.
3156 * @action Action expected from current function.
3157 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3158 * flag indicating that a restart record has been previously
3159 * found (.@restart) and time used for the X axis origin
3161 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3162 * @record_hdr Pointer on record header of current stats sample.
3163 ***************************************************************************
3165 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3166 unsigned long long itv, struct record_header *record_hdr)
3168 struct stats_net_icmp
3169 *snic = (struct stats_net_icmp *) a->buf[curr],
3170 *snip = (struct stats_net_icmp *) a->buf[!curr];
3171 int group[] = {2, 4, 4, 4};
3172 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3174 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3175 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3176 char *g_title[] = {"imsg/s", "omsg/s",
3177 "iech/s", "iechr/s", "oech/s", "oechr/s",
3178 "itm/s", "itmr/s", "otm/s", "otmr/s",
3179 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3180 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3181 static double *spmin, *spmax;
3183 static int *outsize;
3185 if (action & F_BEGIN) {
3187 * Allocate arrays that will contain the graphs data
3188 * and the min/max values.
3190 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3193 if (action & F_MAIN) {
3194 /* Check for min/max values */
3195 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3196 itv, spmin, spmax, g_fields);
3199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3200 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3201 out, outsize, svg_p->restart);
3203 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3204 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3205 out + 1, outsize + 1, svg_p->restart);
3207 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3208 S_VALUE(snip->InEchos, snic->InEchos, itv),
3209 out + 2, outsize + 2, svg_p->restart);
3211 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3212 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3213 out + 3, outsize + 3, svg_p->restart);
3215 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3216 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3217 out + 4, outsize + 4, svg_p->restart);
3219 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3220 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3221 out + 5, outsize + 5, svg_p->restart);
3223 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3224 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3225 out + 6, outsize + 6, svg_p->restart);
3227 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3228 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3229 out + 7, outsize + 7, svg_p->restart);
3231 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3232 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3233 out + 8, outsize + 8, svg_p->restart);
3235 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3236 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3237 out + 9, outsize + 9, svg_p->restart);
3239 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3240 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3241 out + 10, outsize + 10, svg_p->restart);
3243 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3244 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3245 out + 11, outsize + 11, svg_p->restart);
3247 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3248 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3249 out + 12, outsize + 12, svg_p->restart);
3251 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3252 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3253 out + 13, outsize + 13, svg_p->restart);
3256 if (action & F_END) {
3257 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3258 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3260 /* Free remaining structures */
3261 free_graphs(out, outsize, spmin, spmax);
3266 ***************************************************************************
3267 * Display ICMPv4 traffic errors statistics in SVG.
3270 * @a Activity structure with statistics.
3271 * @curr Index in array for current sample statistics.
3272 * @action Action expected from current function.
3273 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3274 * flag indicating that a restart record has been previously
3275 * found (.@restart) and time used for the X axis origin
3277 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3278 * @record_hdr Pointer on record header of current stats sample.
3279 ***************************************************************************
3281 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3282 unsigned long long itv, struct record_header *record_hdr)
3284 struct stats_net_eicmp
3285 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3286 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3287 int group[] = {2, 2, 2, 2, 2, 2};
3288 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3289 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3290 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3291 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3292 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3293 char *g_title[] = {"ierr/s", "oerr/s",
3294 "idstunr/s", "odstunr/s",
3295 "itmex/s", "otmex/s",
3296 "iparmpb/s", "oparmpb/s",
3297 "isrcq/s", "osrcq/s",
3298 "iredir/s", "oredir/s"};
3299 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3300 static double *spmin, *spmax;
3302 static int *outsize;
3304 if (action & F_BEGIN) {
3306 * Allocate arrays that will contain the graphs data
3307 * and the min/max values.
3309 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3312 if (action & F_MAIN) {
3313 /* Check for min/max values */
3314 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3315 itv, spmin, spmax, g_fields);
3318 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3319 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3320 out, outsize, svg_p->restart);
3322 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3323 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3324 out + 1, outsize + 1, svg_p->restart);
3326 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3327 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3328 out + 2, outsize + 2, svg_p->restart);
3330 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3331 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3332 out + 3, outsize + 3, svg_p->restart);
3334 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3335 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3336 out + 4, outsize + 4, svg_p->restart);
3338 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3339 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3340 out + 5, outsize + 5, svg_p->restart);
3342 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3343 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3344 out + 6, outsize + 6, svg_p->restart);
3346 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3347 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3348 out + 7, outsize + 7, svg_p->restart);
3350 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3351 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3352 out + 8, outsize + 8, svg_p->restart);
3354 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3355 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3356 out + 9, outsize + 9, svg_p->restart);
3358 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3359 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3360 out + 10, outsize + 10, svg_p->restart);
3362 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3363 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3364 out + 11, outsize + 11, svg_p->restart);
3367 if (action & F_END) {
3368 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3369 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3371 /* Free remaining structures */
3372 free_graphs(out, outsize, spmin, spmax);
3377 ***************************************************************************
3378 * Display TCPv4 traffic statistics in SVG.
3381 * @a Activity structure with statistics.
3382 * @curr Index in array for current sample statistics.
3383 * @action Action expected from current function.
3384 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3385 * flag indicating that a restart record has been previously
3386 * found (.@restart) and time used for the X axis origin
3388 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3389 * @record_hdr Pointer on record header of current stats sample.
3390 ***************************************************************************
3392 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3393 unsigned long long itv, struct record_header *record_hdr)
3395 struct stats_net_tcp
3396 *sntc = (struct stats_net_tcp *) a->buf[curr],
3397 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3398 int group[] = {2, 2};
3399 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3400 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3401 char *g_title[] = {"active/s", "passive/s",
3402 "iseg/s", "oseg/s"};
3403 int g_fields[] = {0, 1, 2, 3};
3404 static double *spmin, *spmax;
3406 static int *outsize;
3408 if (action & F_BEGIN) {
3410 * Allocate arrays that will contain the graphs data
3411 * and the min/max values.
3413 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3416 if (action & F_MAIN) {
3417 /* Check for min/max values */
3418 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3419 itv, spmin, spmax, g_fields);
3422 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3423 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3424 out, outsize, svg_p->restart);
3426 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3427 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3428 out + 1, outsize + 1, svg_p->restart);
3430 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3431 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3432 out + 2, outsize + 2, svg_p->restart);
3434 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3435 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3436 out + 3, outsize + 3, svg_p->restart);
3439 if (action & F_END) {
3440 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3441 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3443 /* Free remaining structures */
3444 free_graphs(out, outsize, spmin, spmax);
3449 ***************************************************************************
3450 * Display TCPv4 traffic errors statistics in SVG.
3453 * @a Activity structure with statistics.
3454 * @curr Index in array for current sample statistics.
3455 * @action Action expected from current function.
3456 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3457 * flag indicating that a restart record has been previously
3458 * found (.@restart) and time used for the X axis origin
3460 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3461 * @record_hdr Pointer on record header of current stats sample.
3462 ***************************************************************************
3464 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3465 unsigned long long itv, struct record_header *record_hdr)
3467 struct stats_net_etcp
3468 *snetc = (struct stats_net_etcp *) a->buf[curr],
3469 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3470 int group[] = {2, 3};
3471 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3472 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3473 char *g_title[] = {"atmptf/s", "estres/s",
3474 "retrans/s", "isegerr/s", "orsts/s"};
3475 int g_fields[] = {0, 1, 2, 3, 4};
3476 static double *spmin, *spmax;
3478 static int *outsize;
3480 if (action & F_BEGIN) {
3482 * Allocate arrays that will contain the graphs data
3483 * and the min/max values.
3485 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3488 if (action & F_MAIN) {
3489 /* Check for min/max values */
3490 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3491 itv, spmin, spmax, g_fields);
3494 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3495 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3496 out, outsize, svg_p->restart);
3498 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3499 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3500 out + 1, outsize + 1, svg_p->restart);
3502 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3503 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3504 out + 2, outsize + 2, svg_p->restart);
3506 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3507 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3508 out + 3, outsize + 3, svg_p->restart);
3510 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3511 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3512 out + 4, outsize + 4, svg_p->restart);
3515 if (action & F_END) {
3516 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3517 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3519 /* Free remaining structures */
3520 free_graphs(out, outsize, spmin, spmax);
3525 ***************************************************************************
3526 * Display UDPv4 traffic statistics in SVG.
3529 * @a Activity structure with statistics.
3530 * @curr Index in array for current sample statistics.
3531 * @action Action expected from current function.
3532 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3533 * flag indicating that a restart record has been previously
3534 * found (.@restart) and time used for the X axis origin
3536 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3537 * @record_hdr Pointer on record header of current stats sample.
3538 ***************************************************************************
3540 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3541 unsigned long long itv, struct record_header *record_hdr)
3543 struct stats_net_udp
3544 *snuc = (struct stats_net_udp *) a->buf[curr],
3545 *snup = (struct stats_net_udp *) a->buf[!curr];
3546 int group[] = {2, 2};
3547 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3548 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3549 char *g_title[] = {"idgm/s", "odgm/s",
3550 "noport/s", "idgmerr/s"};
3551 int g_fields[] = {0, 1, 2, 3};
3552 static double *spmin, *spmax;
3554 static int *outsize;
3556 if (action & F_BEGIN) {
3558 * Allocate arrays that will contain the graphs data
3559 * and the min/max values.
3561 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3564 if (action & F_MAIN) {
3565 /* Check for min/max values */
3566 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3567 itv, spmin, spmax, g_fields);
3570 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3571 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3572 out, outsize, svg_p->restart);
3574 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3575 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3576 out + 1, outsize + 1, svg_p->restart);
3578 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3579 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3580 out + 2, outsize + 2, svg_p->restart);
3582 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3583 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3584 out + 3, outsize + 3, svg_p->restart);
3587 if (action & F_END) {
3588 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3589 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3591 /* Free remaining structures */
3592 free_graphs(out, outsize, spmin, spmax);
3597 ***************************************************************************
3598 * Display IPV6 socket statistics in SVG.
3601 * @a Activity structure with statistics.
3602 * @curr Index in array for current sample statistics.
3603 * @action Action expected from current function.
3604 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3605 * flag indicating that a restart record has been previously
3606 * found (.@restart) and time used for the X axis origin
3608 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3609 * @record_hdr Pointer on record header of current stats sample.
3610 ***************************************************************************
3612 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3613 unsigned long long itv, struct record_header *record_hdr)
3615 struct stats_net_sock6
3616 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3618 int g_type[] = {SVG_LINE_GRAPH};
3619 char *title[] = {"IPv6 sockets statistics"};
3620 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3621 int g_fields[] = {0, 1, 2, 3};
3622 static double *spmin, *spmax;
3624 static int *outsize;
3626 if (action & F_BEGIN) {
3628 * Allocate arrays that will contain the graphs data
3629 * and the min/max values.
3631 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3634 if (action & F_MAIN) {
3635 /* Check for min/max values */
3636 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3637 itv, spmin, spmax, g_fields);
3639 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3640 (unsigned long long) snsc->tcp6_inuse,
3641 out, outsize, svg_p->restart);
3643 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3644 (unsigned long long) snsc->udp6_inuse,
3645 out + 1, outsize + 1, svg_p->restart);
3647 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3648 (unsigned long long) snsc->raw6_inuse,
3649 out + 2, outsize + 2, svg_p->restart);
3651 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3652 (unsigned long long) snsc->frag6_inuse,
3653 out + 3, outsize + 3, svg_p->restart);
3656 if (action & F_END) {
3657 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3658 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3660 /* Free remaining structures */
3661 free_graphs(out, outsize, spmin, spmax);
3666 ***************************************************************************
3667 * Display IPv6 traffic statistics in SVG.
3670 * @a Activity structure with statistics.
3671 * @curr Index in array for current sample statistics.
3672 * @action Action expected from current function.
3673 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3674 * flag indicating that a restart record has been previously
3675 * found (.@restart) and time used for the X axis origin
3677 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3678 * @record_hdr Pointer on record header of current stats sample.
3679 ***************************************************************************
3681 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3682 unsigned long long itv, struct record_header *record_hdr)
3684 struct stats_net_ip6
3685 *snic = (struct stats_net_ip6 *) a->buf[curr],
3686 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3687 int group[] = {4, 2, 2, 2};
3688 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3690 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3691 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3692 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3693 "asmrq6/s", "asmok6/s",
3694 "imcpck6/s", "omcpck6/s",
3695 "fragok6/s", "fragcr6/s"};
3696 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3697 static double *spmin, *spmax;
3699 static int *outsize;
3701 if (action & F_BEGIN) {
3703 * Allocate arrays that will contain the graphs data
3704 * and the min/max values.
3706 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3709 if (action & F_MAIN) {
3710 /* Check for min/max values */
3711 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3712 itv, spmin, spmax, g_fields);
3715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3716 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3717 out, outsize, svg_p->restart);
3719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3720 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3721 out + 1, outsize + 1, svg_p->restart);
3723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3724 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3725 out + 2, outsize + 2, svg_p->restart);
3727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3728 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3729 out + 3, outsize + 3, svg_p->restart);
3731 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3732 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3733 out + 4, outsize + 4, svg_p->restart);
3735 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3736 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3737 out + 5, outsize + 5, svg_p->restart);
3739 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3740 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3741 out + 6, outsize + 6, svg_p->restart);
3743 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3744 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3745 out + 7, outsize + 7, svg_p->restart);
3747 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3748 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3749 out + 8, outsize + 8, svg_p->restart);
3751 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3752 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3753 out + 9, outsize + 9, svg_p->restart);
3756 if (action & F_END) {
3757 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3758 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3760 /* Free remaining structures */
3761 free_graphs(out, outsize, spmin, spmax);
3766 ***************************************************************************
3767 * Display IPv6 traffic errors statistics in SVG.
3770 * @a Activity structure with statistics.
3771 * @curr Index in array for current sample statistics.
3772 * @action Action expected from current function.
3773 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3774 * flag indicating that a restart record has been previously
3775 * found (.@restart) and time used for the X axis origin
3777 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3778 * @record_hdr Pointer on record header of current stats sample.
3779 ***************************************************************************
3781 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3782 unsigned long long itv, struct record_header *record_hdr)
3784 struct stats_net_eip6
3785 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3786 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3787 int group[] = {4, 2, 2, 3};
3788 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3790 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3791 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3792 "IPv6 traffic errors statistics (5)"};
3793 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3794 "idisc6/s", "odisc6/s",
3795 "inort6/s", "onort6/s",
3796 "asmf6/s", "fragf6/s", "itrpck6/s"};
3797 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3798 static double *spmin, *spmax;
3800 static int *outsize;
3802 if (action & F_BEGIN) {
3804 * Allocate arrays that will contain the graphs data
3805 * and the min/max values.
3807 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3810 if (action & F_MAIN) {
3811 /* Check for min/max values */
3812 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3813 itv, spmin, spmax, g_fields);
3816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3817 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3818 out, outsize, svg_p->restart);
3820 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3821 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3822 out + 1, outsize + 1, svg_p->restart);
3824 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3825 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3826 out + 2, outsize + 2, svg_p->restart);
3828 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3829 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3830 out + 3, outsize + 3, svg_p->restart);
3832 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3833 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3834 out + 4, outsize + 4, svg_p->restart);
3836 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3837 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3838 out + 5, outsize + 5, svg_p->restart);
3840 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3841 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3842 out + 6, outsize + 6, svg_p->restart);
3844 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3845 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3846 out + 7, outsize + 7, svg_p->restart);
3848 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3849 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3850 out + 8, outsize + 8, svg_p->restart);
3852 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3853 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3854 out + 9, outsize + 9, svg_p->restart);
3856 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3857 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3858 out + 10, outsize + 10, svg_p->restart);
3861 if (action & F_END) {
3862 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3863 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3865 /* Free remaining structures */
3866 free_graphs(out, outsize, spmin, spmax);
3871 ***************************************************************************
3872 * Display ICMPv6 traffic statistics in SVG.
3875 * @a Activity structure with statistics.
3876 * @curr Index in array for current sample statistics.
3877 * @action Action expected from current function.
3878 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3879 * flag indicating that a restart record has been previously
3880 * found (.@restart) and time used for the X axis origin
3882 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3883 * @record_hdr Pointer on record header of current stats sample.
3884 ***************************************************************************
3886 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3887 unsigned long long itv, struct record_header *record_hdr)
3889 struct stats_net_icmp6
3890 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3891 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3892 int group[] = {2, 3, 5, 3, 4};
3893 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3894 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3895 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3896 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3897 "ICMPv6 traffic statistics (5)"};
3898 char *g_title[] = {"imsg6/s", "omsg6/s",
3899 "iech6/s", "iechr6/s", "oechr6/s",
3900 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3901 "irtsol6/s", "ortsol6/s", "irtad6/s",
3902 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3903 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3904 static double *spmin, *spmax;
3906 static int *outsize;
3908 if (action & F_BEGIN) {
3910 * Allocate arrays that will contain the graphs data
3911 * and the min/max values.
3913 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3916 if (action & F_MAIN) {
3917 /* Check for min/max values */
3918 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3919 itv, spmin, spmax, g_fields);
3922 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3923 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3924 out, outsize, svg_p->restart);
3926 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3927 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3928 out + 1, outsize + 1, svg_p->restart);
3930 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3931 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3932 out + 2, outsize + 2, svg_p->restart);
3934 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3935 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3936 out + 3, outsize + 3, svg_p->restart);
3938 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3939 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3940 out + 4, outsize + 4, svg_p->restart);
3942 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3943 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3944 out + 5, outsize + 5, svg_p->restart);
3946 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3947 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3948 out + 6, outsize + 6, svg_p->restart);
3950 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3951 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3952 out + 7, outsize + 7, svg_p->restart);
3954 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3955 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3956 out + 8, outsize + 8, svg_p->restart);
3958 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3959 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3960 out + 9, outsize + 9, svg_p->restart);
3962 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3963 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3964 out + 10, outsize + 10, svg_p->restart);
3966 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3967 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3968 out + 11, outsize + 11, svg_p->restart);
3970 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3971 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3972 out + 12, outsize + 12, svg_p->restart);
3974 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3975 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
3976 out + 13, outsize + 13, svg_p->restart);
3978 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3979 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3980 out + 14, outsize + 14, svg_p->restart);
3982 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3983 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3984 out + 15, outsize + 15, svg_p->restart);
3986 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3987 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3988 out + 16, outsize + 16, svg_p->restart);
3991 if (action & F_END) {
3992 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3993 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3995 /* Free remaining structures */
3996 free_graphs(out, outsize, spmin, spmax);
4001 ***************************************************************************
4002 * Display ICMPv6 traffic errors statistics in SVG.
4005 * @a Activity structure with statistics.
4006 * @curr Index in array for current sample statistics.
4007 * @action Action expected from current function.
4008 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4009 * flag indicating that a restart record has been previously
4010 * found (.@restart) and time used for the X axis origin
4012 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4013 * @record_hdr Pointer on record header of current stats sample.
4014 ***************************************************************************
4016 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4017 unsigned long long itv, struct record_header *record_hdr)
4019 struct stats_net_eicmp6
4020 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
4021 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
4022 int group[] = {1, 2, 2, 2, 2, 2};
4023 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4024 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4025 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
4026 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
4027 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
4028 char *g_title[] = {"ierr6/s",
4029 "idtunr6/s", "odtunr6/s",
4030 "itmex6/s", "otmex6/s",
4031 "iprmpb6/s", "oprmpb6/s",
4032 "iredir6/s", "oredir6/s",
4033 "ipck2b6/s", "opck2b6/s"};
4034 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4035 static double *spmin, *spmax;
4037 static int *outsize;
4039 if (action & F_BEGIN) {
4041 * Allocate arrays that will contain the graphs data
4042 * and the min/max values.
4044 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4047 if (action & F_MAIN) {
4048 /* Check for min/max values */
4049 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4050 itv, spmin, spmax, g_fields);
4053 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4054 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4055 out, outsize, svg_p->restart);
4057 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4058 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4059 out + 1, outsize + 1, svg_p->restart);
4061 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4062 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4063 out + 2, outsize + 2, svg_p->restart);
4065 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4066 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4067 out + 3, outsize + 3, svg_p->restart);
4069 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4070 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4071 out + 4, outsize + 4, svg_p->restart);
4073 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4074 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4075 out + 5, outsize + 5, svg_p->restart);
4077 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4078 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4079 out + 6, outsize + 6, svg_p->restart);
4081 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4082 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4083 out + 7, outsize + 7, svg_p->restart);
4085 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4086 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4087 out + 8, outsize + 8, svg_p->restart);
4089 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4090 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4091 out + 9, outsize + 9, svg_p->restart);
4093 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4094 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4095 out + 10, outsize + 10, svg_p->restart);
4098 if (action & F_END) {
4099 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4100 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4102 /* Free remaining structures */
4103 free_graphs(out, outsize, spmin, spmax);
4108 ***************************************************************************
4109 * Display UDPv6 traffic statistics in SVG.
4112 * @a Activity structure with statistics.
4113 * @curr Index in array for current sample statistics.
4114 * @action Action expected from current function.
4115 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4116 * flag indicating that a restart record has been previously
4117 * found (.@restart) and time used for the X axis origin
4119 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4120 * @record_hdr Pointer on record header of current stats sample.
4121 ***************************************************************************
4123 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4124 unsigned long long itv, struct record_header *record_hdr)
4126 struct stats_net_udp6
4127 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4128 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4129 int group[] = {2, 2};
4130 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4131 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4132 char *g_title[] = {"idgm6/s", "odgm6/s",
4133 "noport6/s", "idgmer6/s"};
4134 int g_fields[] = {0, 1, 2, 3};
4135 static double *spmin, *spmax;
4137 static int *outsize;
4139 if (action & F_BEGIN) {
4141 * Allocate arrays that will contain the graphs data
4142 * and the min/max values.
4144 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4147 if (action & F_MAIN) {
4148 /* Check for min/max values */
4149 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4150 itv, spmin, spmax, g_fields);
4153 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4154 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4155 out, outsize, svg_p->restart);
4157 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4158 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4159 out + 1, outsize + 1, svg_p->restart);
4161 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4162 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4163 out + 2, outsize + 2, svg_p->restart);
4165 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4166 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4167 out + 3, outsize + 3, svg_p->restart);
4170 if (action & F_END) {
4171 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4172 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4174 /* Free remaining structures */
4175 free_graphs(out, outsize, spmin, spmax);
4180 ***************************************************************************
4181 * Display CPU frequency statistics in SVG.
4184 * @a Activity structure with statistics.
4185 * @curr Index in array for current sample statistics.
4186 * @action Action expected from current function.
4187 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4188 * flag indicating that a restart record has been previously
4189 * found (.@restart) and time used for the X axis origin
4191 * @itv Interval of time in 1/100th of a second (unused here).
4192 * @record_hdr Pointer on record header of current stats sample.
4193 ***************************************************************************
4195 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4196 unsigned long long itv, struct record_header *record_hdr)
4198 struct stats_pwr_cpufreq *spc, *spp;
4200 int g_type[] = {SVG_LINE_GRAPH};
4201 char *title[] = {"CPU clock frequency"};
4202 char *g_title[] = {"MHz"};
4203 static double *spmin, *spmax;
4205 static int *outsize;
4209 if (action & F_BEGIN) {
4211 * Allocate arrays that will contain the graphs data
4212 * and the min/max values.
4214 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4217 if (action & F_MAIN) {
4219 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4221 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4222 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4224 /* Should current CPU (including CPU "all") be displayed? */
4225 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4230 * Note: Don't skip offline CPU here as it is needed
4231 * to make the graph go though 0.
4235 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4236 ((double) spp->cpufreq) / 100,
4237 ((double) spc->cpufreq) / 100,
4238 out + i, outsize + i, svg_p->restart, svg_p->dt,
4239 spmin + i, spmax + i);
4243 if (action & F_END) {
4246 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
4248 /* Should current CPU (including CPU "all") be displayed? */
4249 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4254 /* This is CPU "all" */
4255 strcpy(item_name, "all");
4259 * If the maximum frequency reached by the CPU is 0, then
4260 * the CPU has been offline on the whole period.
4261 * => Don't display it.
4263 if (*(spmax + i) == 0)
4266 sprintf(item_name, "%d", i - 1);
4269 if (draw_activity_graphs(a->g_nr, g_type,
4270 title, g_title, item_name, group,
4271 spmin + i, spmax + i, out + i, outsize + i,
4272 svg_p, record_hdr, i, a->id, xid)) {
4277 /* Free remaining structures */
4278 free_graphs(out, outsize, spmin, spmax);
4283 ***************************************************************************
4284 * Display fan statistics in SVG.
4287 * @a Activity structure with statistics.
4288 * @curr Index in array for current sample statistics.
4289 * @action Action expected from current function.
4290 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4291 * flag indicating that a restart record has been previously
4292 * found (.@restart) and time used for the X axis origin
4294 * @itv Interval of time in 1/100th of a second (unused here).
4295 * @record_hdr Pointer on record header of current stats sample.
4296 ***************************************************************************
4298 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4299 unsigned long long itv, struct record_header *record_hdr)
4301 struct stats_pwr_fan *spc, *spp;
4303 int g_type[] = {SVG_LINE_GRAPH};
4304 char *title[] = {"Fans speed"};
4305 char *g_title[] = {"~rpm"};
4306 static double *spmin, *spmax;
4308 static int *outsize;
4309 char item_name[MAX_SENSORS_DEV_LEN + 8];
4312 if (action & F_BEGIN) {
4314 * Allocate arrays that will contain the graphs data
4315 * and the min/max values.
4317 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4320 if (action & F_MAIN) {
4322 for (i = 0; i < a->nr[curr]; i++) {
4324 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4325 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4328 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4331 out + i, outsize + i, svg_p->restart, svg_p->dt,
4332 spmin + i, spmax + i);
4336 if (action & F_END) {
4339 for (i = 0; i < svg_p->nr_max; i++) {
4341 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4343 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4344 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4346 if (draw_activity_graphs(a->g_nr, g_type,
4347 title, g_title, item_name, group,
4348 spmin + i, spmax + i, out + i, outsize + i,
4349 svg_p, record_hdr, FALSE, a->id, xid)) {
4354 /* Free remaining structures */
4355 free_graphs(out, outsize, spmin, spmax);
4360 ***************************************************************************
4361 * Display temperature statistics in SVG.
4364 * @a Activity structure with statistics.
4365 * @curr Index in array for current sample statistics.
4366 * @action Action expected from current function.
4367 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4368 * flag indicating that a restart record has been previously
4369 * found (.@restart) and time used for the X axis origin
4371 * @itv Interval of time in 1/100th of a second (unused here).
4372 * @record_hdr Pointer on record header of current stats sample.
4373 ***************************************************************************
4375 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4376 unsigned long long itv, struct record_header *record_hdr)
4378 struct stats_pwr_temp *spc;
4379 int group[] = {1, 1};
4380 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4381 char *title[] = {"Devices temperature (1)",
4382 "Devices temperature (2)"};
4383 char *g_title[] = {"~degC",
4385 static double *spmin, *spmax;
4387 static int *outsize;
4388 char item_name[MAX_SENSORS_DEV_LEN + 8];
4392 if (action & F_BEGIN) {
4394 * Allocate arrays that will contain the graphs data
4395 * and the min/max values.
4397 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4400 if (action & F_MAIN) {
4401 /* For each temperature sensor */
4402 for (i = 0; i < a->nr[curr]; i++) {
4404 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4406 /* Look for min/max values */
4407 if (spc->temp < *(spmin + 2 * i)) {
4408 *(spmin + 2 * i) = spc->temp;
4410 if (spc->temp > *(spmax + 2 * i)) {
4411 *(spmax + 2 * i) = spc->temp;
4413 tval = (spc->temp_max - spc->temp_min) ?
4414 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4416 if (tval < *(spmin + 2 * i + 1)) {
4417 *(spmin + 2 * i + 1) = tval;
4419 if (tval > *(spmax + 2 * i + 1)) {
4420 *(spmax + 2 * i + 1) = tval;
4424 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4426 out + 2 * i, outsize + 2 * i, svg_p->restart);
4428 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4430 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4434 if (action & F_END) {
4437 for (i = 0; i < svg_p->nr_max; i++) {
4439 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4441 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4442 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4444 if (draw_activity_graphs(a->g_nr, g_type,
4445 title, g_title, item_name, group,
4446 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4447 svg_p, record_hdr, FALSE, a->id, xid)) {
4452 /* Free remaining structures */
4453 free_graphs(out, outsize, spmin, spmax);
4458 ***************************************************************************
4459 * Display voltage inputs statistics in SVG.
4462 * @a Activity structure with statistics.
4463 * @curr Index in array for current sample statistics.
4464 * @action Action expected from current function.
4465 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4466 * flag indicating that a restart record has been previously
4467 * found (.@restart) and time used for the X axis origin
4469 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4470 * @record_hdr Pointer on record header of current stats sample.
4471 ***************************************************************************
4473 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4474 unsigned long long itv, struct record_header *record_hdr)
4476 struct stats_pwr_in *spc;
4477 int group[] = {1, 1};
4478 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4479 char *title[] = {"Voltage inputs statistics (1)",
4480 "Voltage inputs statistics (2)"};
4481 char *g_title[] = {"inV",
4483 static double *spmin, *spmax;
4485 static int *outsize;
4486 char item_name[MAX_SENSORS_DEV_LEN + 8];
4490 if (action & F_BEGIN) {
4492 * Allocate arrays that will contain the graphs data
4493 * and the min/max values.
4495 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4498 if (action & F_MAIN) {
4499 /* For each voltage input sensor */
4500 for (i = 0; i < a->nr[curr]; i++) {
4502 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4504 /* Look for min/max values */
4505 if (spc->in < *(spmin + 2 * i)) {
4506 *(spmin + 2 * i) = spc->in;
4508 if (spc->in > *(spmax + 2 * i)) {
4509 *(spmax + 2 * i) = spc->in;
4511 tval = (spc->in_max - spc->in_min) ?
4512 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4514 if (tval < *(spmin + 2 * i + 1)) {
4515 *(spmin + 2 * i + 1) = tval;
4517 if (tval > *(spmax + 2 * i + 1)) {
4518 *(spmax + 2 * i + 1) = tval;
4522 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4524 out + 2 * i, outsize + 2 * i, svg_p->restart);
4526 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4528 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4532 if (action & F_END) {
4535 for (i = 0; i < svg_p->nr_max; i++) {
4537 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4539 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4540 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4542 if (draw_activity_graphs(a->g_nr, g_type,
4543 title, g_title, item_name, group,
4544 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4545 svg_p, record_hdr, FALSE, a->id, xid)) {
4550 /* Free remaining structures */
4551 free_graphs(out, outsize, spmin, spmax);
4556 ***************************************************************************
4557 * Display huge pages statistics in SVG.
4560 * @a Activity structure with statistics.
4561 * @curr Index in array for current sample statistics.
4562 * @action Action expected from current function.
4563 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4564 * flag indicating that a restart record has been previously
4565 * found (.@restart) and time used for the X axis origin
4567 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4568 * @record_hdr Pointer on record header of current stats sample.
4569 ***************************************************************************
4571 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4572 unsigned long long itv, struct record_header *record_hdr)
4575 *smc = (struct stats_huge *) a->buf[curr];
4576 int group[] = {2, 1};
4577 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4578 char *title[] = {"Huge pages utilization (1)",
4579 "Huge pages utilization (2)"};
4580 char *g_title[] = {"~kbhugfree", "~kbhugused",
4582 int g_fields[] = {0};
4583 unsigned int local_types_nr[] = {0, 1, 0};
4584 static double *spmin, *spmax;
4586 static int *outsize;
4589 if (action & F_BEGIN) {
4591 * Allocate arrays that will contain the graphs data
4592 * and the min/max values.
4594 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4597 if (action & F_MAIN) {
4598 /* Check for min/max values */
4599 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4600 itv, spmin, spmax, g_fields);
4602 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4603 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4605 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4606 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4608 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4609 if (tval < *(spmin + 2)) {
4610 *(spmin + 2) = tval;
4612 if (tval > *(spmax + 2)) {
4613 *(spmax + 2) = tval;
4617 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4618 (unsigned long long) smc->frhkb,
4619 out, outsize, svg_p->restart);
4621 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4622 (unsigned long long) smc->tlhkb - smc->frhkb,
4623 out + 1, outsize + 1, svg_p->restart);
4625 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4627 out + 2, outsize + 2, svg_p->dt);
4630 if (action & F_END) {
4631 draw_activity_graphs(a->g_nr, g_type,
4632 title, g_title, NULL, group,
4633 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4635 /* Free remaining structures */
4636 free_graphs(out, outsize, spmin, spmax);
4641 ***************************************************************************
4642 * Display filesystem statistics in SVG.
4645 * @a Activity structure with statistics.
4646 * @curr Index in array for current sample statistics.
4647 * @action Action expected from current function.
4648 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4649 * flag indicating that a restart record has been previously
4650 * found (.@restart) and time used for the X axis origin
4652 * @itv Interval of time in 1/100th of a second (unused here).
4653 * @record_hdr Pointer on record header of current stats sample.
4654 ***************************************************************************
4656 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4657 unsigned long long itv, struct record_header *record_hdr)
4659 struct stats_filesystem *sfc, *sfp;
4660 int group[] = {2, 2, 2, 1};
4661 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4662 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4663 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4664 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4665 char *g_title[] = {"~MBfsfree", "~MBfsused",
4666 "%ufsused", "%fsused",
4667 "Ifree/1000", "Iused/1000",
4669 static double *spmin, *spmax;
4671 static int *outsize;
4672 char *item_name = NULL;
4674 int i, k, pos, restart;
4676 if (action & F_BEGIN) {
4678 * Allocate arrays (#0..6) that will contain the graphs data
4679 * and the min/max values.
4680 * Also allocate two additional arrays (#7..8) for each filesystem:
4681 * out + 7 will contain the filesystem name,
4682 * out + 8 will contain the mount point.
4684 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
4687 if (action & F_MAIN) {
4688 /* For each filesystem structure */
4689 for (i = 0; i < a->nr[curr]; i++) {
4690 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4693 /* A list of devices has been entered on the command line */
4694 if (!search_sa_dlist(st_fs_list, dlst_fs_idx,
4695 DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name))
4696 /* Device not found */
4700 /* Look for corresponding graph */
4701 for (k = 0; k < svg_p->nr_max; k++) {
4702 item_name = *(out + k * 9 + 7);
4703 if (!strcmp(sfc->fs_name, item_name))
4708 if (k == svg_p->nr_max) {
4709 /* Graph not found: Look for first free entry */
4710 for (k = 0; k < svg_p->nr_max; k++) {
4711 item_name = *(out + k * 9 + 7);
4712 if (!strcmp(item_name, ""))
4715 if (k == svg_p->nr_max) {
4716 /* No free graph entry: Extend all buffers */
4717 reallocate_all_graph_lines(svg_p->nr_max,
4718 &out, &outsize, &spmin, &spmax);
4725 if (!item_name[0]) {
4726 /* Save filesystem name and mount point (if not already done) */
4727 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4728 item_name[CHUNKSIZE - 1] = '\0';
4729 item_name = *(out + pos + 8);
4730 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4731 item_name[CHUNKSIZE - 1] = '\0';
4735 for (k = 0; k < a->nr[!curr]; k++) {
4736 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4737 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4738 /* Filesystem found in previous sample */
4739 restart = svg_p->restart;
4743 /* Check for min/max values */
4745 /* Compute fsfree min/max values */
4746 tval = (double) sfc->f_bfree;
4747 if (tval > *(spmax + pos)) {
4748 *(spmax + pos) = tval;
4750 if (tval < *(spmin + pos)) {
4751 *(spmin + pos) = tval;
4753 /* Compute fsused min/max values */
4754 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4755 if (tval > *(spmax + pos + 1)) {
4756 *(spmax + pos + 1) = tval;
4758 if (tval < *(spmin + pos + 1)) {
4759 *(spmin + pos + 1) = tval;
4761 /* Compute %ufsused min/max values */
4762 tval = sfc->f_blocks ?
4763 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4764 if (tval > *(spmax + pos + 2)) {
4765 *(spmax + pos + 2) = tval;
4767 if (tval < *(spmin + pos + 2)) {
4768 *(spmin + pos + 2) = tval;
4770 /* Compute %fsused min/max values */
4771 tval = sfc->f_blocks ?
4772 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4773 if (tval > *(spmax + pos + 3)) {
4774 *(spmax + pos + 3) = tval;
4776 if (tval < *(spmin + pos + 3)) {
4777 *(spmin + pos + 3) = tval;
4779 /* Compute Ifree min/max values */
4780 tval = (double) sfc->f_ffree;
4781 if (tval > *(spmax + pos + 4)) {
4782 *(spmax + pos + 4) = tval;
4784 if (tval < *(spmin + pos + 4)) {
4785 *(spmin + pos + 4) = tval;
4787 /* Compute Iused min/max values */
4788 tval = (double) (sfc->f_files - sfc->f_ffree);
4789 if (tval > *(spmax + pos + 5)) {
4790 *(spmax + pos + 5) = tval;
4792 if (tval < *(spmin + pos + 5)) {
4793 *(spmin + pos + 5) = tval;
4795 /* Compute %Iused min/max values */
4796 tval = sfc->f_files ?
4797 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4798 if (tval > *(spmax + pos + 6)) {
4799 *(spmax + pos + 6) = tval;
4801 if (tval < *(spmin + pos + 6)) {
4802 *(spmin + pos + 6) = tval;
4806 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4807 (double) sfc->f_bfree / 1024 / 1024,
4808 out + pos, outsize + pos, restart);
4810 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4811 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4812 out + pos + 1, outsize + pos + 1, restart);
4814 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4817 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4818 out + pos + 2, outsize + pos + 2, svg_p->dt);
4820 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4823 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4824 out + pos + 3, outsize + pos + 3, svg_p->dt);
4826 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4827 ((double) sfc->f_ffree) / 1000,
4828 out + pos + 4, outsize + pos + 4, restart);
4830 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4831 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4832 out + pos + 5, outsize + pos + 5, restart);
4834 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4837 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4838 out + pos + 6, outsize + pos + 6, svg_p->dt);
4842 if (action & F_END) {
4845 for (i = 0; i < svg_p->nr_max; i++) {
4847 /* Check if there is something to display */
4852 /* Conversion B -> MB and inodes/1000 */
4853 for (k = 0; k < 2; k++) {
4854 *(spmin + pos + k) /= (1024 * 1024);
4855 *(spmax + pos + k) /= (1024 * 1024);
4856 *(spmin + pos + 4 + k) /= 1000;
4857 *(spmax + pos + 4 + k) /= 1000;
4860 if (DISPLAY_MOUNT(a->opt_flags)) {
4861 item_name = *(out + pos + 8);
4864 item_name = *(out + pos + 7);
4867 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4868 spmin + pos, spmax + pos, out + pos, outsize + pos,
4869 svg_p, record_hdr, FALSE, a->id, xid)) {
4874 /* Free remaining structures */
4875 free_graphs(out, outsize, spmin, spmax);
4880 ***************************************************************************
4881 * Display Fibre Channel HBA statistics in SVG.
4884 * @a Activity structure with statistics.
4885 * @curr Index in array for current sample statistics.
4886 * @action Action expected from current function.
4887 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4888 * flag indicating that a restart record has been previously
4889 * found (.@restart) and time used for the X axis origin
4891 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4892 * @record_hdr Pointer on record header of current stats sample.
4893 ***************************************************************************
4895 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4896 unsigned long long itv, struct record_header *record_hdr)
4898 struct stats_fchost *sfcc, *sfcp;
4899 int group[] = {2, 2};
4900 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4901 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4902 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4903 "fch_rxw/s", "fch_txw/s"};
4904 int g_fields[] = {0, 1, 2, 3};
4905 static double *spmin, *spmax;
4907 static int *outsize;
4909 int i, j, j0, k, found, pos, restart, *unregistered;
4911 if (action & F_BEGIN) {
4913 * Allocate arrays (#0..3) that will contain the graphs data
4914 * and the min/max values.
4915 * Also allocate one additional array (#4) that will contain
4916 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4917 * has either still not been registered, or has been unregistered
4920 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
4923 if (action & F_MAIN) {
4924 restart = svg_p->restart;
4926 * Mark previously registered interfaces as now
4927 * possibly unregistered for all graphs.
4929 for (k = 0; k < svg_p->nr_max; k++) {
4930 unregistered = outsize + k * 5 + 4;
4931 if (*unregistered == FALSE) {
4932 *unregistered = MAYBE;
4936 /* For each FC HBA */
4937 for (i = 0; i < a->nr[curr]; i++) {
4941 if (a->nr[!curr] > 0) {
4942 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4944 /* Look for corresponding graph */
4945 for (k = 0; k < svg_p->nr_max; k++) {
4946 item_name = *(out + k * 5 + 4);
4947 if (!strcmp(sfcc->fchost_name, item_name))
4951 if (k == svg_p->nr_max) {
4952 /* Graph not found: Look for first free entry */
4953 for (k = 0; k < svg_p->nr_max; k++) {
4954 item_name = *(out + k * 5 + 4);
4955 if (!strcmp(item_name, ""))
4958 if (k == svg_p->nr_max) {
4959 /* No free graph entry: Extend all buffers */
4960 reallocate_all_graph_lines(svg_p->nr_max,
4961 &out, &outsize, &spmin, &spmax);
4967 unregistered = outsize + pos + 4;
4969 /* Look for corresponding structure in previous iteration */
4972 if (j >= a->nr[!curr]) {
4973 j = a->nr[!curr] - 1;
4979 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4980 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4984 if (++j >= a->nr[!curr]) {
4995 * If current interface was marked as previously unregistered,
4996 * then set restart variable to TRUE so that the graph will be
4997 * discontinuous, and mark it as now registered.
4999 if (*unregistered == TRUE) {
5002 *unregistered = FALSE;
5004 item_name = *(out + pos + 4);
5005 if (!item_name[0]) {
5006 /* Save FC HBA name */
5007 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
5008 item_name[CHUNKSIZE - 1] = '\0';
5011 /* Look for min/max values */
5012 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
5013 itv, spmin + pos, spmax + pos, g_fields);
5016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5017 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5018 out + pos, outsize + pos, restart);
5020 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5021 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5022 out + pos + 1, outsize + pos + 1, restart);
5024 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5025 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5026 out + pos + 2, outsize + pos + 2, restart);
5028 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5029 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5030 out + pos + 3, outsize + pos + 3, restart);
5033 /* Mark interfaces not seen here as now unregistered */
5034 for (k = 0; k < svg_p->nr_max; k++) {
5035 unregistered = outsize + k * 5 + 4;
5036 if (*unregistered != FALSE) {
5037 *unregistered = TRUE;
5042 if (action & F_END) {
5043 for (i = 0; i < svg_p->nr_max; i++) {
5045 /* Check if there is something to display */
5050 item_name = *(out + pos + 4);
5051 draw_activity_graphs(a->g_nr, g_type,
5052 title, g_title, item_name, group,
5053 spmin + pos, spmax + pos, out + pos, outsize + pos,
5054 svg_p, record_hdr, FALSE, a->id, i);
5057 /* Free remaining structures */
5058 free_graphs(out, outsize, spmin, spmax);
5063 ***************************************************************************
5064 * Display softnet statistics in SVG.
5067 * @a Activity structure with statistics.
5068 * @curr Index in array for current sample statistics.
5069 * @action Action expected from current function.
5070 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5071 * flag indicating that a restart record has been previously
5072 * found (.@restart) and time used for the X axis origin
5074 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5075 * @record_hdr Pointer on record header of current stats sample.
5076 ***************************************************************************
5078 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5079 unsigned long long itv, struct record_header *record_hdr)
5081 struct stats_softnet *ssnc, *ssnp, ssnczero;
5082 int group[] = {2, 3};
5083 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5084 char *title[] = {"Software-based network processing statistics (1)",
5085 "Software-based network processing statistics (2)"};
5086 char *g_title[] = {"total/s", "dropd/s",
5087 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5088 int g_fields[] = {0, 1, 2, 3, 4};
5089 static double *spmin, *spmax;
5091 static int *outsize;
5093 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5094 int i, pos, restart;
5096 if (action & F_BEGIN) {
5098 * Allocate arrays that will contain the graphs data
5099 * and the min/max values.
5101 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
5104 if (action & F_MAIN) {
5105 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5107 /* @nr[curr] cannot normally be greater than @nr_ini */
5108 if (a->nr[curr] > a->nr_ini) {
5109 a->nr_ini = a->nr[curr];
5112 /* Compute statistics for CPU "all" */
5113 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5116 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5117 restart = svg_p->restart;
5119 /* Should current CPU (including CPU "all") be displayed? */
5120 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5124 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5125 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5127 /* Is current CPU marked offline? */
5128 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5130 * Yes and it doesn't follow a RESTART record.
5131 * To add a discontinuity in graph, we simulate
5135 if (svg_p->restart) {
5137 * CPU is offline and it follows a real
5138 * RESTART record. Ignore its current value
5139 * (no previous sample).
5146 /* Check for min/max values */
5147 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5148 itv, spmin + pos, spmax + pos, g_fields);
5151 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5152 S_VALUE(ssnp->processed, ssnc->processed, itv),
5153 out + pos, outsize + pos, restart);
5155 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5156 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5157 out + pos + 1, outsize + pos + 1, restart);
5159 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5160 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5161 out + pos + 2, outsize + pos + 2, restart);
5163 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5164 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5165 out + pos + 3, outsize + pos + 3, restart);
5167 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5168 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5169 out + pos + 4, outsize + pos + 4, restart);
5173 if (action & F_END) {
5174 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
5176 /* Should current CPU (including CPU "all") be displayed? */
5177 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5184 /* This is CPU "all" */
5185 strcpy(item_name, "all");
5188 sprintf(item_name, "%d", i - 1);
5191 draw_activity_graphs(a->g_nr, g_type,
5192 title, g_title, item_name, group,
5193 spmin + pos, spmax + pos, out + pos, outsize + pos,
5194 svg_p, record_hdr, FALSE, a->id, i);
5197 /* Free remaining structures */
5198 free_graphs(out, outsize, spmin, spmax);