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);
1064 /* For next row of views */
1065 (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;
1693 unsigned long long nousedmem;
1695 if (action & F_BEGIN) {
1697 * Allocate arrays that will contain the graphs data
1698 * and the min/max values.
1700 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1703 if (action & F_MAIN) {
1704 /* Check for min/max values */
1705 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1706 itv, spmin, spmax, g_fields);
1707 /* Compute %memused min/max values */
1708 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1709 if (nousedmem > smc->tlmkb) {
1710 nousedmem = smc->tlmkb;
1712 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1713 if (tval > *(spmax + 3)) {
1714 *(spmax + 3) = tval;
1716 if (tval < *(spmin + 3)) {
1717 *(spmin + 3) = tval;
1719 /* Compute %commit min/max values */
1720 tval = (smc->tlmkb + smc->tlskb) ?
1721 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1722 if (tval > *(spmax + 7)) {
1723 *(spmax + 7) = tval;
1725 if (tval < *(spmin + 7)) {
1726 *(spmin + 7) = tval;
1728 /* Compute %swpused min/max values */
1730 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1731 if (tval > *(spmax + 19)) {
1732 *(spmax + 19) = tval;
1734 if (tval < *(spmin + 19)) {
1735 *(spmin + 19) = tval;
1737 /* Compute %swpcad min/max values */
1738 tval = (smc->tlskb - smc->frskb) ?
1739 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1740 if (tval > *(spmax + 20)) {
1741 *(spmax + 20) = tval;
1743 if (tval < *(spmin + 20)) {
1744 *(spmin + 20) = tval;
1746 /* Compute memused min/max values in MB */
1747 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1748 if (tval > *(spmax + 2)) {
1749 *(spmax + 2) = tval;
1751 if (tval < *(spmin + 2)) {
1752 *(spmin + 2) = tval;
1754 /* Compute swpused min/max values in MB */
1755 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1756 if (tval > *(spmax + 17)) {
1757 *(spmax + 17) = tval;
1759 if (tval < *(spmin + 17)) {
1760 *(spmin + 17) = tval;
1764 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1765 ((double) smc->frmkb) / 1024,
1766 out, outsize, svg_p->restart);
1768 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1769 ((double) (smc->tlmkb - nousedmem)) / 1024,
1770 out + 2, outsize + 2, svg_p->restart);
1772 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1773 ((double) smc->availablekb) / 1024,
1774 out + 1, outsize + 1, svg_p->restart);
1776 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1777 ((double) smc->bufkb) / 1024,
1778 out + 4, outsize + 4, svg_p->restart);
1780 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1781 ((double) smc->camkb) / 1024,
1782 out + 5, outsize + 5, svg_p->restart);
1784 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1785 ((double) smc->frskb) / 1024,
1786 out + 16, outsize + 16, svg_p->restart);
1788 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1789 ((double) (smc->tlskb - smc->frskb)) / 1024,
1790 out + 17, outsize + 17, svg_p->restart);
1792 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1793 ((double) smc->caskb) / 1024,
1794 out + 18, outsize + 18, svg_p->restart);
1796 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1797 ((double) smc->comkb) / 1024,
1798 out + 6, outsize + 6, svg_p->restart);
1800 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1801 ((double) smc->activekb) / 1024,
1802 out + 8, outsize + 8, svg_p->restart);
1804 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1805 ((double) smc->inactkb) / 1024,
1806 out + 9, outsize + 9, svg_p->restart);
1808 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1809 ((double) smc->dirtykb) / 1024,
1810 out + 10, outsize + 10, svg_p->restart);
1812 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1813 ((double) smc->anonpgkb) / 1024,
1814 out + 11, outsize + 11, svg_p->restart);
1816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1817 ((double) smc->slabkb) / 1024,
1818 out + 12, outsize + 12, svg_p->restart);
1820 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1821 ((double) smc->kstackkb) / 1024,
1822 out + 13, outsize + 13, svg_p->restart);
1824 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1825 ((double) smc->pgtblkb) / 1024,
1826 out + 14, outsize + 14, svg_p->restart);
1828 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1829 ((double) smc->vmusedkb) / 1024,
1830 out + 15, outsize + 15, svg_p->restart);
1832 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1835 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1836 out + 3, outsize + 3, svg_p->dt);
1838 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1840 (smc->tlmkb + smc->tlskb) ?
1841 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1842 out + 7, outsize + 7, svg_p->dt);
1844 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1847 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1848 out + 19, outsize + 19, svg_p->dt);
1850 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1852 (smc->tlskb - smc->frskb) ?
1853 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1854 out + 20, outsize + 20, svg_p->dt);
1857 if (action & F_END) {
1859 /* Conversion kB -> MB */
1860 for (i = 0; i < 17; i++) {
1861 *(spmin + g_fields[i]) /= 1024;
1862 *(spmax + g_fields[i]) /= 1024;
1865 if (DISPLAY_MEMORY(a->opt_flags)) {
1866 if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1867 g_type1, title1, g_title1, NULL, group1,
1868 spmin, spmax, out, outsize, svg_p, record_hdr,
1869 FALSE, a->id, xid)) {
1874 if (DISPLAY_SWAP(a->opt_flags)) {
1875 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1876 spmin + 16, spmax + 16, out + 16, outsize + 16,
1877 svg_p, record_hdr, FALSE, a->id, xid);
1880 /* Free remaining structures */
1881 free_graphs(out, outsize, spmin, spmax);
1886 ***************************************************************************
1887 * Display kernel tables statistics in SVG.
1890 * @a Activity structure with statistics.
1891 * @curr Index in array for current sample statistics.
1892 * @action Action expected from current function.
1893 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1894 * flag indicating that a restart record has been previously
1895 * found (.@restart) and time used for the X axis origin
1897 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1898 * @record_hdr Pointer on record header of current stats sample.
1899 ***************************************************************************
1901 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1902 unsigned long long itv, struct record_header *record_hdr)
1904 struct stats_ktables
1905 *skc = (struct stats_ktables *) a->buf[curr];
1906 int group[] = {3, 1};
1907 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1908 char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
1909 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1911 int g_fields[] = {1, 2, 0, 3};
1912 static double *spmin, *spmax;
1914 static int *outsize;
1916 if (action & F_BEGIN) {
1918 * Allocate arrays that will contain the graphs data
1919 * and the min/max values.
1921 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1924 if (action & F_MAIN) {
1925 /* Check for min/max values */
1926 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1927 itv, spmin, spmax, g_fields);
1929 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1930 (unsigned long long) skc->dentry_stat,
1931 out, outsize, svg_p->restart);
1933 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1934 (unsigned long long) skc->file_used,
1935 out + 1, outsize + 1, svg_p->restart);
1937 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1938 (unsigned long long) skc->inode_used,
1939 out + 2, outsize + 2, svg_p->restart);
1941 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1942 (unsigned long long) skc->pty_nr,
1943 out + 3, outsize + 3, svg_p->restart);
1946 if (action & F_END) {
1947 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1948 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
1950 /* Free remaining structures */
1951 free_graphs(out, outsize, spmin, spmax);
1956 ***************************************************************************
1957 * Display queue and load statistics in SVG.
1960 * @a Activity structure with statistics.
1961 * @curr Index in array for current sample statistics.
1962 * @action Action expected from current function.
1963 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1964 * flag indicating that a restart record has been previously
1965 * found (.@restart) and time used for the X axis origin
1967 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1968 * @record_hdr Pointer on record header of current stats sample.
1969 ***************************************************************************
1971 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1972 unsigned long long itv, struct record_header *record_hdr)
1975 *sqc = (struct stats_queue *) a->buf[curr];
1976 int group[] = {2, 1, 3};
1977 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1978 char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
1979 char *g_title[] = {"~runq-sz", "~blocked",
1981 "ldavg-1", "ldavg-5", "ldavg-15"};
1982 int g_fields[] = {0, 1, 2, 3, 4, 5};
1983 static double *spmin, *spmax;
1985 static int *outsize;
1987 if (action & F_BEGIN) {
1989 * Allocate arrays that will contain the graphs data
1990 * and the min/max values.
1992 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1995 if (action & F_MAIN) {
1996 /* Check for min/max values */
1997 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1998 itv, spmin, spmax, g_fields);
2000 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2001 (unsigned long long) sqc->nr_running,
2002 out, outsize, svg_p->restart);
2004 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2005 (unsigned long long) sqc->procs_blocked,
2006 out + 1, outsize + 1, svg_p->restart);
2008 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2009 (unsigned long long) sqc->nr_threads,
2010 out + 2, outsize + 2, svg_p->restart);
2012 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2013 (double) sqc->load_avg_1 / 100,
2014 out + 3, outsize + 3, svg_p->restart);
2016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2017 (double) sqc->load_avg_5 / 100,
2018 out + 4, outsize + 4, svg_p->restart);
2020 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2021 (double) sqc->load_avg_15 / 100,
2022 out + 5, outsize + 5, svg_p->restart);
2025 if (action & F_END) {
2026 /* Fix min/max values for load average */
2027 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
2028 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2029 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2031 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2032 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2034 /* Free remaining structures */
2035 free_graphs(out, outsize, spmin, spmax);
2040 ***************************************************************************
2041 * Display disk statistics in SVG.
2044 * @a Activity structure with statistics.
2045 * @curr Index in array for current sample statistics.
2046 * @action Action expected from current function.
2047 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2048 * flag indicating that a restart record has been previously
2049 * found (.@restart) and time used for the X axis origin
2051 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2052 * @record_hdr Pointer on record header of current stats sample.
2053 ***************************************************************************
2055 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2056 unsigned long long itv, struct record_header *record_hdr)
2058 struct stats_disk *sdc, *sdp, sdpzero;
2059 struct ext_disk_stats xds;
2060 int group[] = {1, 2, 2, 2, 1};
2061 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2062 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2063 char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
2064 "Block devices statistics (3)", "Block devices statistics (4)",
2065 "Block devices statistics (5)"};
2066 char *g_title[] = {"tps",
2068 "areq-sz", "aqu-sz",
2071 int g_fields[] = {0, 1, 2};
2072 unsigned int local_types_nr[] = {1, 0, 0};
2073 static double *spmin, *spmax;
2075 static int *outsize;
2077 double rkB, wkB, aqusz;
2078 int i, j, k, pos, restart, *unregistered;
2080 if (action & F_BEGIN) {
2082 * Allocate arrays (#0..7) that will contain the graphs data
2083 * and the min/max values.
2084 * Also allocate one additional array (#8) for each disk device:
2085 * spmax + 8 will contain the device major number,
2086 * spmin + 8 will contain the device minor number,
2087 * outsize + 8 will contain a positive value (TRUE) if the device
2088 * has either still not been registered, or has been unregistered.
2090 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2093 if (action & F_MAIN) {
2094 memset(&sdpzero, 0, STATS_DISK_SIZE);
2095 restart = svg_p->restart;
2097 * Mark previously registered devices as now
2098 * possibly unregistered for all graphs.
2100 for (k = 0; k < svg_p->nr_max; k++) {
2101 unregistered = outsize + k * 9 + 8;
2102 if (*unregistered == FALSE) {
2103 *unregistered = MAYBE;
2107 /* For each device structure */
2108 for (i = 0; i < a->nr[curr]; i++) {
2109 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2111 /* Get device name */
2112 item_name = get_sa_devname(sdc->major, sdc->minor, flags);
2115 /* A list of devices has been entered on the command line */
2116 if (!search_sa_dlist(st_dev_list, dlst_dev_idx, item_name))
2117 /* Device not found */
2121 /* Look for corresponding graph */
2122 for (k = 0; k < svg_p->nr_max; k++) {
2123 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2124 (sdc->minor == *(spmin + k * 9 + 8)))
2128 if (k == svg_p->nr_max) {
2129 /* Graph not found: Look for first free entry */
2130 for (k = 0; k < svg_p->nr_max; k++) {
2131 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2134 if (k == svg_p->nr_max) {
2135 /* No free graph entry: Extend all buffers */
2136 reallocate_all_graph_lines(9 * svg_p->nr_max,
2137 &out, &outsize, &spmin, &spmax);
2142 unregistered = outsize + pos + 8;
2145 * If current device was marked as previously unregistered,
2146 * then set restart variable to TRUE so that the graph will be
2147 * discontinuous, and mark it as now registered.
2149 if (*unregistered == TRUE) {
2152 *unregistered = FALSE;
2154 if (*(spmax + pos + 8) == -DBL_MAX) {
2155 /* Save device major and minor numbers (if not already done) */
2156 *(spmax + pos + 8) = sdc->major;
2157 *(spmin + pos + 8) = sdc->minor;
2160 j = check_disk_reg(a, curr, !curr, i);
2162 /* This is a newly registered interface. Previous stats are zero */
2166 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2169 /* Check for min/max values */
2170 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2171 itv, spmin + pos, spmax + pos, g_fields);
2173 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2174 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2175 if (rkB < *(spmin + pos + 1)) {
2176 *(spmin + pos + 1) = rkB;
2178 if (rkB > *(spmax + pos + 1)) {
2179 *(spmax + pos + 1) = rkB;
2181 if (wkB < *(spmin + pos + 2)) {
2182 *(spmin + pos + 2) = wkB;
2184 if (wkB > *(spmax + pos + 2)) {
2185 *(spmax + pos + 2) = wkB;
2188 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2189 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2190 *(spmin + pos + 3) = xds.arqsz / 2;
2192 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2193 *(spmax + pos + 3) = xds.arqsz / 2;
2195 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2196 if (aqusz < *(spmin + pos + 4)) {
2197 *(spmin + pos + 4) = aqusz;
2199 if (aqusz > *(spmax + pos + 4)) {
2200 *(spmax + pos + 4) = aqusz;
2202 if (xds.await < *(spmin + pos + 5)) {
2203 *(spmin + pos + 5) = xds.await;
2205 if (xds.await > *(spmax + pos + 5)) {
2206 *(spmax + pos + 5) = xds.await;
2208 if (xds.svctm < *(spmin + pos + 6)) {
2209 *(spmin + pos + 6) = xds.svctm;
2211 if (xds.svctm > *(spmax + pos + 6)) {
2212 *(spmax + pos + 6) = xds.svctm;
2214 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2215 *(spmin + pos + 7) = xds.util / 10.0;
2217 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2218 *(spmax + pos + 7) = xds.util / 10.0;
2222 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2223 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2224 out + pos, outsize + pos, restart);
2226 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2227 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2228 out + pos + 1, outsize + pos + 1, restart);
2230 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2231 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2232 out + pos + 2, outsize + pos + 2, restart);
2234 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2236 out + pos + 3, outsize + pos + 3, restart);
2238 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2240 out + pos + 4, outsize + pos + 4, restart);
2242 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2244 out + pos + 5, outsize + pos + 5, restart);
2246 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2248 out + pos + 6, outsize + pos + 6, restart);
2250 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2251 0.0, xds.util / 10.0,
2252 out + pos + 7, outsize + pos + 7, svg_p->dt);
2255 /* Mark devices not seen here as now unregistered */
2256 for (k = 0; k < svg_p->nr_max; k++) {
2257 unregistered = outsize + k * 9 + 8;
2258 if (*unregistered != FALSE) {
2259 *unregistered = TRUE;
2264 if (action & F_END) {
2267 for (i = 0; i < svg_p->nr_max; i++) {
2268 /* Check if there is something to display */
2273 /* Get device name */
2274 item_name = get_sa_devname(*(spmax + pos + 8), *(spmin + pos + 8), flags);
2276 if (draw_activity_graphs(a->g_nr, g_type,
2277 title, g_title, item_name, group,
2278 spmin + pos, spmax + pos, out + pos, outsize + pos,
2279 svg_p, record_hdr, FALSE, a->id, xid)) {
2284 /* Free remaining structures */
2285 free_graphs(out, outsize, spmin, spmax);
2290 ***************************************************************************
2291 * Display network interfaces statistics in SVG.
2294 * @a Activity structure with statistics.
2295 * @curr Index in array for current sample statistics.
2296 * @action Action expected from current function.
2297 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2298 * flag indicating that a restart record has been previously
2299 * found (.@restart) and time used for the X axis origin
2301 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2302 * @record_hdr Pointer on record header of current stats sample.
2303 ***************************************************************************
2305 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2306 unsigned long long itv, struct record_header *record_hdr)
2308 struct stats_net_dev *sndc, *sndp, sndzero;
2309 int group[] = {2, 2, 3, 1};
2310 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2312 char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
2313 "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
2314 char *g_title[] = {"rxpck/s", "txpck/s",
2316 "rxcmp/s", "txcmp/s", "rxmcst/s",
2318 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2319 unsigned int local_types_nr[] = {7, 0, 0};
2320 static double *spmin, *spmax;
2322 static int *outsize;
2324 double rxkb, txkb, ifutil;
2325 int i, j, k, pos, restart, *unregistered;
2327 if (action & F_BEGIN) {
2329 * Allocate arrays (#0..7) that will contain the graphs data
2330 * and the min/max values.
2331 * Also allocate one additional array (#8) for each interface:
2332 * out + 8 will contain the interface name,
2333 * outsize + 8 will contain a positive value (TRUE) if the interface
2334 * has either still not been registered, or has been unregistered.
2336 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2339 if (action & F_MAIN) {
2340 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2341 restart = svg_p->restart;
2343 * Mark previously registered interfaces as now
2344 * possibly unregistered for all graphs.
2346 for (k = 0; k < svg_p->nr_max; k++) {
2347 unregistered = outsize + k * 9 + 8;
2348 if (*unregistered == FALSE) {
2349 *unregistered = MAYBE;
2353 /* For each network interfaces structure */
2354 for (i = 0; i < a->nr[curr]; i++) {
2355 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2357 if (dlst_iface_idx) {
2358 /* A list of devices has been entered on the command line */
2359 if (!search_sa_dlist(st_iface_list, dlst_iface_idx, sndc->interface))
2360 /* Device not found */
2364 /* Look for corresponding graph */
2365 for (k = 0; k < svg_p->nr_max; k++) {
2366 item_name = *(out + k * 9 + 8);
2367 if (!strcmp(sndc->interface, item_name))
2371 if (k == svg_p->nr_max) {
2372 /* Graph not found: Look for first free entry */
2373 for (k = 0; k < svg_p->nr_max; k++) {
2374 item_name = *(out + k * 9 + 8);
2375 if (!strcmp(item_name, ""))
2378 if (k == svg_p->nr_max) {
2379 /* No free graph entry: Extend all buffers */
2380 reallocate_all_graph_lines(9 * svg_p->nr_max,
2381 &out, &outsize, &spmin, &spmax);
2386 unregistered = outsize + pos + 8;
2388 j = check_net_dev_reg(a, curr, !curr, i);
2390 /* This is a newly registered interface. Previous stats are zero */
2394 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2398 * If current interface was marked as previously unregistered,
2399 * then set restart variable to TRUE so that the graph will be
2400 * discontinuous, and mark it as now registered.
2402 if (*unregistered == TRUE) {
2405 *unregistered = FALSE;
2407 item_name = *(out + pos + 8);
2408 if (!item_name[0]) {
2409 /* Save network interface name (if not already done) */
2410 strncpy(item_name, sndc->interface, CHUNKSIZE);
2411 item_name[CHUNKSIZE - 1] = '\0';
2414 /* Check for min/max values */
2415 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2416 itv, spmin + pos, spmax + pos, g_fields);
2418 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2419 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2420 ifutil = compute_ifutil(sndc, rxkb, txkb);
2421 if (ifutil < *(spmin + pos + 7)) {
2422 *(spmin + pos + 7) = ifutil;
2424 if (ifutil > *(spmax + pos + 7)) {
2425 *(spmax + pos + 7) = ifutil;
2429 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2430 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2431 out + pos, outsize + pos, restart);
2433 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2434 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2435 out + pos + 1, outsize + pos + 1, restart);
2437 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2439 out + pos + 2, outsize + pos + 2, restart);
2441 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2443 out + pos + 3, outsize + pos + 3, restart);
2445 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2446 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2447 out + pos + 4, outsize + pos + 4, restart);
2449 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2450 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2451 out + pos + 5, outsize + pos + 5, restart);
2453 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2454 S_VALUE(sndp->multicast, sndc->multicast, itv),
2455 out + pos + 6, outsize + pos + 6, restart);
2457 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2459 out + pos + 7, outsize + pos + 7, svg_p->dt);
2462 /* Mark interfaces not seen here as now unregistered */
2463 for (k = 0; k < svg_p->nr_max; k++) {
2464 unregistered = outsize + k * 9 + 8;
2465 if (*unregistered != FALSE) {
2466 *unregistered = TRUE;
2471 if (action & F_END) {
2474 for (i = 0; i < svg_p->nr_max; i++) {
2476 * Check if there is something to display.
2477 * Don't test sndc->interface because maybe the network
2478 * interface has been registered later.
2484 /* Recalculate min and max values in kB, not in B */
2485 *(spmin + pos + 2) /= 1024;
2486 *(spmax + pos + 2) /= 1024;
2487 *(spmin + pos + 3) /= 1024;
2488 *(spmax + pos + 3) /= 1024;
2490 item_name = *(out + pos + 8);
2491 if (draw_activity_graphs(a->g_nr, g_type,
2492 title, g_title, item_name, group,
2493 spmin + pos, spmax + pos, out + pos, outsize + pos,
2494 svg_p, record_hdr, FALSE, a->id, xid)) {
2499 /* Free remaining structures */
2500 free_graphs(out, outsize, spmin, spmax);
2505 ***************************************************************************
2506 * Display network interfaces errors statistics in SVG.
2509 * @a Activity structure with statistics.
2510 * @curr Index in array for current sample statistics.
2511 * @action Action expected from current function.
2512 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2513 * flag indicating that a restart record has been previously
2514 * found (.@restart) and time used for the X axis origin
2516 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2517 * @record_hdr Pointer on record header of current stats sample.
2518 ***************************************************************************
2520 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2521 unsigned long long itv, struct record_header *record_hdr)
2523 struct stats_net_edev *snedc, *snedp, snedzero;
2524 int group[] = {2, 2, 2, 3};
2525 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2527 char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
2528 "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
2529 char *g_title[] = {"rxerr/s", "txerr/s",
2530 "rxdrop/s", "txdrop/s",
2531 "rxfifo/s", "txfifo/s",
2532 "coll/s", "txcarr/s", "rxfram/s"};
2533 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2534 static double *spmin, *spmax;
2536 static int *outsize;
2538 int i, j, k, pos, restart, *unregistered;
2540 if (action & F_BEGIN) {
2542 * Allocate arrays (#0..8) that will contain the graphs data
2543 * and the min/max values.
2544 * Also allocate one additional array (#9) for each interface:
2545 * out + 9 will contain the interface name,
2546 * outsize + 9 will contain a positive value (TRUE) if the interface
2547 * has either still not been registered, or has been unregistered.
2549 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
2552 if (action & F_MAIN) {
2553 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2554 restart = svg_p->restart;
2556 * Mark previously registered interfaces as now
2557 * possibly unregistered for all graphs.
2559 for (k = 0; k < svg_p->nr_max; k++) {
2560 unregistered = outsize + k * 10 + 9;
2561 if (*unregistered == FALSE) {
2562 *unregistered = MAYBE;
2566 /* For each network interfaces structure */
2567 for (i = 0; i < a->nr[curr]; i++) {
2568 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2569 if (!strcmp(snedc->interface, ""))
2570 /* Empty structure: This is the end of the list */
2573 if (dlst_iface_idx) {
2574 /* A list of devices has been entered on the command line */
2575 if (!search_sa_dlist(st_iface_list, dlst_iface_idx, snedc->interface))
2576 /* Device not found */
2580 /* Look for corresponding graph */
2581 for (k = 0; k < svg_p->nr_max; k++) {
2582 item_name = *(out + k * 10 + 9);
2583 if (!strcmp(snedc->interface, item_name))
2587 if (k == svg_p->nr_max) {
2588 /* Graph not found: Look for first free entry */
2589 for (k = 0; k < svg_p->nr_max; k++) {
2590 item_name = *(out + k * 10 + 9);
2591 if (!strcmp(item_name, ""))
2594 if (k == svg_p->nr_max) {
2595 /* No free graph entry: Extend all buffers */
2596 reallocate_all_graph_lines(10 * svg_p->nr_max,
2597 &out, &outsize, &spmin, &spmax);
2603 unregistered = outsize + pos + 9;
2605 j = check_net_edev_reg(a, curr, !curr, i);
2607 /* This is a newly registered interface. Previous stats are zero */
2611 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2615 * If current interface was marked as previously unregistered,
2616 * then set restart variable to TRUE so that the graph will be
2617 * discontinuous, and mark it as now registered.
2619 if (*unregistered == TRUE) {
2622 *unregistered = FALSE;
2624 item_name = *(out + pos + 9);
2625 if (!item_name[0]) {
2626 /* Save network interface name (if not already done) */
2627 strncpy(item_name, snedc->interface, CHUNKSIZE);
2628 item_name[CHUNKSIZE - 1] = '\0';
2631 /* Check for min/max values */
2632 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2633 itv, spmin + pos, spmax + pos, g_fields);
2636 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2637 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2638 out + pos, outsize + pos, restart);
2640 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2641 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2642 out + pos + 1, outsize + pos + 1, restart);
2644 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2645 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2646 out + pos + 2, outsize + pos + 2, restart);
2648 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2649 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2650 out + pos + 3, outsize + pos + 3, restart);
2652 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2653 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2654 out + pos + 4, outsize + pos + 4, restart);
2656 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2657 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2658 out + pos + 5, outsize + pos + 5, restart);
2660 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2661 S_VALUE(snedp->collisions, snedc->collisions, itv),
2662 out + pos + 6, outsize + pos + 6, restart);
2664 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2665 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2666 out + pos + 7, outsize + pos + 7, restart);
2668 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2669 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2670 out + pos + 8, outsize + pos + 8, restart);
2673 /* Mark interfaces not seen here as now unregistered */
2674 for (k = 0; k < svg_p->nr_max; k++) {
2675 unregistered = outsize + k * 10 + 9;
2676 if (*unregistered != FALSE) {
2677 *unregistered = TRUE;
2682 if (action & F_END) {
2685 for (i = 0; i < svg_p->nr_max; i++) {
2687 * Check if there is something to display.
2688 * Don't test snedc->interface because maybe the network
2689 * interface has been registered later.
2695 item_name = *(out + pos + 9);
2696 if (draw_activity_graphs(a->g_nr, g_type,
2697 title, g_title, item_name, group,
2698 spmin + pos, spmax + pos, out + pos, outsize + pos,
2699 svg_p, record_hdr, FALSE, a->id, xid)) {
2704 /* Free remaining structures */
2705 free_graphs(out, outsize, spmin, spmax);
2710 ***************************************************************************
2711 * Display NFS client statistics in SVG.
2714 * @a Activity structure with statistics.
2715 * @curr Index in array for current sample statistics.
2716 * @action Action expected from current function.
2717 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2718 * flag indicating that a restart record has been previously
2719 * found (.@restart) and time used for the X axis origin
2721 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2722 * @record_hdr Pointer on record header of current stats sample.
2723 ***************************************************************************
2725 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2726 unsigned long long itv, struct record_header *record_hdr)
2728 struct stats_net_nfs
2729 *snnc = (struct stats_net_nfs *) a->buf[curr],
2730 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2731 int group[] = {2, 2, 2};
2732 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2733 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2734 "NFS client statistics (3)"};
2735 char *g_title[] = {"call/s", "retrans/s",
2736 "read/s", "write/s",
2737 "access/s", "getatt/s"};
2738 int g_fields[] = {0, 1, 2, 3, 4, 5};
2739 static double *spmin, *spmax;
2741 static int *outsize;
2743 if (action & F_BEGIN) {
2745 * Allocate arrays that will contain the graphs data
2746 * and the min/max values.
2748 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2751 if (action & F_MAIN) {
2752 /* Check for min/max values */
2753 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2754 itv, spmin, spmax, g_fields);
2757 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2758 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2759 out, outsize, svg_p->restart);
2761 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2762 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2763 out + 1, outsize + 1, svg_p->restart);
2765 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2766 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2767 out + 2, outsize + 2, svg_p->restart);
2769 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2770 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2771 out + 3, outsize + 3, svg_p->restart);
2773 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2774 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2775 out + 4, outsize + 4, svg_p->restart);
2777 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2778 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2779 out + 5, outsize + 5, svg_p->restart);
2782 if (action & F_END) {
2783 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2784 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2786 /* Free remaining structures */
2787 free_graphs(out, outsize, spmin, spmax);
2792 ***************************************************************************
2793 * Display NFS server statistics in SVG.
2796 * @a Activity structure with statistics.
2797 * @curr Index in array for current sample statistics.
2798 * @action Action expected from current function.
2799 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2800 * flag indicating that a restart record has been previously
2801 * found (.@restart) and time used for the X axis origin
2803 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2804 * @record_hdr Pointer on record header of current stats sample.
2805 ***************************************************************************
2807 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2808 unsigned long long itv, struct record_header *record_hdr)
2810 struct stats_net_nfsd
2811 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2812 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2813 int group[] = {2, 3, 2, 2, 2};
2814 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2815 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2816 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2817 "NFS server statistics (3)", "NFS server statistics (4)",
2818 "NFS server statistics (5)"};
2819 char *g_title[] = {"scall/s", "badcall/s",
2820 "packet/s", "udp/s", "tcp/s",
2822 "sread/s", "swrite/s",
2823 "saccess/s", "sgetatt/s"};
2824 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2825 static double *spmin, *spmax;
2827 static int *outsize;
2829 if (action & F_BEGIN) {
2831 * Allocate arrays that will contain the graphs data
2832 * and the min/max values.
2834 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2837 if (action & F_MAIN) {
2838 /* Check for min/max values */
2839 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2840 itv, spmin, spmax, g_fields);
2843 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2844 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2845 out, outsize, svg_p->restart);
2847 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2848 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2849 out + 1, outsize + 1, svg_p->restart);
2851 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2852 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2853 out + 2, outsize + 2, svg_p->restart);
2855 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2856 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2857 out + 3, outsize + 3, svg_p->restart);
2859 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2860 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2861 out + 4, outsize + 4, svg_p->restart);
2863 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2864 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2865 out + 5, outsize + 5, svg_p->restart);
2867 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2868 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2869 out + 6, outsize + 6, svg_p->restart);
2871 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2872 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2873 out + 7, outsize + 7, svg_p->restart);
2875 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2876 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2877 out + 8, outsize + 8, svg_p->restart);
2879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2880 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2881 out + 9, outsize + 9, svg_p->restart);
2883 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2884 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2885 out + 10, outsize + 10, svg_p->restart);
2888 if (action & F_END) {
2889 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2890 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2892 /* Free remaining structures */
2893 free_graphs(out, outsize, spmin, spmax);
2898 ***************************************************************************
2899 * Display socket statistics in SVG.
2902 * @a Activity structure with statistics.
2903 * @curr Index in array for current sample statistics.
2904 * @action Action expected from current function.
2905 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2906 * flag indicating that a restart record has been previously
2907 * found (.@restart) and time used for the X axis origin
2909 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2910 * @record_hdr Pointer on record header of current stats sample.
2911 ***************************************************************************
2913 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2914 unsigned long long itv, struct record_header *record_hdr)
2916 struct stats_net_sock
2917 *snsc = (struct stats_net_sock *) a->buf[curr];
2918 int group[] = {1, 5};
2919 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2920 char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
2921 char *g_title[] = {"~totsck",
2922 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2923 int g_fields[] = {0, 1, 5, 2, 3, 4};
2924 static double *spmin, *spmax;
2926 static int *outsize;
2928 if (action & F_BEGIN) {
2930 * Allocate arrays that will contain the graphs data
2931 * and the min/max values.
2933 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2936 if (action & F_MAIN) {
2937 /* Check for min/max values */
2938 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2939 itv, spmin, spmax, g_fields);
2941 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2942 (unsigned long long) snsc->sock_inuse,
2943 out, outsize, svg_p->restart);
2945 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2946 (unsigned long long) snsc->tcp_inuse,
2947 out + 1, outsize + 1, svg_p->restart);
2949 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2950 (unsigned long long) snsc->udp_inuse,
2951 out + 2, outsize + 2, svg_p->restart);
2953 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2954 (unsigned long long) snsc->raw_inuse,
2955 out + 3, outsize + 3, svg_p->restart);
2957 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2958 (unsigned long long) snsc->frag_inuse,
2959 out + 4, outsize + 4, svg_p->restart);
2961 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2962 (unsigned long long) snsc->tcp_tw,
2963 out + 5, outsize + 5, svg_p->restart);
2966 if (action & F_END) {
2967 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2968 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
2970 /* Free remaining structures */
2971 free_graphs(out, outsize, spmin, spmax);
2976 ***************************************************************************
2977 * Display IPv4 traffic statistics in SVG.
2980 * @a Activity structure with statistics.
2981 * @curr Index in array for current sample statistics.
2982 * @action Action expected from current function.
2983 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2984 * flag indicating that a restart record has been previously
2985 * found (.@restart) and time used for the X axis origin
2987 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2988 * @record_hdr Pointer on record header of current stats sample.
2989 ***************************************************************************
2991 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2992 unsigned long long itv, struct record_header *record_hdr)
2995 *snic = (struct stats_net_ip *) a->buf[curr],
2996 *snip = (struct stats_net_ip *) a->buf[!curr];
2997 int group[] = {4, 2, 2};
2998 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2999 char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
3000 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
3001 "asmrq/s", "asmok/s",
3002 "fragok/s", "fragcrt/s"};
3003 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3004 static double *spmin, *spmax;
3006 static int *outsize;
3008 if (action & F_BEGIN) {
3010 * Allocate arrays that will contain the graphs data
3011 * and the min/max values.
3013 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3016 if (action & F_MAIN) {
3017 /* Check for min/max values */
3018 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3019 itv, spmin, spmax, g_fields);
3022 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3023 S_VALUE(snip->InReceives, snic->InReceives, itv),
3024 out, outsize, svg_p->restart);
3026 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3027 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
3028 out + 1, outsize + 1, svg_p->restart);
3030 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3031 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
3032 out + 2, outsize + 2, svg_p->restart);
3034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3035 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
3036 out + 3, outsize + 3, svg_p->restart);
3038 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3039 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
3040 out + 4, outsize + 4, svg_p->restart);
3042 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3043 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
3044 out + 5, outsize + 5, svg_p->restart);
3046 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3047 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3048 out + 6, outsize + 6, svg_p->restart);
3050 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3051 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3052 out + 7, outsize + 7, svg_p->restart);
3055 if (action & F_END) {
3056 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3057 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3059 /* Free remaining structures */
3060 free_graphs(out, outsize, spmin, spmax);
3065 ***************************************************************************
3066 * Display IPv4 traffic errors statistics in SVG.
3069 * @a Activity structure with statistics.
3070 * @curr Index in array for current sample statistics.
3071 * @action Action expected from current function.
3072 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3073 * flag indicating that a restart record has been previously
3074 * found (.@restart) and time used for the X axis origin
3076 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3077 * @record_hdr Pointer on record header of current stats sample.
3078 ***************************************************************************
3080 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3081 unsigned long long itv, struct record_header *record_hdr)
3083 struct stats_net_eip
3084 *sneic = (struct stats_net_eip *) a->buf[curr],
3085 *sneip = (struct stats_net_eip *) a->buf[!curr];
3086 int group[] = {3, 2, 3};
3087 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3088 char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
3089 "IPv4 traffic errors statistics (3)"};
3090 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3091 "idisc/s", "odisc/s",
3092 "onort/s", "asmf/s", "fragf/s"};
3093 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3094 static double *spmin, *spmax;
3096 static int *outsize;
3098 if (action & F_BEGIN) {
3100 * Allocate arrays that will contain the graphs data
3101 * and the min/max values.
3103 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3106 if (action & F_MAIN) {
3107 /* Check for min/max values */
3108 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3109 itv, spmin, spmax, g_fields);
3112 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3113 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3114 out, outsize, svg_p->restart);
3116 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3117 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3118 out + 1, outsize + 1, svg_p->restart);
3120 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3121 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3122 out + 2, outsize + 2, svg_p->restart);
3124 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3125 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3126 out + 3, outsize + 3, svg_p->restart);
3128 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3129 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3130 out + 4, outsize + 4, svg_p->restart);
3132 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3133 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3134 out + 5, outsize + 5, svg_p->restart);
3136 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3137 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3138 out + 6, outsize + 6, svg_p->restart);
3140 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3141 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3142 out + 7, outsize + 7, svg_p->restart);
3145 if (action & F_END) {
3146 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3147 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3149 /* Free remaining structures */
3150 free_graphs(out, outsize, spmin, spmax);
3155 ***************************************************************************
3156 * Display ICMPv4 traffic statistics in SVG.
3159 * @a Activity structure with statistics.
3160 * @curr Index in array for current sample statistics.
3161 * @action Action expected from current function.
3162 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3163 * flag indicating that a restart record has been previously
3164 * found (.@restart) and time used for the X axis origin
3166 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3167 * @record_hdr Pointer on record header of current stats sample.
3168 ***************************************************************************
3170 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3171 unsigned long long itv, struct record_header *record_hdr)
3173 struct stats_net_icmp
3174 *snic = (struct stats_net_icmp *) a->buf[curr],
3175 *snip = (struct stats_net_icmp *) a->buf[!curr];
3176 int group[] = {2, 4, 4, 4};
3177 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3179 char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
3180 "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
3181 char *g_title[] = {"imsg/s", "omsg/s",
3182 "iech/s", "iechr/s", "oech/s", "oechr/s",
3183 "itm/s", "itmr/s", "otm/s", "otmr/s",
3184 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3185 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3186 static double *spmin, *spmax;
3188 static int *outsize;
3190 if (action & F_BEGIN) {
3192 * Allocate arrays that will contain the graphs data
3193 * and the min/max values.
3195 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3198 if (action & F_MAIN) {
3199 /* Check for min/max values */
3200 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3201 itv, spmin, spmax, g_fields);
3204 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3205 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3206 out, outsize, svg_p->restart);
3208 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3209 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3210 out + 1, outsize + 1, svg_p->restart);
3212 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3213 S_VALUE(snip->InEchos, snic->InEchos, itv),
3214 out + 2, outsize + 2, svg_p->restart);
3216 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3217 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3218 out + 3, outsize + 3, svg_p->restart);
3220 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3221 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3222 out + 4, outsize + 4, svg_p->restart);
3224 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3225 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3226 out + 5, outsize + 5, svg_p->restart);
3228 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3229 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3230 out + 6, outsize + 6, svg_p->restart);
3232 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3233 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3234 out + 7, outsize + 7, svg_p->restart);
3236 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3237 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3238 out + 8, outsize + 8, svg_p->restart);
3240 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3241 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3242 out + 9, outsize + 9, svg_p->restart);
3244 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3245 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3246 out + 10, outsize + 10, svg_p->restart);
3248 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3249 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3250 out + 11, outsize + 11, svg_p->restart);
3252 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3253 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3254 out + 12, outsize + 12, svg_p->restart);
3256 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3257 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3258 out + 13, outsize + 13, svg_p->restart);
3261 if (action & F_END) {
3262 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3263 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3265 /* Free remaining structures */
3266 free_graphs(out, outsize, spmin, spmax);
3271 ***************************************************************************
3272 * Display ICMPv4 traffic errors statistics in SVG.
3275 * @a Activity structure with statistics.
3276 * @curr Index in array for current sample statistics.
3277 * @action Action expected from current function.
3278 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3279 * flag indicating that a restart record has been previously
3280 * found (.@restart) and time used for the X axis origin
3282 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3283 * @record_hdr Pointer on record header of current stats sample.
3284 ***************************************************************************
3286 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3287 unsigned long long itv, struct record_header *record_hdr)
3289 struct stats_net_eicmp
3290 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3291 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3292 int group[] = {2, 2, 2, 2, 2, 2};
3293 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3294 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3295 char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
3296 "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
3297 "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
3298 char *g_title[] = {"ierr/s", "oerr/s",
3299 "idstunr/s", "odstunr/s",
3300 "itmex/s", "otmex/s",
3301 "iparmpb/s", "oparmpb/s",
3302 "isrcq/s", "osrcq/s",
3303 "iredir/s", "oredir/s"};
3304 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3305 static double *spmin, *spmax;
3307 static int *outsize;
3309 if (action & F_BEGIN) {
3311 * Allocate arrays that will contain the graphs data
3312 * and the min/max values.
3314 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3317 if (action & F_MAIN) {
3318 /* Check for min/max values */
3319 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3320 itv, spmin, spmax, g_fields);
3323 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3324 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3325 out, outsize, svg_p->restart);
3327 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3328 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3329 out + 1, outsize + 1, svg_p->restart);
3331 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3332 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3333 out + 2, outsize + 2, svg_p->restart);
3335 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3336 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3337 out + 3, outsize + 3, svg_p->restart);
3339 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3340 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3341 out + 4, outsize + 4, svg_p->restart);
3343 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3344 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3345 out + 5, outsize + 5, svg_p->restart);
3347 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3348 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3349 out + 6, outsize + 6, svg_p->restart);
3351 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3352 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3353 out + 7, outsize + 7, svg_p->restart);
3355 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3356 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3357 out + 8, outsize + 8, svg_p->restart);
3359 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3360 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3361 out + 9, outsize + 9, svg_p->restart);
3363 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3364 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3365 out + 10, outsize + 10, svg_p->restart);
3367 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3368 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3369 out + 11, outsize + 11, svg_p->restart);
3372 if (action & F_END) {
3373 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3374 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3376 /* Free remaining structures */
3377 free_graphs(out, outsize, spmin, spmax);
3382 ***************************************************************************
3383 * Display TCPv4 traffic statistics in SVG.
3386 * @a Activity structure with statistics.
3387 * @curr Index in array for current sample statistics.
3388 * @action Action expected from current function.
3389 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3390 * flag indicating that a restart record has been previously
3391 * found (.@restart) and time used for the X axis origin
3393 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3394 * @record_hdr Pointer on record header of current stats sample.
3395 ***************************************************************************
3397 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3398 unsigned long long itv, struct record_header *record_hdr)
3400 struct stats_net_tcp
3401 *sntc = (struct stats_net_tcp *) a->buf[curr],
3402 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3403 int group[] = {2, 2};
3404 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3405 char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
3406 char *g_title[] = {"active/s", "passive/s",
3407 "iseg/s", "oseg/s"};
3408 int g_fields[] = {0, 1, 2, 3};
3409 static double *spmin, *spmax;
3411 static int *outsize;
3413 if (action & F_BEGIN) {
3415 * Allocate arrays that will contain the graphs data
3416 * and the min/max values.
3418 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3421 if (action & F_MAIN) {
3422 /* Check for min/max values */
3423 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3424 itv, spmin, spmax, g_fields);
3427 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3428 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3429 out, outsize, svg_p->restart);
3431 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3432 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3433 out + 1, outsize + 1, svg_p->restart);
3435 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3436 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3437 out + 2, outsize + 2, svg_p->restart);
3439 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3440 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3441 out + 3, outsize + 3, svg_p->restart);
3444 if (action & F_END) {
3445 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3446 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3448 /* Free remaining structures */
3449 free_graphs(out, outsize, spmin, spmax);
3454 ***************************************************************************
3455 * Display TCPv4 traffic errors statistics in SVG.
3458 * @a Activity structure with statistics.
3459 * @curr Index in array for current sample statistics.
3460 * @action Action expected from current function.
3461 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3462 * flag indicating that a restart record has been previously
3463 * found (.@restart) and time used for the X axis origin
3465 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3466 * @record_hdr Pointer on record header of current stats sample.
3467 ***************************************************************************
3469 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3470 unsigned long long itv, struct record_header *record_hdr)
3472 struct stats_net_etcp
3473 *snetc = (struct stats_net_etcp *) a->buf[curr],
3474 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3475 int group[] = {2, 3};
3476 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3477 char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
3478 char *g_title[] = {"atmptf/s", "estres/s",
3479 "retrans/s", "isegerr/s", "orsts/s"};
3480 int g_fields[] = {0, 1, 2, 3, 4};
3481 static double *spmin, *spmax;
3483 static int *outsize;
3485 if (action & F_BEGIN) {
3487 * Allocate arrays that will contain the graphs data
3488 * and the min/max values.
3490 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3493 if (action & F_MAIN) {
3494 /* Check for min/max values */
3495 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3496 itv, spmin, spmax, g_fields);
3499 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3500 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3501 out, outsize, svg_p->restart);
3503 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3504 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3505 out + 1, outsize + 1, svg_p->restart);
3507 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3508 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3509 out + 2, outsize + 2, svg_p->restart);
3511 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3512 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3513 out + 3, outsize + 3, svg_p->restart);
3515 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3516 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3517 out + 4, outsize + 4, svg_p->restart);
3520 if (action & F_END) {
3521 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3522 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3524 /* Free remaining structures */
3525 free_graphs(out, outsize, spmin, spmax);
3530 ***************************************************************************
3531 * Display UDPv4 traffic statistics in SVG.
3534 * @a Activity structure with statistics.
3535 * @curr Index in array for current sample statistics.
3536 * @action Action expected from current function.
3537 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3538 * flag indicating that a restart record has been previously
3539 * found (.@restart) and time used for the X axis origin
3541 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3542 * @record_hdr Pointer on record header of current stats sample.
3543 ***************************************************************************
3545 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3546 unsigned long long itv, struct record_header *record_hdr)
3548 struct stats_net_udp
3549 *snuc = (struct stats_net_udp *) a->buf[curr],
3550 *snup = (struct stats_net_udp *) a->buf[!curr];
3551 int group[] = {2, 2};
3552 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3553 char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
3554 char *g_title[] = {"idgm/s", "odgm/s",
3555 "noport/s", "idgmerr/s"};
3556 int g_fields[] = {0, 1, 2, 3};
3557 static double *spmin, *spmax;
3559 static int *outsize;
3561 if (action & F_BEGIN) {
3563 * Allocate arrays that will contain the graphs data
3564 * and the min/max values.
3566 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3569 if (action & F_MAIN) {
3570 /* Check for min/max values */
3571 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3572 itv, spmin, spmax, g_fields);
3575 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3576 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3577 out, outsize, svg_p->restart);
3579 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3580 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3581 out + 1, outsize + 1, svg_p->restart);
3583 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3584 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3585 out + 2, outsize + 2, svg_p->restart);
3587 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3588 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3589 out + 3, outsize + 3, svg_p->restart);
3592 if (action & F_END) {
3593 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3594 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3596 /* Free remaining structures */
3597 free_graphs(out, outsize, spmin, spmax);
3602 ***************************************************************************
3603 * Display IPV6 socket statistics in SVG.
3606 * @a Activity structure with statistics.
3607 * @curr Index in array for current sample statistics.
3608 * @action Action expected from current function.
3609 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3610 * flag indicating that a restart record has been previously
3611 * found (.@restart) and time used for the X axis origin
3613 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3614 * @record_hdr Pointer on record header of current stats sample.
3615 ***************************************************************************
3617 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3618 unsigned long long itv, struct record_header *record_hdr)
3620 struct stats_net_sock6
3621 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3623 int g_type[] = {SVG_LINE_GRAPH};
3624 char *title[] = {"IPv6 sockets statistics"};
3625 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3626 int g_fields[] = {0, 1, 2, 3};
3627 static double *spmin, *spmax;
3629 static int *outsize;
3631 if (action & F_BEGIN) {
3633 * Allocate arrays that will contain the graphs data
3634 * and the min/max values.
3636 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3639 if (action & F_MAIN) {
3640 /* Check for min/max values */
3641 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3642 itv, spmin, spmax, g_fields);
3644 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3645 (unsigned long long) snsc->tcp6_inuse,
3646 out, outsize, svg_p->restart);
3648 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3649 (unsigned long long) snsc->udp6_inuse,
3650 out + 1, outsize + 1, svg_p->restart);
3652 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3653 (unsigned long long) snsc->raw6_inuse,
3654 out + 2, outsize + 2, svg_p->restart);
3656 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3657 (unsigned long long) snsc->frag6_inuse,
3658 out + 3, outsize + 3, svg_p->restart);
3661 if (action & F_END) {
3662 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3663 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3665 /* Free remaining structures */
3666 free_graphs(out, outsize, spmin, spmax);
3671 ***************************************************************************
3672 * Display IPv6 traffic statistics in SVG.
3675 * @a Activity structure with statistics.
3676 * @curr Index in array for current sample statistics.
3677 * @action Action expected from current function.
3678 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3679 * flag indicating that a restart record has been previously
3680 * found (.@restart) and time used for the X axis origin
3682 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3683 * @record_hdr Pointer on record header of current stats sample.
3684 ***************************************************************************
3686 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3687 unsigned long long itv, struct record_header *record_hdr)
3689 struct stats_net_ip6
3690 *snic = (struct stats_net_ip6 *) a->buf[curr],
3691 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3692 int group[] = {4, 2, 2, 2};
3693 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3695 char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
3696 "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
3697 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3698 "asmrq6/s", "asmok6/s",
3699 "imcpck6/s", "omcpck6/s",
3700 "fragok6/s", "fragcr6/s"};
3701 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3702 static double *spmin, *spmax;
3704 static int *outsize;
3706 if (action & F_BEGIN) {
3708 * Allocate arrays that will contain the graphs data
3709 * and the min/max values.
3711 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3714 if (action & F_MAIN) {
3715 /* Check for min/max values */
3716 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3717 itv, spmin, spmax, g_fields);
3720 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3721 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3722 out, outsize, svg_p->restart);
3724 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3725 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3726 out + 1, outsize + 1, svg_p->restart);
3728 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3729 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3730 out + 2, outsize + 2, svg_p->restart);
3732 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3733 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3734 out + 3, outsize + 3, svg_p->restart);
3736 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3737 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3738 out + 4, outsize + 4, svg_p->restart);
3740 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3741 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3742 out + 5, outsize + 5, svg_p->restart);
3744 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3745 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3746 out + 6, outsize + 6, svg_p->restart);
3748 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3749 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3750 out + 7, outsize + 7, svg_p->restart);
3752 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3753 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3754 out + 8, outsize + 8, svg_p->restart);
3756 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3757 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3758 out + 9, outsize + 9, svg_p->restart);
3761 if (action & F_END) {
3762 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3763 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3765 /* Free remaining structures */
3766 free_graphs(out, outsize, spmin, spmax);
3771 ***************************************************************************
3772 * Display IPv6 traffic errors statistics in SVG.
3775 * @a Activity structure with statistics.
3776 * @curr Index in array for current sample statistics.
3777 * @action Action expected from current function.
3778 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3779 * flag indicating that a restart record has been previously
3780 * found (.@restart) and time used for the X axis origin
3782 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3783 * @record_hdr Pointer on record header of current stats sample.
3784 ***************************************************************************
3786 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3787 unsigned long long itv, struct record_header *record_hdr)
3789 struct stats_net_eip6
3790 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3791 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3792 int group[] = {4, 2, 2, 3};
3793 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3795 char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
3796 "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
3797 "IPv6 traffic errors statistics (5)"};
3798 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3799 "idisc6/s", "odisc6/s",
3800 "inort6/s", "onort6/s",
3801 "asmf6/s", "fragf6/s", "itrpck6/s"};
3802 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3803 static double *spmin, *spmax;
3805 static int *outsize;
3807 if (action & F_BEGIN) {
3809 * Allocate arrays that will contain the graphs data
3810 * and the min/max values.
3812 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3815 if (action & F_MAIN) {
3816 /* Check for min/max values */
3817 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3818 itv, spmin, spmax, g_fields);
3821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3822 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3823 out, outsize, svg_p->restart);
3825 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3826 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3827 out + 1, outsize + 1, svg_p->restart);
3829 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3830 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3831 out + 2, outsize + 2, svg_p->restart);
3833 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3834 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3835 out + 3, outsize + 3, svg_p->restart);
3837 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3838 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3839 out + 4, outsize + 4, svg_p->restart);
3841 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3842 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3843 out + 5, outsize + 5, svg_p->restart);
3845 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3846 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3847 out + 6, outsize + 6, svg_p->restart);
3849 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3850 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3851 out + 7, outsize + 7, svg_p->restart);
3853 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3854 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3855 out + 8, outsize + 8, svg_p->restart);
3857 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3858 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3859 out + 9, outsize + 9, svg_p->restart);
3861 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3862 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3863 out + 10, outsize + 10, svg_p->restart);
3866 if (action & F_END) {
3867 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3868 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
3870 /* Free remaining structures */
3871 free_graphs(out, outsize, spmin, spmax);
3876 ***************************************************************************
3877 * Display ICMPv6 traffic statistics in SVG.
3880 * @a Activity structure with statistics.
3881 * @curr Index in array for current sample statistics.
3882 * @action Action expected from current function.
3883 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3884 * flag indicating that a restart record has been previously
3885 * found (.@restart) and time used for the X axis origin
3887 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3888 * @record_hdr Pointer on record header of current stats sample.
3889 ***************************************************************************
3891 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3892 unsigned long long itv, struct record_header *record_hdr)
3894 struct stats_net_icmp6
3895 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3896 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3897 int group[] = {2, 3, 5, 3, 4};
3898 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3899 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3900 char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
3901 "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
3902 "ICMPv6 traffic statistics (5)"};
3903 char *g_title[] = {"imsg6/s", "omsg6/s",
3904 "iech6/s", "iechr6/s", "oechr6/s",
3905 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3906 "irtsol6/s", "ortsol6/s", "irtad6/s",
3907 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3908 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3909 static double *spmin, *spmax;
3911 static int *outsize;
3913 if (action & F_BEGIN) {
3915 * Allocate arrays that will contain the graphs data
3916 * and the min/max values.
3918 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3921 if (action & F_MAIN) {
3922 /* Check for min/max values */
3923 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3924 itv, spmin, spmax, g_fields);
3927 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3928 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3929 out, outsize, svg_p->restart);
3931 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3932 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3933 out + 1, outsize + 1, svg_p->restart);
3935 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3936 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3937 out + 2, outsize + 2, svg_p->restart);
3939 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3940 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3941 out + 3, outsize + 3, svg_p->restart);
3943 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3944 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3945 out + 4, outsize + 4, svg_p->restart);
3947 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3948 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3949 out + 5, outsize + 5, svg_p->restart);
3951 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3952 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3953 out + 6, outsize + 6, svg_p->restart);
3955 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3956 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3957 out + 7, outsize + 7, svg_p->restart);
3959 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3960 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3961 out + 8, outsize + 8, svg_p->restart);
3963 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3964 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3965 out + 9, outsize + 9, svg_p->restart);
3967 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3968 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3969 out + 10, outsize + 10, svg_p->restart);
3971 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3972 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3973 out + 11, outsize + 11, svg_p->restart);
3975 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3976 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3977 out + 12, outsize + 12, svg_p->restart);
3979 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3980 S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
3981 out + 13, outsize + 13, svg_p->restart);
3983 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3984 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3985 out + 14, outsize + 14, svg_p->restart);
3987 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3988 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3989 out + 15, outsize + 15, svg_p->restart);
3991 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3992 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3993 out + 16, outsize + 16, svg_p->restart);
3996 if (action & F_END) {
3997 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3998 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4000 /* Free remaining structures */
4001 free_graphs(out, outsize, spmin, spmax);
4006 ***************************************************************************
4007 * Display ICMPv6 traffic errors statistics in SVG.
4010 * @a Activity structure with statistics.
4011 * @curr Index in array for current sample statistics.
4012 * @action Action expected from current function.
4013 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4014 * flag indicating that a restart record has been previously
4015 * found (.@restart) and time used for the X axis origin
4017 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4018 * @record_hdr Pointer on record header of current stats sample.
4019 ***************************************************************************
4021 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4022 unsigned long long itv, struct record_header *record_hdr)
4024 struct stats_net_eicmp6
4025 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
4026 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
4027 int group[] = {1, 2, 2, 2, 2, 2};
4028 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
4029 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4030 char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
4031 "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
4032 "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
4033 char *g_title[] = {"ierr6/s",
4034 "idtunr6/s", "odtunr6/s",
4035 "itmex6/s", "otmex6/s",
4036 "iprmpb6/s", "oprmpb6/s",
4037 "iredir6/s", "oredir6/s",
4038 "ipck2b6/s", "opck2b6/s"};
4039 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4040 static double *spmin, *spmax;
4042 static int *outsize;
4044 if (action & F_BEGIN) {
4046 * Allocate arrays that will contain the graphs data
4047 * and the min/max values.
4049 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4052 if (action & F_MAIN) {
4053 /* Check for min/max values */
4054 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4055 itv, spmin, spmax, g_fields);
4058 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4059 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4060 out, outsize, svg_p->restart);
4062 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4063 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4064 out + 1, outsize + 1, svg_p->restart);
4066 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4067 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4068 out + 2, outsize + 2, svg_p->restart);
4070 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4071 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4072 out + 3, outsize + 3, svg_p->restart);
4074 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4075 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4076 out + 4, outsize + 4, svg_p->restart);
4078 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4079 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4080 out + 5, outsize + 5, svg_p->restart);
4082 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4083 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4084 out + 6, outsize + 6, svg_p->restart);
4086 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4087 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4088 out + 7, outsize + 7, svg_p->restart);
4090 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4091 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4092 out + 8, outsize + 8, svg_p->restart);
4094 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4095 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4096 out + 9, outsize + 9, svg_p->restart);
4098 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4099 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4100 out + 10, outsize + 10, svg_p->restart);
4103 if (action & F_END) {
4104 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4105 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4107 /* Free remaining structures */
4108 free_graphs(out, outsize, spmin, spmax);
4113 ***************************************************************************
4114 * Display UDPv6 traffic statistics in SVG.
4117 * @a Activity structure with statistics.
4118 * @curr Index in array for current sample statistics.
4119 * @action Action expected from current function.
4120 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4121 * flag indicating that a restart record has been previously
4122 * found (.@restart) and time used for the X axis origin
4124 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4125 * @record_hdr Pointer on record header of current stats sample.
4126 ***************************************************************************
4128 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4129 unsigned long long itv, struct record_header *record_hdr)
4131 struct stats_net_udp6
4132 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4133 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4134 int group[] = {2, 2};
4135 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4136 char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
4137 char *g_title[] = {"idgm6/s", "odgm6/s",
4138 "noport6/s", "idgmer6/s"};
4139 int g_fields[] = {0, 1, 2, 3};
4140 static double *spmin, *spmax;
4142 static int *outsize;
4144 if (action & F_BEGIN) {
4146 * Allocate arrays that will contain the graphs data
4147 * and the min/max values.
4149 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4152 if (action & F_MAIN) {
4153 /* Check for min/max values */
4154 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4155 itv, spmin, spmax, g_fields);
4158 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4159 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4160 out, outsize, svg_p->restart);
4162 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4163 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4164 out + 1, outsize + 1, svg_p->restart);
4166 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4167 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4168 out + 2, outsize + 2, svg_p->restart);
4170 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4171 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4172 out + 3, outsize + 3, svg_p->restart);
4175 if (action & F_END) {
4176 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4177 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4179 /* Free remaining structures */
4180 free_graphs(out, outsize, spmin, spmax);
4185 ***************************************************************************
4186 * Display CPU frequency statistics in SVG.
4189 * @a Activity structure with statistics.
4190 * @curr Index in array for current sample statistics.
4191 * @action Action expected from current function.
4192 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4193 * flag indicating that a restart record has been previously
4194 * found (.@restart) and time used for the X axis origin
4196 * @itv Interval of time in 1/100th of a second (unused here).
4197 * @record_hdr Pointer on record header of current stats sample.
4198 ***************************************************************************
4200 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4201 unsigned long long itv, struct record_header *record_hdr)
4203 struct stats_pwr_cpufreq *spc, *spp;
4205 int g_type[] = {SVG_LINE_GRAPH};
4206 char *title[] = {"CPU clock frequency"};
4207 char *g_title[] = {"MHz"};
4208 static double *spmin, *spmax;
4210 static int *outsize;
4214 if (action & F_BEGIN) {
4216 * Allocate arrays that will contain the graphs data
4217 * and the min/max values.
4219 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4222 if (action & F_MAIN) {
4224 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4226 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4227 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4229 /* Should current CPU (including CPU "all") be displayed? */
4230 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4235 * Note: Don't skip offline CPU here as it is needed
4236 * to make the graph go though 0.
4240 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4241 ((double) spp->cpufreq) / 100,
4242 ((double) spc->cpufreq) / 100,
4243 out + i, outsize + i, svg_p->restart, svg_p->dt,
4244 spmin + i, spmax + i);
4248 if (action & F_END) {
4251 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
4253 /* Should current CPU (including CPU "all") be displayed? */
4254 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4259 /* This is CPU "all" */
4260 strcpy(item_name, "all");
4264 * If the maximum frequency reached by the CPU is 0, then
4265 * the CPU has been offline on the whole period.
4266 * => Don't display it.
4268 if (*(spmax + i) == 0)
4271 sprintf(item_name, "%d", i - 1);
4274 if (draw_activity_graphs(a->g_nr, g_type,
4275 title, g_title, item_name, group,
4276 spmin + i, spmax + i, out + i, outsize + i,
4277 svg_p, record_hdr, i, a->id, xid)) {
4282 /* Free remaining structures */
4283 free_graphs(out, outsize, spmin, spmax);
4288 ***************************************************************************
4289 * Display fan statistics in SVG.
4292 * @a Activity structure with statistics.
4293 * @curr Index in array for current sample statistics.
4294 * @action Action expected from current function.
4295 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4296 * flag indicating that a restart record has been previously
4297 * found (.@restart) and time used for the X axis origin
4299 * @itv Interval of time in 1/100th of a second (unused here).
4300 * @record_hdr Pointer on record header of current stats sample.
4301 ***************************************************************************
4303 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4304 unsigned long long itv, struct record_header *record_hdr)
4306 struct stats_pwr_fan *spc, *spp;
4308 int g_type[] = {SVG_LINE_GRAPH};
4309 char *title[] = {"Fans speed"};
4310 char *g_title[] = {"~rpm"};
4311 static double *spmin, *spmax;
4313 static int *outsize;
4314 char item_name[MAX_SENSORS_DEV_LEN + 8];
4317 if (action & F_BEGIN) {
4319 * Allocate arrays that will contain the graphs data
4320 * and the min/max values.
4322 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4325 if (action & F_MAIN) {
4327 for (i = 0; i < a->nr[curr]; i++) {
4329 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4330 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4333 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4336 out + i, outsize + i, svg_p->restart, svg_p->dt,
4337 spmin + i, spmax + i);
4341 if (action & F_END) {
4344 for (i = 0; i < svg_p->nr_max; i++) {
4346 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4348 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4349 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4351 if (draw_activity_graphs(a->g_nr, g_type,
4352 title, g_title, item_name, group,
4353 spmin + i, spmax + i, out + i, outsize + i,
4354 svg_p, record_hdr, FALSE, a->id, xid)) {
4359 /* Free remaining structures */
4360 free_graphs(out, outsize, spmin, spmax);
4365 ***************************************************************************
4366 * Display temperature statistics in SVG.
4369 * @a Activity structure with statistics.
4370 * @curr Index in array for current sample statistics.
4371 * @action Action expected from current function.
4372 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4373 * flag indicating that a restart record has been previously
4374 * found (.@restart) and time used for the X axis origin
4376 * @itv Interval of time in 1/100th of a second (unused here).
4377 * @record_hdr Pointer on record header of current stats sample.
4378 ***************************************************************************
4380 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4381 unsigned long long itv, struct record_header *record_hdr)
4383 struct stats_pwr_temp *spc;
4384 int group[] = {1, 1};
4385 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4386 char *title[] = {"Devices temperature (1)",
4387 "Devices temperature (2)"};
4388 char *g_title[] = {"~degC",
4390 static double *spmin, *spmax;
4392 static int *outsize;
4393 char item_name[MAX_SENSORS_DEV_LEN + 8];
4397 if (action & F_BEGIN) {
4399 * Allocate arrays that will contain the graphs data
4400 * and the min/max values.
4402 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4405 if (action & F_MAIN) {
4406 /* For each temperature sensor */
4407 for (i = 0; i < a->nr[curr]; i++) {
4409 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4411 /* Look for min/max values */
4412 if (spc->temp < *(spmin + 2 * i)) {
4413 *(spmin + 2 * i) = spc->temp;
4415 if (spc->temp > *(spmax + 2 * i)) {
4416 *(spmax + 2 * i) = spc->temp;
4418 tval = (spc->temp_max - spc->temp_min) ?
4419 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4421 if (tval < *(spmin + 2 * i + 1)) {
4422 *(spmin + 2 * i + 1) = tval;
4424 if (tval > *(spmax + 2 * i + 1)) {
4425 *(spmax + 2 * i + 1) = tval;
4429 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4431 out + 2 * i, outsize + 2 * i, svg_p->restart);
4433 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4435 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4439 if (action & F_END) {
4442 for (i = 0; i < svg_p->nr_max; i++) {
4444 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4446 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4447 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4449 if (draw_activity_graphs(a->g_nr, g_type,
4450 title, g_title, item_name, group,
4451 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4452 svg_p, record_hdr, FALSE, a->id, xid)) {
4457 /* Free remaining structures */
4458 free_graphs(out, outsize, spmin, spmax);
4463 ***************************************************************************
4464 * Display voltage inputs statistics in SVG.
4467 * @a Activity structure with statistics.
4468 * @curr Index in array for current sample statistics.
4469 * @action Action expected from current function.
4470 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4471 * flag indicating that a restart record has been previously
4472 * found (.@restart) and time used for the X axis origin
4474 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4475 * @record_hdr Pointer on record header of current stats sample.
4476 ***************************************************************************
4478 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4479 unsigned long long itv, struct record_header *record_hdr)
4481 struct stats_pwr_in *spc;
4482 int group[] = {1, 1};
4483 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4484 char *title[] = {"Voltage inputs statistics (1)",
4485 "Voltage inputs statistics (2)"};
4486 char *g_title[] = {"inV",
4488 static double *spmin, *spmax;
4490 static int *outsize;
4491 char item_name[MAX_SENSORS_DEV_LEN + 8];
4495 if (action & F_BEGIN) {
4497 * Allocate arrays that will contain the graphs data
4498 * and the min/max values.
4500 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4503 if (action & F_MAIN) {
4504 /* For each voltage input sensor */
4505 for (i = 0; i < a->nr[curr]; i++) {
4507 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4509 /* Look for min/max values */
4510 if (spc->in < *(spmin + 2 * i)) {
4511 *(spmin + 2 * i) = spc->in;
4513 if (spc->in > *(spmax + 2 * i)) {
4514 *(spmax + 2 * i) = spc->in;
4516 tval = (spc->in_max - spc->in_min) ?
4517 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4519 if (tval < *(spmin + 2 * i + 1)) {
4520 *(spmin + 2 * i + 1) = tval;
4522 if (tval > *(spmax + 2 * i + 1)) {
4523 *(spmax + 2 * i + 1) = tval;
4527 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4529 out + 2 * i, outsize + 2 * i, svg_p->restart);
4531 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4533 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4537 if (action & F_END) {
4540 for (i = 0; i < svg_p->nr_max; i++) {
4542 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4544 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4545 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4547 if (draw_activity_graphs(a->g_nr, g_type,
4548 title, g_title, item_name, group,
4549 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4550 svg_p, record_hdr, FALSE, a->id, xid)) {
4555 /* Free remaining structures */
4556 free_graphs(out, outsize, spmin, spmax);
4561 ***************************************************************************
4562 * Display huge pages statistics in SVG.
4565 * @a Activity structure with statistics.
4566 * @curr Index in array for current sample statistics.
4567 * @action Action expected from current function.
4568 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4569 * flag indicating that a restart record has been previously
4570 * found (.@restart) and time used for the X axis origin
4572 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4573 * @record_hdr Pointer on record header of current stats sample.
4574 ***************************************************************************
4576 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4577 unsigned long long itv, struct record_header *record_hdr)
4580 *smc = (struct stats_huge *) a->buf[curr];
4581 int group[] = {2, 1};
4582 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4583 char *title[] = {"Huge pages utilization (1)",
4584 "Huge pages utilization (2)"};
4585 char *g_title[] = {"~kbhugfree", "~kbhugused",
4587 int g_fields[] = {0};
4588 unsigned int local_types_nr[] = {0, 1, 0};
4589 static double *spmin, *spmax;
4591 static int *outsize;
4594 if (action & F_BEGIN) {
4596 * Allocate arrays that will contain the graphs data
4597 * and the min/max values.
4599 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4602 if (action & F_MAIN) {
4603 /* Check for min/max values */
4604 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4605 itv, spmin, spmax, g_fields);
4607 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4608 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4610 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4611 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4613 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4614 if (tval < *(spmin + 2)) {
4615 *(spmin + 2) = tval;
4617 if (tval > *(spmax + 2)) {
4618 *(spmax + 2) = tval;
4622 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4623 (unsigned long long) smc->frhkb,
4624 out, outsize, svg_p->restart);
4626 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4627 (unsigned long long) smc->tlhkb - smc->frhkb,
4628 out + 1, outsize + 1, svg_p->restart);
4630 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4632 out + 2, outsize + 2, svg_p->dt);
4635 if (action & F_END) {
4636 draw_activity_graphs(a->g_nr, g_type,
4637 title, g_title, NULL, group,
4638 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a->id, 0);
4640 /* Free remaining structures */
4641 free_graphs(out, outsize, spmin, spmax);
4646 ***************************************************************************
4647 * Display filesystem statistics in SVG.
4650 * @a Activity structure with statistics.
4651 * @curr Index in array for current sample statistics.
4652 * @action Action expected from current function.
4653 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4654 * flag indicating that a restart record has been previously
4655 * found (.@restart) and time used for the X axis origin
4657 * @itv Interval of time in 1/100th of a second (unused here).
4658 * @record_hdr Pointer on record header of current stats sample.
4659 ***************************************************************************
4661 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4662 unsigned long long itv, struct record_header *record_hdr)
4664 struct stats_filesystem *sfc, *sfp;
4665 int group[] = {2, 2, 2, 1};
4666 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4667 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4668 char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
4669 "Filesystems statistics (3)", "Filesystems statistics (4)"};
4670 char *g_title[] = {"~MBfsfree", "~MBfsused",
4671 "%ufsused", "%fsused",
4672 "Ifree/1000", "Iused/1000",
4674 static double *spmin, *spmax;
4676 static int *outsize;
4679 int i, k, pos, restart;
4681 if (action & F_BEGIN) {
4683 * Allocate arrays (#0..6) that will contain the graphs data
4684 * and the min/max values.
4685 * Also allocate two additional arrays (#7..8) for each filesystem:
4686 * out + 7 will contain the filesystem name,
4687 * out + 8 will contain the mount point.
4689 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
4692 if (action & F_MAIN) {
4693 /* For each filesystem structure */
4694 for (i = 0; i < a->nr[curr]; i++) {
4695 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4698 /* A list of devices has been entered on the command line */
4699 if (!search_sa_dlist(st_fs_list, dlst_fs_idx,
4700 DISPLAY_MOUNT(a->opt_flags) ? sfc->mountp : sfc->fs_name))
4701 /* Device not found */
4705 /* Look for corresponding graph */
4706 for (k = 0; k < svg_p->nr_max; k++) {
4707 item_name = *(out + k * 9 + 7);
4708 if (!strcmp(sfc->fs_name, item_name))
4713 if (k == svg_p->nr_max) {
4714 /* Graph not found: Look for first free entry */
4715 for (k = 0; k < svg_p->nr_max; k++) {
4716 item_name = *(out + k * 9 + 7);
4717 if (!strcmp(item_name, ""))
4720 if (k == svg_p->nr_max) {
4721 /* No free graph entry: Extend all buffers */
4722 reallocate_all_graph_lines(9 * svg_p->nr_max,
4723 &out, &outsize, &spmin, &spmax);
4730 item_name = *(out + pos + 7);
4731 if (!item_name[0]) {
4732 /* Save filesystem name and mount point (if not already done) */
4733 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4734 item_name[CHUNKSIZE - 1] = '\0';
4735 item_name = *(out + pos + 8);
4736 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4737 item_name[CHUNKSIZE - 1] = '\0';
4741 for (k = 0; k < a->nr[!curr]; k++) {
4742 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4743 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4744 /* Filesystem found in previous sample */
4745 restart = svg_p->restart;
4749 /* Check for min/max values */
4751 /* Compute fsfree min/max values */
4752 tval = (double) sfc->f_bfree;
4753 if (tval > *(spmax + pos)) {
4754 *(spmax + pos) = tval;
4756 if (tval < *(spmin + pos)) {
4757 *(spmin + pos) = tval;
4759 /* Compute fsused min/max values */
4760 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4761 if (tval > *(spmax + pos + 1)) {
4762 *(spmax + pos + 1) = tval;
4764 if (tval < *(spmin + pos + 1)) {
4765 *(spmin + pos + 1) = tval;
4767 /* Compute %ufsused min/max values */
4768 tval = sfc->f_blocks ?
4769 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4770 if (tval > *(spmax + pos + 2)) {
4771 *(spmax + pos + 2) = tval;
4773 if (tval < *(spmin + pos + 2)) {
4774 *(spmin + pos + 2) = tval;
4776 /* Compute %fsused min/max values */
4777 tval = sfc->f_blocks ?
4778 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4779 if (tval > *(spmax + pos + 3)) {
4780 *(spmax + pos + 3) = tval;
4782 if (tval < *(spmin + pos + 3)) {
4783 *(spmin + pos + 3) = tval;
4785 /* Compute Ifree min/max values */
4786 tval = (double) sfc->f_ffree;
4787 if (tval > *(spmax + pos + 4)) {
4788 *(spmax + pos + 4) = tval;
4790 if (tval < *(spmin + pos + 4)) {
4791 *(spmin + pos + 4) = tval;
4793 /* Compute Iused min/max values */
4794 tval = (double) (sfc->f_files - sfc->f_ffree);
4795 if (tval > *(spmax + pos + 5)) {
4796 *(spmax + pos + 5) = tval;
4798 if (tval < *(spmin + pos + 5)) {
4799 *(spmin + pos + 5) = tval;
4801 /* Compute %Iused min/max values */
4802 tval = sfc->f_files ?
4803 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4804 if (tval > *(spmax + pos + 6)) {
4805 *(spmax + pos + 6) = tval;
4807 if (tval < *(spmin + pos + 6)) {
4808 *(spmin + pos + 6) = tval;
4812 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4813 (double) sfc->f_bfree / 1024 / 1024,
4814 out + pos, outsize + pos, restart);
4816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4817 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4818 out + pos + 1, outsize + pos + 1, restart);
4820 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4823 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4824 out + pos + 2, outsize + pos + 2, svg_p->dt);
4826 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4829 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4830 out + pos + 3, outsize + pos + 3, svg_p->dt);
4832 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4833 ((double) sfc->f_ffree) / 1000,
4834 out + pos + 4, outsize + pos + 4, restart);
4836 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4837 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4838 out + pos + 5, outsize + pos + 5, restart);
4840 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4843 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4844 out + pos + 6, outsize + pos + 6, svg_p->dt);
4848 if (action & F_END) {
4851 for (i = 0; i < svg_p->nr_max; i++) {
4853 /* Check if there is something to display */
4858 /* Conversion B -> MB and inodes/1000 */
4859 for (k = 0; k < 2; k++) {
4860 *(spmin + pos + k) /= (1024 * 1024);
4861 *(spmax + pos + k) /= (1024 * 1024);
4862 *(spmin + pos + 4 + k) /= 1000;
4863 *(spmax + pos + 4 + k) /= 1000;
4866 if (DISPLAY_MOUNT(a->opt_flags)) {
4867 item_name = *(out + pos + 8);
4870 item_name = *(out + pos + 7);
4873 if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4874 spmin + pos, spmax + pos, out + pos, outsize + pos,
4875 svg_p, record_hdr, FALSE, a->id, xid)) {
4880 /* Free remaining structures */
4881 free_graphs(out, outsize, spmin, spmax);
4886 ***************************************************************************
4887 * Display Fibre Channel HBA statistics in SVG.
4890 * @a Activity structure with statistics.
4891 * @curr Index in array for current sample statistics.
4892 * @action Action expected from current function.
4893 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4894 * flag indicating that a restart record has been previously
4895 * found (.@restart) and time used for the X axis origin
4897 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4898 * @record_hdr Pointer on record header of current stats sample.
4899 ***************************************************************************
4901 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4902 unsigned long long itv, struct record_header *record_hdr)
4904 struct stats_fchost *sfcc, *sfcp;
4905 int group[] = {2, 2};
4906 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4907 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4908 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4909 "fch_rxw/s", "fch_txw/s"};
4910 int g_fields[] = {0, 1, 2, 3};
4911 static double *spmin, *spmax;
4913 static int *outsize;
4915 int i, j, j0, k, found, pos, restart, *unregistered;
4917 if (action & F_BEGIN) {
4919 * Allocate arrays (#0..3) that will contain the graphs data
4920 * and the min/max values.
4921 * Also allocate one additional array (#4) that will contain
4922 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4923 * has either still not been registered, or has been unregistered
4926 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
4929 if (action & F_MAIN) {
4930 restart = svg_p->restart;
4932 * Mark previously registered interfaces as now
4933 * possibly unregistered for all graphs.
4935 for (k = 0; k < svg_p->nr_max; k++) {
4936 unregistered = outsize + k * 5 + 4;
4937 if (*unregistered == FALSE) {
4938 *unregistered = MAYBE;
4942 /* For each FC HBA */
4943 for (i = 0; i < a->nr[curr]; i++) {
4947 if (a->nr[!curr] > 0) {
4948 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4950 /* Look for corresponding graph */
4951 for (k = 0; k < svg_p->nr_max; k++) {
4952 item_name = *(out + k * 5 + 4);
4953 if (!strcmp(sfcc->fchost_name, item_name))
4957 if (k == svg_p->nr_max) {
4958 /* Graph not found: Look for first free entry */
4959 for (k = 0; k < svg_p->nr_max; k++) {
4960 item_name = *(out + k * 5 + 4);
4961 if (!strcmp(item_name, ""))
4964 if (k == svg_p->nr_max) {
4965 /* No free graph entry: Extend all buffers */
4966 reallocate_all_graph_lines(5 * svg_p->nr_max,
4967 &out, &outsize, &spmin, &spmax);
4973 unregistered = outsize + pos + 4;
4975 /* Look for corresponding structure in previous iteration */
4978 if (j >= a->nr[!curr]) {
4979 j = a->nr[!curr] - 1;
4985 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4986 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4990 if (++j >= a->nr[!curr]) {
5001 * If current interface was marked as previously unregistered,
5002 * then set restart variable to TRUE so that the graph will be
5003 * discontinuous, and mark it as now registered.
5005 if (*unregistered == TRUE) {
5008 *unregistered = FALSE;
5010 item_name = *(out + pos + 4);
5011 if (!item_name[0]) {
5012 /* Save FC HBA name */
5013 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
5014 item_name[CHUNKSIZE - 1] = '\0';
5017 /* Look for min/max values */
5018 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
5019 itv, spmin + pos, spmax + pos, g_fields);
5022 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5023 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
5024 out + pos, outsize + pos, restart);
5026 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5027 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
5028 out + pos + 1, outsize + pos + 1, restart);
5030 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5031 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
5032 out + pos + 2, outsize + pos + 2, restart);
5034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5035 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
5036 out + pos + 3, outsize + pos + 3, restart);
5039 /* Mark interfaces not seen here as now unregistered */
5040 for (k = 0; k < svg_p->nr_max; k++) {
5041 unregistered = outsize + k * 5 + 4;
5042 if (*unregistered != FALSE) {
5043 *unregistered = TRUE;
5048 if (action & F_END) {
5049 for (i = 0; i < svg_p->nr_max; i++) {
5051 /* Check if there is something to display */
5056 item_name = *(out + pos + 4);
5057 draw_activity_graphs(a->g_nr, g_type,
5058 title, g_title, item_name, group,
5059 spmin + pos, spmax + pos, out + pos, outsize + pos,
5060 svg_p, record_hdr, FALSE, a->id, i);
5063 /* Free remaining structures */
5064 free_graphs(out, outsize, spmin, spmax);
5069 ***************************************************************************
5070 * Display softnet statistics in SVG.
5073 * @a Activity structure with statistics.
5074 * @curr Index in array for current sample statistics.
5075 * @action Action expected from current function.
5076 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5077 * flag indicating that a restart record has been previously
5078 * found (.@restart) and time used for the X axis origin
5080 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5081 * @record_hdr Pointer on record header of current stats sample.
5082 ***************************************************************************
5084 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5085 unsigned long long itv, struct record_header *record_hdr)
5087 struct stats_softnet *ssnc, *ssnp, ssnczero;
5088 int group[] = {2, 3};
5089 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5090 char *title[] = {"Software-based network processing statistics (1)",
5091 "Software-based network processing statistics (2)"};
5092 char *g_title[] = {"total/s", "dropd/s",
5093 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5094 int g_fields[] = {0, 1, 2, 3, 4};
5095 static double *spmin, *spmax;
5097 static int *outsize;
5099 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5100 int i, pos, restart;
5102 if (action & F_BEGIN) {
5104 * Allocate arrays that will contain the graphs data
5105 * and the min/max values.
5107 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
5110 if (action & F_MAIN) {
5111 memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
5113 /* @nr[curr] cannot normally be greater than @nr_ini */
5114 if (a->nr[curr] > a->nr_ini) {
5115 a->nr_ini = a->nr[curr];
5118 /* Compute statistics for CPU "all" */
5119 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5122 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5123 restart = svg_p->restart;
5125 /* Should current CPU (including CPU "all") be displayed? */
5126 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5130 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5131 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5133 /* Is current CPU marked offline? */
5134 if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
5136 * Yes and it doesn't follow a RESTART record.
5137 * To add a discontinuity in graph, we simulate
5141 if (svg_p->restart) {
5143 * CPU is offline and it follows a real
5144 * RESTART record. Ignore its current value
5145 * (no previous sample).
5152 /* Check for min/max values */
5153 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5154 itv, spmin + pos, spmax + pos, g_fields);
5157 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5158 S_VALUE(ssnp->processed, ssnc->processed, itv),
5159 out + pos, outsize + pos, restart);
5161 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5162 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5163 out + pos + 1, outsize + pos + 1, restart);
5165 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5166 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5167 out + pos + 2, outsize + pos + 2, restart);
5169 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5170 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5171 out + pos + 3, outsize + pos + 3, restart);
5173 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5174 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5175 out + pos + 4, outsize + pos + 4, restart);
5179 if (action & F_END) {
5180 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
5182 /* Should current CPU (including CPU "all") be displayed? */
5183 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5190 /* This is CPU "all" */
5191 strcpy(item_name, "all");
5194 sprintf(item_name, "%d", i - 1);
5197 draw_activity_graphs(a->g_nr, g_type,
5198 title, g_title, item_name, group,
5199 spmin + pos, spmax + pos, out + pos, outsize + pos,
5200 svg_p, record_hdr, FALSE, a->id, i);
5203 /* Free remaining structures */
5204 free_graphs(out, outsize, spmin, spmax);