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 unsigned int dm_major;
43 unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
44 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
45 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
46 0xcc3300, 0x50040f, 0xffffbf, 0x193d55};
47 #define SVG_COLORS_IDX_MASK 0x0f
50 ***************************************************************************
51 * Compare the values of a statistics sample with the max and min values
52 * already found in previous samples for this same activity. If some new
53 * min or max values are found, then save them.
54 * Assume values cannot be negative.
55 * The structure containing the statistics sample is composed of @llu_nr
56 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
57 * followed by @u_nr unsigned int fields.
60 * @types_nr Number of fields whose type is "long long", "long" and "int"
61 * composing the structure.
62 * @cs Pointer on current sample statistics structure.
63 * @ps Pointer on previous sample statistics structure (may be NULL).
64 * @itv Interval of time in 1/100th of a second.
65 * @spmin Array containing min values already found for this activity.
66 * @spmax Array containing max values already found for this activity.
67 * @g_fields Index in spmin/spmax arrays where extrema values for each
68 * activity metric will be saved. As a consequence spmin/spmax
69 * arrays may contain values in a different order than that of
70 * the fields in the statistics structure.
73 * @spmin Array containg the possible new min values for current activity.
74 * @spmax Array containg the possible new max values for current activity.
75 ***************************************************************************
77 void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
78 double *spmin, double *spmax, int g_fields[])
80 unsigned long long *lluc, *llup;
81 unsigned long *luc, *lup;
82 unsigned int *uc, *up;
86 /* Compare unsigned long long fields */
87 lluc = (unsigned long long *) cs;
88 llup = (unsigned long long *) ps;
89 for (i = 0; i < types_nr[0]; i++, m++) {
91 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
95 * If no pointer on previous sample has been given
96 * then the value is not a per-second one.
100 if (val < *(spmin + g_fields[m])) {
101 *(spmin + g_fields[m]) = val;
103 if (val > *(spmax + g_fields[m])) {
104 *(spmax + g_fields[m]) = val;
106 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
108 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
112 /* Compare unsigned long fields */
113 luc = (unsigned long *) lluc;
114 lup = (unsigned long *) llup;
115 for (i = 0; i < types_nr[1]; i++, m++) {
117 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
122 if (val < *(spmin + g_fields[m])) {
123 *(spmin + g_fields[m]) = val;
125 if (val > *(spmax + g_fields[m])) {
126 *(spmax + g_fields[m]) = val;
128 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
130 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
134 /* Compare unsigned int fields */
135 uc = (unsigned int *) luc;
136 up = (unsigned int *) lup;
137 for (i = 0; i < types_nr[2]; i++, m++) {
139 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
144 if (val < *(spmin + g_fields[m])) {
145 *(spmin + g_fields[m]) = val;
147 if (val > *(spmax + g_fields[m])) {
148 *(spmax + g_fields[m]) = val;
150 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
152 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
158 ***************************************************************************
159 * Find the min and max values of all the graphs that will be drawn in the
160 * same view. The graphs have their own min and max values in
161 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
164 * @pos Position in array for the first graph extrema value.
165 * @n Number of graphs to scan.
166 * @spmin Array containing min values for graphs.
167 * @spmax Array containing max values for graphs.
170 * @gmin Global min value found.
171 * @gmax Global max value found.
172 ***************************************************************************
174 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
175 double *gmin, double *gmax)
179 *gmin = *(spmin + pos);
180 *gmax = *(spmax + pos);
182 for (i = 1; i < n; i++) {
183 if (*(spmin + pos + i) < *gmin) {
184 *gmin = *(spmin + pos + i);
186 if (*(spmax + pos + i) > *gmax) {
187 *gmax = *(spmax + pos + i);
193 ***************************************************************************
194 * Allocate arrays used to save graphs data, min and max values.
195 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
196 * array is returned. This is equivalent to "char data[][n]" where each
197 * element is of indeterminate size and will contain the graph data (eg.
198 * << path d="M12,14 L13,16..." ... >>.
199 * The size of element data[i] is given by outsize[i].
200 * Also allocate an array to save min values (equivalent to "double spmin[n]")
201 * and an array for max values (equivalent to "double spmax[n]").
204 * @n Number of graphs to draw for current activity.
207 * @outsize Array that will contain the sizes of each element in array
208 * of chars. Equivalent to "int outsize[n]" with
209 * outsize[n] = sizeof(data[][n]).
210 * @spmin Array that will contain min values for current activity.
211 * @spmax Array that will contain max values for current activity.
214 * Pointer on array of arrays of chars that will contain the graphs data.
216 * NB: @min and @max arrays contain values in the same order as the fields
217 * in the statistics structure.
218 ***************************************************************************
220 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
227 * Allocate an array of pointers. Each of these pointers will
228 * be an array of chars.
230 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
234 /* Allocate array that will contain the size of each array of chars */
235 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
239 /* Allocate array that will contain the min value of each graph */
240 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
244 /* Allocate array that will contain the max value of each graph */
245 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
249 /* Allocate arrays of chars that will contain graphs data */
250 for (i = 0; i < n; i++) {
251 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
256 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
257 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
258 *(*spmin + i) = DBL_MAX; /* Init min and max values */
259 *(*spmax + i) = -DBL_MAX;
266 ***************************************************************************
267 * Reallocate all the arrays used to save graphs data, min and max values.
268 * The new size is the double of the original one.
271 * @n Number of slots currently allocated.
272 * @out Current pointer on arrays containing the graphs data.
273 * @outsize Current pointer on array containing the size of each element
275 * @spmin Current pointer on array containing min values.
276 * @spmax Current pointer on array containing max values.
279 * @out New pointer on arrays containing the graphs data.
280 * @outsize New pointer on array containing the size of each element
282 * @spmin New pointer on array containing min values.
283 * @spmax New pointer on array containing max values.
284 ***************************************************************************
286 void reallocate_all_graph_lines(int n, char ***out, int **outsize,
287 double **spmin, double **spmax)
292 /* Reallocate all the arrays */
293 SREALLOC(*out, char *, n * sizeof(char *) * 2);
294 SREALLOC(*outsize, int, n * sizeof(int) * 2);
295 SREALLOC(*spmin, double, n * sizeof(double) * 2);
296 SREALLOC(*spmax, double, n * sizeof(double) * 2);
298 /* Allocate arrays of chars that will contain graphs data for the newly allocated slots */
299 for (i = 0; i < n; i++) {
300 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
304 *(*out + n + i) = out_p;
306 *(*outsize + n + i) = CHUNKSIZE;
307 *(*spmin + n + i) = DBL_MAX;
308 *(*spmax + n + i) = -DBL_MAX;
313 ***************************************************************************
314 * Save SVG code for current graph.
317 * @data SVG code to append to current graph definition.
318 * @out Pointer on array of chars for current graph definition.
319 * @outsize Size of array of chars for current graph definition.
322 * @out Pointer on array of chars for current graph definition that
323 * has been updated with the addition of current sample data.
324 * @outsize Array that containing the (possibly new) sizes of each
325 * element in array of chars.
326 ***************************************************************************
328 void save_svg_data(char *data, char **out, int *outsize)
334 /* Determine space left in array */
335 len = *outsize - strlen(out_p) - 1;
336 if (strlen(data) >= len) {
338 * If current array of chars doesn't have enough space left
339 * then reallocate it with CHUNKSIZE more bytes.
341 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
343 *outsize += CHUNKSIZE;
346 strncat(out_p, data, len);
350 ***************************************************************************
351 * Update line graph definition by appending current X,Y coordinates.
354 * @timetag Timestamp in seconds since the epoch for current sample
355 * stats. Will be used as X coordinate.
356 * @value Value of current sample metric. Will be used as Y coordinate.
357 * @out Pointer on array of chars for current graph definition.
358 * @outsize Size of array of chars for current graph definition.
359 * @restart Set to TRUE if a RESTART record has been read since the last
363 * @out Pointer on array of chars for current graph definition that
364 * has been updated with the addition of current sample data.
365 * @outsize Array that containing the (possibly new) sizes of each
366 * element in array of chars.
367 ***************************************************************************
369 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
374 /* Prepare additional graph definition data */
375 snprintf(data, 128, " %c%llu,%.2f", restart ? 'M' : 'L', timetag, value);
378 save_svg_data(data, out, outsize);
382 ***************************************************************************
383 * Update line graph definition by appending current X,Y coordinates. Use
384 * (unsigned long) integer values here.
387 * @timetag Timestamp in seconds since the epoch for current sample
388 * stats. Will be used as X coordinate.
389 * @value Value of current sample metric. Will be used as Y coordinate.
390 * @out Pointer on array of chars for current graph definition.
391 * @outsize Size of array of chars for current graph definition.
392 * @restart Set to TRUE if a RESTART record has been read since the last
396 * @out Pointer on array of chars for current graph definition that
397 * has been updated with the addition of current sample data.
398 * @outsize Array that containing the (possibly new) sizes of each
399 * element in array of chars.
400 ***************************************************************************
402 void lniappend(unsigned long long timetag, unsigned long long value, char **out,
403 int *outsize, int restart)
407 /* Prepare additional graph definition data */
408 snprintf(data, 128, " %c%llu,%llu", restart ? 'M' : 'L', timetag, value);
411 save_svg_data(data, out, outsize);
415 ***************************************************************************
416 * Update bar graph definition by adding a new rectangle.
419 * @timetag Timestamp in seconds since the epoch for current sample
420 * stats. Will be used as X coordinate.
421 * @value Value of current sample metric. Will be used as rectangle
423 * @offset Offset for Y coordinate.
424 * @out Pointer on array of chars for current graph definition.
425 * @outsize Size of array of chars for current graph definition.
426 * @dt Interval of time in seconds between current and previous
430 * @out Pointer on array of chars for current graph definition that
431 * has been updated with the addition of current sample data.
432 * @outsize Array that containing the (possibly new) sizes of each
433 * element in array of chars.
434 ***************************************************************************
436 void brappend(unsigned long long timetag, double offset, double value, char **out,
437 int *outsize, unsigned long long dt)
441 /* Prepare additional graph definition data */
442 if ((value == 0.0) || (dt == 0))
443 /* Don't draw a flat rectangle! */
446 snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
447 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
450 save_svg_data(data, out, outsize);
455 ***************************************************************************
456 * Update CPU graph and min/max values for each metric.
459 * @timetag Timestamp in seconds since the epoch for current sample
460 * stats. Will be used as X coordinate.
461 * @offset Offset for Y coordinate.
462 * @value Value of current CPU metric. Will be used as rectangle
464 * @out Pointer on array of chars for current graph definition.
465 * @outsize Size of array of chars for current graph definition.
466 * @dt Interval of time in seconds between current and previous
468 * @spmin Min value already found for this CPU metric.
469 * @spmax Max value already found for this CPU metric.
472 * @offset New offset value, to use to draw next rectangle
473 * @out Pointer on array of chars for current graph definition that
474 * has been updated with the addition of current sample data.
475 * @outsize Array that containing the (possibly new) sizes of each
476 * element in array of chars.
477 ***************************************************************************
479 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
480 int *outsize, unsigned long long dt, double *spmin, double *spmax)
482 /* Save min and max values */
483 if (value < *spmin) {
486 if (value > *spmax) {
489 /* Prepare additional graph definition data */
490 brappend(timetag, *offset, value, out, outsize, dt);
496 ***************************************************************************
497 * Update rectangular graph and min/max values.
500 * @timetag Timestamp in seconds since the epoch for current sample
501 * stats. Will be used as X coordinate.
502 * @p_value Metric value for previous sample
503 * @value Metric value for current sample.
504 * @out Pointer on array of chars for current graph definition.
505 * @outsize Size of array of chars for current graph definition.
506 * @restart Set to TRUE if a RESTART record has been read since the last
508 * @dt Interval of time in seconds between current and previous
510 * @spmin Min value already found for this metric.
511 * @spmax Max value already found for this metric.
514 * @out Pointer on array of chars for current graph definition that
515 * has been updated with the addition of current sample data.
516 * @outsize Array that containing the (possibly new) sizes of each
517 * element in array of chars.
518 * @spmin Min value for this metric.
519 * @spmax Max value for this metric.
520 ***************************************************************************
522 void recappend(unsigned long long timetag, double p_value, double value, char **out,
523 int *outsize, int restart, unsigned long long dt,
524 double *spmin, double *spmax)
526 char data[128], data1[128], data2[128];
528 /* Save min and max values */
529 if (value < *spmin) {
532 if (value > *spmax) {
535 /* Prepare additional graph definition data */
537 snprintf(data1, 128, " M%llu,%.2f", timetag - dt, p_value);
540 if (p_value != value) {
541 snprintf(data2, 128, " L%llu,%.2f", timetag, value);
544 snprintf(data, 128, "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
545 p_value != value ? data2 : "");
548 save_svg_data(data, out, outsize);
552 ***************************************************************************
553 * Calculate 10 raised to the power of n.
556 * @n Power number to use.
559 * 10 raised to the power of n.
560 ***************************************************************************
562 unsigned int pwr10(int n)
567 for (i = 0; i < n; i++) {
575 ***************************************************************************
576 * Autoscale graphs of a given view.
579 * @asf_nr (Maximum) number of autoscale factors.
580 * @group Number of graphs in current view.
581 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
582 * @pos Position in array for the first graph in view.
583 * @gmax Global max value for all graphs in view.
584 * @spmax Array containing max values for graphs.
587 * @asfactor Autoscale factors (one for each graph).
588 ***************************************************************************
590 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
591 double gmax, double *spmax)
596 for (j = 0; j < asf_nr; j++) {
597 /* Init autoscale factors */
601 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
603 for (j = 0; (j < group) && (j < asf_nr); j++) {
604 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
607 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
608 if (strlen(val) > 0) {
609 asfactor[j] = pwr10(strlen(val) - 1);
616 ***************************************************************************
617 * Display background grid (horizontal lines) and corresponding graduations.
620 * @ypos Gap between two horizontal lines.
621 * @yfactor Scaling factor on Y axis.
622 * @lmax Max value for current view.
623 * @dp Number of decimal places for graduations.
624 ***************************************************************************
626 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
632 /* Display horizontal lines (except on X axis) */
634 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
635 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
636 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
640 * Display graduations.
641 * Use same rounded value for graduation numbers as for grid lines
642 * to make sure they are properly aligned.
644 sprintf(stmp, "%.2f", ypos * j);
645 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
646 "text-anchor: end\">%.*f.</text>\n",
647 (long) (atof(stmp) * yfactor), dp, ypos * j);
650 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
654 ***************************************************************************
655 * Display background grid (vertical lines) and corresponding graduations.
658 * @xpos Gap between two vertical lines.
659 * @xfactor Scaling factor on X axis.
660 * @v_gridnr Default number of vertical lines to display. The actual
661 * number may vary between this value and 2 times this value.
662 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
663 ***************************************************************************
665 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
667 struct record_header stamp;
669 char cur_time[TIMESTAMP_LEN];
672 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
675 * What really matters to know when we should stop drawing vertical lines
676 * is the time end. v_gridnr is only informative and used to calculate
677 * the gap between two lines.
679 for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
681 /* Display vertical lines */
682 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
683 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
684 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
685 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
686 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
688 * Display graduations.
689 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
690 * In this case, we should rather display the exact time instead of only the hour.
692 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
693 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
694 "text-anchor: start\">%2d:00</text>\n",
695 (long) (xpos * j * xfactor) - 15, rectime.tm_hour);
698 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
699 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
700 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
702 stamp.ust_time += xpos;
705 if (!PRINT_LOCAL_TIME(flags)) {
706 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
707 "text-anchor: end\">UTC</text>\n");
712 ***************************************************************************
713 * Calculate the value on the Y axis between two horizontal lines that will
714 * make the graph background grid.
717 * @lmax Max value reached for this graph.
720 * @dp Number of decimal places for Y graduations.
723 * Value between two horizontal lines.
724 ***************************************************************************
726 double ygrid(double lmax, int *dp)
737 n = (long) (lmax / SVG_H_GRIDNR);
740 return (lmax / SVG_H_GRIDNR);
742 snprintf(val, 32, "%ld", n);
749 return ((double) (((long) (n / e)) * e));
753 ***************************************************************************
754 * Calculate the value on the X axis between two vertical lines that will
755 * make the graph background grid.
758 * @timestart First data timestamp (X coordinate of the first data point).
759 * @timeend Last data timestamp (X coordinate of the last data point).
760 * @v_gridnr Number of vertical lines to display. Its value is normally
761 * SVG_V_GRIDNR, except when option "oneday" is used, in which
762 * case it is set to 12.
765 * Value between two vertical lines.
766 ***************************************************************************
768 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
770 if ((timeend - timestart) <= v_gridnr)
773 return ((timeend - timestart) / v_gridnr);
777 ***************************************************************************
778 * Free global graphs structures.
781 * @out Pointer on array of chars for each graph definition.
782 * @outsize Size of array of chars for each graph definition.
783 * @spmin Array containing min values for graphs.
784 * @spmax Array containing max values for graphs.
785 ***************************************************************************
787 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
804 ***************************************************************************
805 * Skip current view where all graphs have only zero values. This function
806 * is called when option "skipempty" has been used, or when "No data" have
807 * been found for current view.
810 * @out Pointer on array of chars for each graph definition.
811 * @pos Position of current view in the array of graphs definitions.
812 * @group Number of graphs in current view.
815 * @pos Position of next view in the array of graphs definitions.
816 ***************************************************************************
818 void skip_current_view(char **out, int *pos, int group)
823 for (j = 0; j < group; j++) {
824 out_p = *(out + *pos + j);
826 /* Even if not displayed, current graph data have to be freed */
834 ***************************************************************************
835 * Display all graphs for current activity.
838 * @g_nr Number of views to display.
839 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
840 * @title Titles for each set of graphs.
841 * @g_title Titles for each graph.
842 * @item_name Item (network interface, etc.) name.
843 * @group Indicate how graphs are grouped together to make sets.
844 * @spmin Array containing min values for graphs.
845 * @spmax Array containing max values for graphs.
846 * @out Pointer on array of chars for each graph definition.
847 * @outsize Size of array of chars for each graph definition.
848 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
849 * time for the first sample of stats (.@ust_time_first), and
850 * times used as start and end values on the X axis
851 * (.@ust_time_ref and .@ust_time_end).
852 * @record_hdr Pointer on record header of current stats sample.
853 * @skip_void Set to <> 0 if graphs with no data should be skipped.
854 * This is typicallly used to not display CPU offline on the
856 ***************************************************************************
858 void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
859 int group[], double *spmin, double *spmax, char **out, int *outsize,
860 struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void)
863 int i, j, dp, pos = 0, views_nr = 0;
864 int v_gridnr, xv, yv;
865 unsigned int asfactor[16];
867 double lmax, xfactor, yfactor, ypos, gmin, gmax;
868 char val[32], cur_date[TIMESTAMP_LEN];
870 /* Translate to proper position for current activity */
871 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
873 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
875 /* For each view which is part of current activity */
876 for (i = 0; i < g_nr; i++) {
878 /* Get global min and max value for current view */
879 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
881 /* Don't display empty views if requested */
882 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
883 skip_current_view(out, &pos, group[i]);
886 /* Skip void graphs */
887 if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
890 /* Increment number of views actually displayed */
893 /* Compute top left position of view */
894 if (PACK_VIEWS(flags)) {
895 xv = (views_nr - 1) * SVG_T_XSIZE;
900 yv = (views_nr - 1) * SVG_T_YSIZE;
903 /* Graph background */
904 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
905 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
908 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
909 xv, 20 + yv, title[i]);
911 printf(" [%s]", item_name);
914 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
915 "(Min, Max values)</tspan>\n</text>\n",
916 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
919 * At least two samples are needed.
920 * And a min and max value should have been found.
922 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
923 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
925 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
926 xv, yv + SVG_M_YSIZE);
927 skip_current_view(out, &pos, group[i]);
932 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
933 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
934 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
935 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
937 /* Autoscaling graphs if needed */
938 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
941 for (j = 0; j < group[i]; j++) {
942 /* Set dp to TRUE (1) if current metric is based on integer values */
943 dp = (g_title[pos + j][0] == '~');
944 snprintf(val, 32, "x%u ", asfactor[j]);
945 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
946 "%s %s(%.*f, %.*f)</text>\n",
947 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
948 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
949 asfactor[j] == 1 ? "" : val,
950 !dp * 2, *(spmin + pos + j) * asfactor[j],
951 !dp * 2, *(spmax + pos + j) * asfactor[j]);
954 if (DISPLAY_INFO(flags)) {
955 /* Display additional info (hostname, date) */
956 printf("<text x=\"%d\" y=\"%d\" "
957 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
959 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
960 svg_p->file_hdr->sa_nodename);
962 /* Get report date */
963 set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
964 cur_date, sizeof(cur_date));
965 printf("<tspan x=\"%d\" y=\"%d\" "
966 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
967 "%s</tspan>\n</text>\n",
968 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
972 /* Translate to proper position for current graph within current activity */
973 printf("<g transform=\"translate(%d,%d)\">\n",
974 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
977 if (g_type[i] == SVG_LINE_GRAPH) {
978 /* For line graphs */
980 /* If all values are zero then set current max value to 1 */
986 /* Max value cannot be too small, else Y graduations will be meaningless */
987 if (lmax < SVG_H_GRIDNR * 0.01) {
988 lmax = SVG_H_GRIDNR * 0.01;
990 ypos = ygrid(lmax, &dp);
993 /* For bar graphs (used for %values) */
994 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
995 dp = 0; /* No decimals */
997 /* Max should be always 100% except for percentage values greater than 100% */
1005 yfactor = (double) -SVG_G_YSIZE / lmax;
1007 /* Display horizontal lines and graduations */
1008 display_hgrid(ypos, yfactor, lmax, dp);
1010 /* Set number of vertical lines to 12 when option "oneday" is used */
1011 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1013 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1014 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1016 /* Display vertical lines and graduations */
1017 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1019 /* Draw current graphs set */
1020 for (j = 0; j < group[i]; j++) {
1021 out_p = *(out + pos + j);
1022 if (g_type[i] == SVG_LINE_GRAPH) {
1024 printf("<path id=\"g%dp%d\" d=\"%s\" "
1025 "style=\"vector-effect: non-scaling-stroke; "
1026 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1027 "transform=\"scale(%f,%f)\"/>\n",
1028 svg_p->graph_no, pos + j, out_p,
1029 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
1031 yfactor * asfactor[j]);
1033 else if (*out_p) { /* Ignore flat bars */
1035 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1036 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1037 printf("%s\n", out_p);
1047 /* For next row of views */
1048 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1052 ***************************************************************************
1053 * Display CPU statistics in SVG.
1056 * @a Activity structure with statistics.
1057 * @curr Index in array for current sample statistics.
1058 * @action Action expected from current function.
1059 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1060 * flag indicating that a restart record has been previously
1061 * found (.@restart), and time used for the X axis origin
1063 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1065 * @record_hdr Pointer on record header of current stats sample.
1066 ***************************************************************************
1068 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1069 unsigned long long itv, struct record_header *record_hdr)
1071 struct stats_cpu *scc, *scp;
1072 unsigned long long deltot_jiffies = 1;
1073 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
1076 int g_type[] = {SVG_BAR_GRAPH};
1077 char *title[] = {"CPU load"};
1078 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1079 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1080 static double *spmin, *spmax;
1082 static int *outsize;
1087 if (action & F_BEGIN) {
1089 * Allocate arrays that will contain the graphs data
1090 * and the min/max values.
1092 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
1095 if (action & F_MAIN) {
1097 /* @nr[curr] cannot normally be greater than @nr_ini */
1098 if (a->nr[curr] > a->nr_ini) {
1099 a->nr_ini = a->nr[curr];
1103 * Compute CPU "all" as sum of all individual CPU (on SMP machines)
1104 * and look for offline CPU.
1106 if (a->nr_ini > 1) {
1107 deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
1108 flags, offline_cpu_bitmap);
1112 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1114 /* Should current CPU (including CPU "all") be displayed? */
1115 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
1116 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
1117 /* Don't display CPU */
1120 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1121 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1127 /* This is CPU "all" */
1128 if (a->nr_ini == 1) {
1130 * This is a UP machine. In this case
1131 * interval has still not been calculated.
1133 deltot_jiffies = get_per_cpu_interval(scc, scp);
1138 * Recalculate interval for current proc.
1139 * If result is 0 then current CPU is a tickless one.
1141 deltot_jiffies = get_per_cpu_interval(scc, scp);
1143 if (!deltot_jiffies) { /* Current CPU is tickless */
1145 val = 100.0; /* Tickless CPU: %idle = 100% */
1147 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1150 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1154 /* Check min/max values for %user, etc. */
1155 for (k = 0; k < j; k++) {
1156 if (0.0 < *(spmin + pos + k)) {
1157 *(spmin + pos + k) = 0.0;
1159 if (0.0 > *(spmax + pos + k)) {
1160 *(spmax + pos + k) = 0.0;
1165 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1167 out + pos + j, outsize + pos + j, svg_p->dt,
1168 spmin + pos + j, spmax + pos + j);
1173 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1175 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1176 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1177 out + pos, outsize + pos, svg_p->dt,
1178 spmin + pos, spmax + pos);
1182 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1184 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1186 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1187 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1188 out + pos, outsize + pos, svg_p->dt,
1189 spmin + pos, spmax + pos);
1192 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1194 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1195 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1196 out + pos + 1, outsize + pos + 1, svg_p->dt,
1197 spmin + pos + 1, spmax + pos + 1);
1201 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1203 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1205 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1206 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1207 out + pos + 1, outsize + pos + 1, svg_p->dt,
1208 spmin + pos + 1, spmax + pos + 1);
1211 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1213 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1215 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1216 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1218 out + pos + 2, outsize + pos + 2, svg_p->dt,
1219 spmin + pos + 2, spmax + pos + 2);
1223 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1224 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1225 out + pos + 2, outsize + pos + 2, svg_p->dt,
1226 spmin + pos + 2, spmax + pos + 2);
1230 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1231 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1232 out + pos + 3, outsize + pos + 3, svg_p->dt,
1233 spmin + pos + 3, spmax + pos + 3);
1235 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1236 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1237 out + pos + 4, outsize + pos + 4, svg_p->dt,
1238 spmin + pos + 4, spmax + pos + 4);
1240 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1242 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1243 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1244 out + pos + 5, outsize + pos + 5, svg_p->dt,
1245 spmin + pos + 5, spmax + pos + 5);
1247 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1248 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1249 out + pos + 6, outsize + pos + 6, svg_p->dt,
1250 spmin + pos + 6, spmax + pos + 6);
1252 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1253 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1254 out + pos + 7, outsize + pos + 7, svg_p->dt,
1255 spmin + pos + 7, spmax + pos + 7);
1257 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1258 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1259 out + pos + 8, outsize + pos + 8, svg_p->dt,
1260 spmin + pos + 8, spmax + pos + 8);
1269 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1271 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1272 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1273 out + pos + j, outsize + pos + j, svg_p->dt,
1274 spmin + pos + j, spmax + pos + j);
1278 if (action & F_END) {
1279 if (DISPLAY_IDLE(flags)) {
1280 /* Include additional %idle field */
1285 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
1287 /* Should current CPU (including CPU "all") be displayed? */
1288 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1294 /* This is CPU "all" */
1295 strcpy(item_name, "all");
1298 sprintf(item_name, "%d", i - 1);
1301 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1302 draw_activity_graphs(a->g_nr, g_type,
1303 title, g_title1, item_name, group1,
1304 spmin + pos, spmax + pos, out + pos, outsize + pos,
1305 svg_p, record_hdr, i);
1308 draw_activity_graphs(a->g_nr, g_type,
1309 title, g_title2, item_name, group2,
1310 spmin + pos, spmax + pos, out + pos, outsize + pos,
1311 svg_p, record_hdr, i);
1315 /* Free remaining structures */
1316 free_graphs(out, outsize, spmin, spmax);
1321 ***************************************************************************
1322 * Display task creation and context switch statistics in SVG.
1325 * @a Activity structure with statistics.
1326 * @curr Index in array for current sample statistics.
1327 * @action Action expected from current function.
1328 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1329 * flag indicating that a restart record has been previously
1330 * found (.@restart) and time used for the X axis origin
1332 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1333 * @record_hdr Pointer on record header of current stats sample.
1334 ***************************************************************************
1336 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1337 unsigned long long itv, struct record_header *record_hdr)
1340 *spc = (struct stats_pcsw *) a->buf[curr],
1341 *spp = (struct stats_pcsw *) a->buf[!curr];
1342 int group[] = {1, 1};
1343 int g_fields[] = {1, 0};
1344 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1345 char *title[] = {"Task creation", "Switching activity"};
1346 char *g_title[] = {"proc/s",
1348 static double *spmin, *spmax;
1350 static int *outsize;
1352 if (action & F_BEGIN) {
1354 * Allocate arrays that will contain the graphs data
1355 * and the min/max values.
1357 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1360 if (action & F_MAIN) {
1361 /* Check for min/max values */
1362 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1363 itv, spmin, spmax, g_fields);
1365 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1366 S_VALUE(spp->processes, spc->processes, itv),
1367 out, outsize, svg_p->restart);
1369 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1370 S_VALUE(spp->context_switch, spc->context_switch, itv),
1371 out + 1, outsize + 1, svg_p->restart);
1374 if (action & F_END) {
1375 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1376 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1378 /* Free remaining structures */
1379 free_graphs(out, outsize, spmin, spmax);
1384 ***************************************************************************
1385 * Display swap statistics in SVG.
1388 * @a Activity structure with statistics.
1389 * @curr Index in array for current sample statistics.
1390 * @action Action expected from current function.
1391 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1392 * flag indicating that a restart record has been previously
1393 * found (.@restart) and time used for the X axis origin
1395 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1396 * @record_hdr Pointer on record header of current stats sample.
1397 ***************************************************************************
1399 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1400 unsigned long long itv, struct record_header *record_hdr)
1403 *ssc = (struct stats_swap *) a->buf[curr],
1404 *ssp = (struct stats_swap *) a->buf[!curr];
1406 int g_type[] = {SVG_LINE_GRAPH};
1407 char *title[] = {"Swap activity"};
1408 char *g_title[] = {"pswpin/s", "pswpout/s" };
1409 int g_fields[] = {0, 1};
1410 static double *spmin, *spmax;
1412 static int *outsize;
1414 if (action & F_BEGIN) {
1416 * Allocate arrays that will contain the graphs data
1417 * and the min/max values.
1419 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1422 if (action & F_MAIN) {
1423 /* Check for min/max values */
1424 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1425 itv, spmin, spmax, g_fields);
1427 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1428 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1429 out, outsize, svg_p->restart);
1431 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1432 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1433 out + 1, outsize + 1, svg_p->restart);
1436 if (action & F_END) {
1437 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1438 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1440 /* Free remaining structures */
1441 free_graphs(out, outsize, spmin, spmax);
1446 ***************************************************************************
1447 * Display paging statistics in SVG.
1450 * @a Activity structure with statistics.
1451 * @curr Index in array for current sample statistics.
1452 * @action Action expected from current function.
1453 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1454 * flag indicating that a restart record has been previously
1455 * found (.@restart) and time used for the X axis origin
1457 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1458 * @record_hdr Pointer on record header of current stats sample.
1459 ***************************************************************************
1461 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1462 unsigned long long itv, struct record_header *record_hdr)
1465 *spc = (struct stats_paging *) a->buf[curr],
1466 *spp = (struct stats_paging *) a->buf[!curr];
1467 int group[] = {2, 2, 4};
1468 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1469 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1470 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1471 "fault/s", "majflt/s",
1472 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1473 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1474 static double *spmin, *spmax;
1476 static int *outsize;
1478 if (action & F_BEGIN) {
1480 * Allocate arrays that will contain the graphs data
1481 * and the min/max values.
1483 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1486 if (action & F_MAIN) {
1487 /* Check for min/max values */
1488 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1489 itv, spmin, spmax, g_fields);
1491 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1492 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1493 out, outsize, svg_p->restart);
1495 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1496 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1497 out + 1, outsize + 1, svg_p->restart);
1499 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1500 S_VALUE(spp->pgfault, spc->pgfault, itv),
1501 out + 2, outsize + 2, svg_p->restart);
1503 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1504 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1505 out + 3, outsize + 3, svg_p->restart);
1507 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1508 S_VALUE(spp->pgfree, spc->pgfree, itv),
1509 out + 4, outsize + 4, svg_p->restart);
1511 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1512 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1513 out + 5, outsize + 5, svg_p->restart);
1515 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1516 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1517 out + 6, outsize + 6, svg_p->restart);
1519 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1520 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1521 out + 7, outsize + 7, svg_p->restart);
1524 if (action & F_END) {
1525 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1526 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1528 /* Free remaining structures */
1529 free_graphs(out, outsize, spmin, spmax);
1534 ***************************************************************************
1535 * Display I/O and transfer rate statistics in SVG.
1538 * @a Activity structure with statistics.
1539 * @curr Index in array for current sample statistics.
1540 * @action Action expected from current function.
1541 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1542 * flag indicating that a restart record has been previously
1543 * found (.@restart) and time used for the X axis origin
1545 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1546 * @record_hdr Pointer on record header of current stats sample.
1547 ***************************************************************************
1549 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1550 unsigned long long itv, struct record_header *record_hdr)
1553 *sic = (struct stats_io *) a->buf[curr],
1554 *sip = (struct stats_io *) a->buf[!curr];
1555 int group[] = {3, 2};
1556 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1557 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1558 char *g_title[] = {"tps", "rtps", "wtps",
1559 "bread/s", "bwrtn/s"};
1560 int g_fields[] = {0, 1, 2, 3, 4};
1561 static double *spmin, *spmax;
1563 static int *outsize;
1565 if (action & F_BEGIN) {
1567 * Allocate arrays that will contain the graphs data
1568 * and the min/max values.
1570 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1573 if (action & F_MAIN) {
1574 /* Check for min/max values */
1575 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1576 itv, spmin, spmax, g_fields);
1579 * If we get negative values, this is probably because
1580 * one or more devices/filesystems have been unmounted.
1581 * We display 0.0 in this case though we should rather tell
1582 * the user that the value cannot be calculated here.
1585 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1586 sic->dk_drive < sip->dk_drive ? 0.0 :
1587 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1588 out, outsize, svg_p->restart);
1590 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1591 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1592 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1593 out + 1, outsize + 1, svg_p->restart);
1595 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1596 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1597 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1598 out + 2, outsize + 2, svg_p->restart);
1600 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1601 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1602 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1603 out + 3, outsize + 3, svg_p->restart);
1605 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1606 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1607 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1608 out + 4, outsize + 4, svg_p->restart);
1611 if (action & F_END) {
1612 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1613 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1615 /* Free remaining structures */
1616 free_graphs(out, outsize, spmin, spmax);
1621 ***************************************************************************
1622 * Display memory statistics in SVG.
1625 * @a Activity structure with statistics.
1626 * @curr Index in array for current sample statistics.
1627 * @action Action expected from current function.
1628 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1629 * flag indicating that a restart record has been previously
1630 * found (.@restart) and time used for the X axis origin
1632 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1633 * @record_hdr Pointer on record header of current stats sample.
1634 ***************************************************************************
1636 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1637 unsigned long long itv, struct record_header *record_hdr)
1640 *smc = (struct stats_memory *) a->buf[curr];
1641 int group1[] = {3, 1, 3, 1, 3, 5};
1642 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1643 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1644 int group2[] = {3, 1, 1};
1645 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1646 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1647 "Memory utilization (3)", "Memory utilization (4)",
1648 "Memory utilization (5)", "Memory utilization (6)"};
1649 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1650 "Swap utilization (3)"};
1651 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1652 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1653 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1655 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1657 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1658 static double *spmin, *spmax;
1660 static int *outsize;
1664 if (action & F_BEGIN) {
1666 * Allocate arrays that will contain the graphs data
1667 * and the min/max values.
1669 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1672 if (action & F_MAIN) {
1673 /* Check for min/max values */
1674 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1675 itv, spmin, spmax, g_fields);
1676 /* Compute %memused min/max values */
1677 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1678 if (tval > *(spmax + 3)) {
1679 *(spmax + 3) = tval;
1681 if (tval < *(spmin + 3)) {
1682 *(spmin + 3) = tval;
1684 /* Compute %commit min/max values */
1685 tval = (smc->tlmkb + smc->tlskb) ?
1686 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1687 if (tval > *(spmax + 7)) {
1688 *(spmax + 7) = tval;
1690 if (tval < *(spmin + 7)) {
1691 *(spmin + 7) = tval;
1693 /* Compute %swpused min/max values */
1695 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1696 if (tval > *(spmax + 19)) {
1697 *(spmax + 19) = tval;
1699 if (tval < *(spmin + 19)) {
1700 *(spmin + 19) = tval;
1702 /* Compute %swpcad min/max values */
1703 tval = (smc->tlskb - smc->frskb) ?
1704 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1705 if (tval > *(spmax + 20)) {
1706 *(spmax + 20) = tval;
1708 if (tval < *(spmin + 20)) {
1709 *(spmin + 20) = tval;
1711 /* Compute memused min/max values in MB */
1712 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1713 if (tval > *(spmax + 2)) {
1714 *(spmax + 2) = tval;
1716 if (tval < *(spmin + 2)) {
1717 *(spmin + 2) = tval;
1719 /* Compute swpused min/max values in MB */
1720 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1721 if (tval > *(spmax + 17)) {
1722 *(spmax + 17) = tval;
1724 if (tval < *(spmin + 17)) {
1725 *(spmin + 17) = tval;
1729 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1730 ((double) smc->frmkb) / 1024,
1731 out, outsize, svg_p->restart);
1733 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1734 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1735 out + 2, outsize + 2, svg_p->restart);
1737 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1738 ((double) smc->availablekb) / 1024,
1739 out + 1, outsize + 1, svg_p->restart);
1741 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1742 ((double) smc->bufkb) / 1024,
1743 out + 4, outsize + 4, svg_p->restart);
1745 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1746 ((double) smc->camkb) / 1024,
1747 out + 5, outsize + 5, svg_p->restart);
1749 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1750 ((double) smc->frskb) / 1024,
1751 out + 16, outsize + 16, svg_p->restart);
1753 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1754 ((double) (smc->tlskb - smc->frskb)) / 1024,
1755 out + 17, outsize + 17, svg_p->restart);
1757 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1758 ((double) smc->caskb) / 1024,
1759 out + 18, outsize + 18, svg_p->restart);
1761 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1762 ((double) smc->comkb) / 1024,
1763 out + 6, outsize + 6, svg_p->restart);
1765 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1766 ((double) smc->activekb) / 1024,
1767 out + 8, outsize + 8, svg_p->restart);
1769 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1770 ((double) smc->inactkb) / 1024,
1771 out + 9, outsize + 9, svg_p->restart);
1773 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1774 ((double) smc->dirtykb) / 1024,
1775 out + 10, outsize + 10, svg_p->restart);
1777 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1778 ((double) smc->anonpgkb) / 1024,
1779 out + 11, outsize + 11, svg_p->restart);
1781 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1782 ((double) smc->slabkb) / 1024,
1783 out + 12, outsize + 12, svg_p->restart);
1785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1786 ((double) smc->kstackkb) / 1024,
1787 out + 13, outsize + 13, svg_p->restart);
1789 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1790 ((double) smc->pgtblkb) / 1024,
1791 out + 14, outsize + 14, svg_p->restart);
1793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1794 ((double) smc->vmusedkb) / 1024,
1795 out + 15, outsize + 15, svg_p->restart);
1797 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1800 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1801 out + 3, outsize + 3, svg_p->dt);
1803 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1805 (smc->tlmkb + smc->tlskb) ?
1806 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1807 out + 7, outsize + 7, svg_p->dt);
1809 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1812 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1813 out + 19, outsize + 19, svg_p->dt);
1815 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1817 (smc->tlskb - smc->frskb) ?
1818 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1819 out + 20, outsize + 20, svg_p->dt);
1822 if (action & F_END) {
1824 /* Conversion kB -> MB */
1825 for (i = 0; i < 17; i++) {
1826 *(spmin + g_fields[i]) /= 1024;
1827 *(spmax + g_fields[i]) /= 1024;
1830 if (DISPLAY_MEMORY(a->opt_flags)) {
1831 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1832 g_type1, title1, g_title1, NULL, group1,
1833 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1836 if (DISPLAY_SWAP(a->opt_flags)) {
1837 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1838 spmin + 16, spmax + 16, out + 16, outsize + 16,
1839 svg_p, record_hdr, FALSE);
1842 /* Free remaining structures */
1843 free_graphs(out, outsize, spmin, spmax);
1848 ***************************************************************************
1849 * Display kernel tables statistics in SVG.
1852 * @a Activity structure with statistics.
1853 * @curr Index in array for current sample statistics.
1854 * @action Action expected from current function.
1855 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1856 * flag indicating that a restart record has been previously
1857 * found (.@restart) and time used for the X axis origin
1859 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1860 * @record_hdr Pointer on record header of current stats sample.
1861 ***************************************************************************
1863 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1864 unsigned long long itv, struct record_header *record_hdr)
1866 struct stats_ktables
1867 *skc = (struct stats_ktables *) a->buf[curr];
1868 int group[] = {3, 1};
1869 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1870 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1871 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1873 int g_fields[] = {1, 2, 0, 3};
1874 static double *spmin, *spmax;
1876 static int *outsize;
1878 if (action & F_BEGIN) {
1880 * Allocate arrays that will contain the graphs data
1881 * and the min/max values.
1883 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1886 if (action & F_MAIN) {
1887 /* Check for min/max values */
1888 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1889 itv, spmin, spmax, g_fields);
1891 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1892 (unsigned long long) skc->dentry_stat,
1893 out, outsize, svg_p->restart);
1895 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1896 (unsigned long long) skc->file_used,
1897 out + 1, outsize + 1, svg_p->restart);
1899 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1900 (unsigned long long) skc->inode_used,
1901 out + 2, outsize + 2, svg_p->restart);
1903 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1904 (unsigned long long) skc->pty_nr,
1905 out + 3, outsize + 3, svg_p->restart);
1908 if (action & F_END) {
1909 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1910 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1912 /* Free remaining structures */
1913 free_graphs(out, outsize, spmin, spmax);
1918 ***************************************************************************
1919 * Display queue and load statistics in SVG.
1922 * @a Activity structure with statistics.
1923 * @curr Index in array for current sample statistics.
1924 * @action Action expected from current function.
1925 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1926 * flag indicating that a restart record has been previously
1927 * found (.@restart) and time used for the X axis origin
1929 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1930 * @record_hdr Pointer on record header of current stats sample.
1931 ***************************************************************************
1933 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1934 unsigned long long itv, struct record_header *record_hdr)
1937 *sqc = (struct stats_queue *) a->buf[curr];
1938 int group[] = {2, 1, 3};
1939 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1940 char *title[] = {"Queue length", "Task list", "Load average"};
1941 char *g_title[] = {"~runq-sz", "~blocked",
1943 "ldavg-1", "ldavg-5", "ldavg-15"};
1944 int g_fields[] = {0, 1, 2, 3, 4, 5};
1945 static double *spmin, *spmax;
1947 static int *outsize;
1949 if (action & F_BEGIN) {
1951 * Allocate arrays that will contain the graphs data
1952 * and the min/max values.
1954 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1957 if (action & F_MAIN) {
1958 /* Check for min/max values */
1959 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1960 itv, spmin, spmax, g_fields);
1962 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1963 (unsigned long long) sqc->nr_running,
1964 out, outsize, svg_p->restart);
1966 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1967 (unsigned long long) sqc->procs_blocked,
1968 out + 1, outsize + 1, svg_p->restart);
1970 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1971 (unsigned long long) sqc->nr_threads,
1972 out + 2, outsize + 2, svg_p->restart);
1974 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1975 (double) sqc->load_avg_1 / 100,
1976 out + 3, outsize + 3, svg_p->restart);
1978 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1979 (double) sqc->load_avg_5 / 100,
1980 out + 4, outsize + 4, svg_p->restart);
1982 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1983 (double) sqc->load_avg_15 / 100,
1984 out + 5, outsize + 5, svg_p->restart);
1987 if (action & F_END) {
1988 /* Fix min/max values for load average */
1989 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1990 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1991 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1993 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1994 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1996 /* Free remaining structures */
1997 free_graphs(out, outsize, spmin, spmax);
2002 ***************************************************************************
2003 * Display disk statistics in SVG.
2006 * @a Activity structure with statistics.
2007 * @curr Index in array for current sample statistics.
2008 * @action Action expected from current function.
2009 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2010 * flag indicating that a restart record has been previously
2011 * found (.@restart) and time used for the X axis origin
2013 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2014 * @record_hdr Pointer on record header of current stats sample.
2015 ***************************************************************************
2017 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2018 unsigned long long itv, struct record_header *record_hdr)
2020 struct stats_disk *sdc, *sdp, sdpzero;
2021 struct ext_disk_stats xds;
2022 int group[] = {1, 2, 2, 2, 1};
2023 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2024 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2025 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
2026 "Disk statistics (3)", "Disk statistics (4)",
2027 "Disk statistics (5)"};
2028 char *g_title[] = {"tps",
2030 "areq-sz", "aqu-sz",
2033 int g_fields[] = {0, 1, 2};
2034 unsigned int local_types_nr[] = {1, 0, 0};
2035 static double *spmin, *spmax;
2037 static int *outsize;
2038 char *item_name, *persist_dev_name;
2039 double rkB, wkB, aqusz;
2040 int i, j, k, pos, restart, *unregistered;
2042 if (action & F_BEGIN) {
2044 * Allocate arrays (#0..7) that will contain the graphs data
2045 * and the min/max values.
2046 * Also allocate one additional array (#8) for each disk device:
2047 * spmax + 8 will contain the device major number,
2048 * spmin + 8 will contain the device minor number,
2049 * outsize + 8 will contain a positive value (TRUE) if the device
2050 * has either still not been registered, or has been unregistered.
2052 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2055 if (action & F_MAIN) {
2056 memset(&sdpzero, 0, STATS_DISK_SIZE);
2057 restart = svg_p->restart;
2059 * Mark previously registered devices as now
2060 * possibly unregistered for all graphs.
2062 for (k = 0; k < svg_p->nr_max; k++) {
2063 unregistered = outsize + k * 9 + 8;
2064 if (*unregistered == FALSE) {
2065 *unregistered = MAYBE;
2069 /* For each device structure */
2070 for (i = 0; i < a->nr[curr]; i++) {
2071 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2073 /* Look for corresponding graph */
2074 for (k = 0; k < svg_p->nr_max; k++) {
2075 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2076 (sdc->minor == *(spmin + k * 9 + 8)))
2080 if (k == svg_p->nr_max) {
2081 /* Graph not found: Look for first free entry */
2082 for (k = 0; k < svg_p->nr_max; k++) {
2083 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2086 if (k == svg_p->nr_max) {
2087 /* No free graph entry: Extend all buffers */
2088 reallocate_all_graph_lines(svg_p->nr_max,
2089 &out, &outsize, &spmin, &spmax);
2094 unregistered = outsize + pos + 8;
2096 j = check_disk_reg(a, curr, !curr, i);
2098 /* This is a newly registered interface. Previous stats are zero */
2102 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2106 * If current device was marked as previously unregistered,
2107 * then set restart variable to TRUE so that the graph will be
2108 * discontinuous, and mark it as now registered.
2110 if (*unregistered == TRUE) {
2113 *unregistered = FALSE;
2115 if (*(spmax + pos + 8) == -DBL_MAX) {
2116 /* Save device major and minor numbers (if not already done) */
2117 *(spmax + pos + 8) = sdc->major;
2118 *(spmin + pos + 8) = sdc->minor;
2121 /* Check for min/max values */
2122 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2123 itv, spmin + pos, spmax + pos, g_fields);
2125 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2126 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2127 if (rkB < *(spmin + pos + 1)) {
2128 *(spmin + pos + 1) = rkB;
2130 if (rkB > *(spmax + pos + 1)) {
2131 *(spmax + pos + 1) = rkB;
2133 if (wkB < *(spmin + pos + 2)) {
2134 *(spmin + pos + 2) = wkB;
2136 if (wkB > *(spmax + pos + 2)) {
2137 *(spmax + pos + 2) = wkB;
2140 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2141 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2142 *(spmin + pos + 3) = xds.arqsz / 2;
2144 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2145 *(spmax + pos + 3) = xds.arqsz / 2;
2147 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2148 if (aqusz < *(spmin + pos + 4)) {
2149 *(spmin + pos + 4) = aqusz;
2151 if (aqusz > *(spmax + pos + 4)) {
2152 *(spmax + pos + 4) = aqusz;
2154 if (xds.await < *(spmin + pos + 5)) {
2155 *(spmin + pos + 5) = xds.await;
2157 if (xds.await > *(spmax + pos + 5)) {
2158 *(spmax + pos + 5) = xds.await;
2160 if (xds.svctm < *(spmin + pos + 6)) {
2161 *(spmin + pos + 6) = xds.svctm;
2163 if (xds.svctm > *(spmax + pos + 6)) {
2164 *(spmax + pos + 6) = xds.svctm;
2166 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2167 *(spmin + pos + 7) = xds.util / 10.0;
2169 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2170 *(spmax + pos + 7) = xds.util / 10.0;
2174 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2175 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2176 out + pos, outsize + pos, restart);
2178 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2179 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2180 out + pos + 1, outsize + pos + 1, restart);
2182 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2183 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2184 out + pos + 2, outsize + pos + 2, restart);
2186 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2188 out + pos + 3, outsize + pos + 3, restart);
2190 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2192 out + pos + 4, outsize + pos + 4, restart);
2194 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2196 out + pos + 5, outsize + pos + 5, restart);
2198 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2200 out + pos + 6, outsize + pos + 6, restart);
2202 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2203 0.0, xds.util / 10.0,
2204 out + pos + 7, outsize + pos + 7, svg_p->dt);
2207 /* Mark devices not seen here as now unregistered */
2208 for (k = 0; k < svg_p->nr_max; k++) {
2209 unregistered = outsize + k * 9 + 8;
2210 if (*unregistered != FALSE) {
2211 *unregistered = TRUE;
2216 if (action & F_END) {
2217 for (i = 0; i < svg_p->nr_max; i++) {
2218 /* Check if there is something to display */
2224 persist_dev_name = NULL;
2226 if (DISPLAY_PERSIST_NAME_S(flags)) {
2227 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2231 if (persist_dev_name) {
2232 item_name = persist_dev_name;
2235 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2236 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2240 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2241 USE_PRETTY_OPTION(flags));
2245 draw_activity_graphs(a->g_nr, g_type,
2246 title, g_title, item_name, group,
2247 spmin + pos, spmax + pos, out + pos, outsize + pos,
2248 svg_p, record_hdr, FALSE);
2251 /* Free remaining structures */
2252 free_graphs(out, outsize, spmin, spmax);
2257 ***************************************************************************
2258 * Display network interfaces statistics in SVG.
2261 * @a Activity structure with statistics.
2262 * @curr Index in array for current sample statistics.
2263 * @action Action expected from current function.
2264 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2265 * flag indicating that a restart record has been previously
2266 * found (.@restart) and time used for the X axis origin
2268 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2269 * @record_hdr Pointer on record header of current stats sample.
2270 ***************************************************************************
2272 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2273 unsigned long long itv, struct record_header *record_hdr)
2275 struct stats_net_dev *sndc, *sndp, sndzero;
2276 int group[] = {2, 2, 3, 1};
2277 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2279 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2280 "Network statistics (3)", "Network statistics (4)"};
2281 char *g_title[] = {"rxpck/s", "txpck/s",
2283 "rxcmp/s", "txcmp/s", "rxmcst/s",
2285 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2286 unsigned int local_types_nr[] = {7, 0, 0};
2287 static double *spmin, *spmax;
2289 static int *outsize;
2291 double rxkb, txkb, ifutil;
2292 int i, j, k, pos, restart, *unregistered;
2294 if (action & F_BEGIN) {
2296 * Allocate arrays (#0..7) that will contain the graphs data
2297 * and the min/max values.
2298 * Also allocate one additional array (#8) for each interface:
2299 * out + 8 will contain the interface name,
2300 * outsize + 8 will contain a positive value (TRUE) if the interface
2301 * has either still not been registered, or has been unregistered.
2303 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2306 if (action & F_MAIN) {
2307 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2308 restart = svg_p->restart;
2310 * Mark previously registered interfaces as now
2311 * possibly unregistered for all graphs.
2313 for (k = 0; k < svg_p->nr_max; k++) {
2314 unregistered = outsize + k * 9 + 8;
2315 if (*unregistered == FALSE) {
2316 *unregistered = MAYBE;
2320 /* For each network interfaces structure */
2321 for (i = 0; i < a->nr[curr]; i++) {
2322 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2324 /* Look for corresponding graph */
2325 for (k = 0; k < svg_p->nr_max; k++) {
2326 item_name = *(out + k * 9 + 8);
2327 if (!strcmp(sndc->interface, item_name))
2331 if (k == svg_p->nr_max) {
2332 /* Graph not found: Look for first free entry */
2333 for (k = 0; k < svg_p->nr_max; k++) {
2334 item_name = *(out + k * 9 + 8);
2335 if (!strcmp(item_name, ""))
2338 if (k == svg_p->nr_max) {
2339 /* No free graph entry: Extend all buffers */
2340 reallocate_all_graph_lines(svg_p->nr_max,
2341 &out, &outsize, &spmin, &spmax);
2347 unregistered = outsize + pos + 8;
2349 j = check_net_dev_reg(a, curr, !curr, i);
2351 /* This is a newly registered interface. Previous stats are zero */
2355 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2359 * If current interface was marked as previously unregistered,
2360 * then set restart variable to TRUE so that the graph will be
2361 * discontinuous, and mark it as now registered.
2363 if (*unregistered == TRUE) {
2366 *unregistered = FALSE;
2368 if (!item_name[0]) {
2369 /* Save network interface name (if not already done) */
2370 strncpy(item_name, sndc->interface, CHUNKSIZE);
2371 item_name[CHUNKSIZE - 1] = '\0';
2374 /* Check for min/max values */
2375 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2376 itv, spmin + pos, spmax + pos, g_fields);
2378 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2379 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2380 ifutil = compute_ifutil(sndc, rxkb, txkb);
2381 if (ifutil < *(spmin + pos + 7)) {
2382 *(spmin + pos + 7) = ifutil;
2384 if (ifutil > *(spmax + pos + 7)) {
2385 *(spmax + pos + 7) = ifutil;
2389 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2390 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2391 out + pos, outsize + pos, restart);
2393 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2394 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2395 out + pos + 1, outsize + pos + 1, restart);
2397 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2399 out + pos + 2, outsize + pos + 2, restart);
2401 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2403 out + pos + 3, outsize + pos + 3, restart);
2405 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2406 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2407 out + pos + 4, outsize + pos + 4, restart);
2409 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2410 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2411 out + pos + 5, outsize + pos + 5, restart);
2413 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2414 S_VALUE(sndp->multicast, sndc->multicast, itv),
2415 out + pos + 6, outsize + pos + 6, restart);
2417 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2419 out + pos + 7, outsize + pos + 7, svg_p->dt);
2422 /* Mark interfaces not seen here as now unregistered */
2423 for (k = 0; k < svg_p->nr_max; k++) {
2424 unregistered = outsize + k * 9 + 8;
2425 if (*unregistered != FALSE) {
2426 *unregistered = TRUE;
2431 if (action & F_END) {
2432 for (i = 0; i < svg_p->nr_max; i++) {
2434 * Check if there is something to display.
2435 * Don't test sndc->interface because maybe the network
2436 * interface has been registered later.
2442 /* Recalculate min and max values in kB, not in B */
2443 *(spmin + pos + 2) /= 1024;
2444 *(spmax + pos + 2) /= 1024;
2445 *(spmin + pos + 3) /= 1024;
2446 *(spmax + pos + 3) /= 1024;
2448 item_name = *(out + pos + 8);
2449 draw_activity_graphs(a->g_nr, g_type,
2450 title, g_title, item_name, group,
2451 spmin + pos, spmax + pos, out + pos, outsize + pos,
2452 svg_p, record_hdr, FALSE);
2455 /* Free remaining structures */
2456 free_graphs(out, outsize, spmin, spmax);
2461 ***************************************************************************
2462 * Display network interface errors statistics in SVG.
2465 * @a Activity structure with statistics.
2466 * @curr Index in array for current sample statistics.
2467 * @action Action expected from current function.
2468 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2469 * flag indicating that a restart record has been previously
2470 * found (.@restart) and time used for the X axis origin
2472 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2473 * @record_hdr Pointer on record header of current stats sample.
2474 ***************************************************************************
2476 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2477 unsigned long long itv, struct record_header *record_hdr)
2479 struct stats_net_edev *snedc, *snedp, snedzero;
2480 int group[] = {2, 2, 2, 3};
2481 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2483 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2484 "Network errors statistics (3)", "Network errors statistics (4)"};
2485 char *g_title[] = {"rxerr/s", "txerr/s",
2486 "rxdrop/s", "txdrop/s",
2487 "rxfifo/s", "txfifo/s",
2488 "coll/s", "txcarr/s", "rxfram/s"};
2489 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2490 static double *spmin, *spmax;
2492 static int *outsize;
2494 int i, j, k, pos, restart, *unregistered;
2496 if (action & F_BEGIN) {
2498 * Allocate arrays (#0..8) that will contain the graphs data
2499 * and the min/max values.
2500 * Also allocate one additional array (#9) for each interface:
2501 * out + 9 will contain the interface name,
2502 * outsize + 9 will contain a positive value (TRUE) if the interface
2503 * has either still not been registered, or has been unregistered.
2505 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
2508 if (action & F_MAIN) {
2509 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2510 restart = svg_p->restart;
2512 * Mark previously registered interfaces as now
2513 * possibly unregistered for all graphs.
2515 for (k = 0; k < svg_p->nr_max; k++) {
2516 unregistered = outsize + k * 10 + 9;
2517 if (*unregistered == FALSE) {
2518 *unregistered = MAYBE;
2522 /* For each network interfaces structure */
2523 for (i = 0; i < a->nr[curr]; i++) {
2524 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2525 if (!strcmp(snedc->interface, ""))
2526 /* Empty structure: This is the end of the list */
2529 /* Look for corresponding graph */
2530 for (k = 0; k < svg_p->nr_max; k++) {
2531 item_name = *(out + k * 10 + 9);
2532 if (!strcmp(snedc->interface, item_name))
2536 if (k == svg_p->nr_max) {
2537 /* Graph not found: Look for first free entry */
2538 for (k = 0; k < svg_p->nr_max; k++) {
2539 item_name = *(out + k * 10 + 9);
2540 if (!strcmp(item_name, ""))
2543 if (k == svg_p->nr_max) {
2544 /* No free graph entry: Extend all buffers */
2545 reallocate_all_graph_lines(svg_p->nr_max,
2546 &out, &outsize, &spmin, &spmax);
2552 unregistered = outsize + pos + 9;
2554 j = check_net_edev_reg(a, curr, !curr, i);
2556 /* This is a newly registered interface. Previous stats are zero */
2560 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2564 * If current interface was marked as previously unregistered,
2565 * then set restart variable to TRUE so that the graph will be
2566 * discontinuous, and mark it as now registered.
2568 if (*unregistered == TRUE) {
2571 *unregistered = FALSE;
2573 if (!item_name[0]) {
2574 /* Save network interface name (if not already done) */
2575 strncpy(item_name, snedc->interface, CHUNKSIZE);
2576 item_name[CHUNKSIZE - 1] = '\0';
2579 /* Check for min/max values */
2580 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2581 itv, spmin + pos, spmax + pos, g_fields);
2584 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2585 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2586 out + pos, outsize + pos, restart);
2588 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2589 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2590 out + pos + 1, outsize + pos + 1, restart);
2592 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2593 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2594 out + pos + 2, outsize + pos + 2, restart);
2596 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2597 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2598 out + pos + 3, outsize + pos + 3, restart);
2600 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2601 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2602 out + pos + 4, outsize + pos + 4, restart);
2604 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2605 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2606 out + pos + 5, outsize + pos + 5, restart);
2608 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2609 S_VALUE(snedp->collisions, snedc->collisions, itv),
2610 out + pos + 6, outsize + pos + 6, restart);
2612 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2613 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2614 out + pos + 7, outsize + pos + 7, restart);
2616 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2617 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2618 out + pos + 8, outsize + pos + 8, restart);
2621 /* Mark interfaces not seen here as now unregistered */
2622 for (k = 0; k < svg_p->nr_max; k++) {
2623 unregistered = outsize + k * 10 + 9;
2624 if (*unregistered != FALSE) {
2625 *unregistered = TRUE;
2630 if (action & F_END) {
2631 for (i = 0; i < svg_p->nr_max; i++) {
2633 * Check if there is something to display.
2634 * Don't test snedc->interface because maybe the network
2635 * interface has been registered later.
2641 item_name = *(out + pos + 9);
2642 draw_activity_graphs(a->g_nr, g_type,
2643 title, g_title, item_name, group,
2644 spmin + pos, spmax + pos, out + pos, outsize + pos,
2645 svg_p, record_hdr, FALSE);
2648 /* Free remaining structures */
2649 free_graphs(out, outsize, spmin, spmax);
2654 ***************************************************************************
2655 * Display NFS client statistics in SVG.
2658 * @a Activity structure with statistics.
2659 * @curr Index in array for current sample statistics.
2660 * @action Action expected from current function.
2661 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2662 * flag indicating that a restart record has been previously
2663 * found (.@restart) and time used for the X axis origin
2665 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2666 * @record_hdr Pointer on record header of current stats sample.
2667 ***************************************************************************
2669 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2670 unsigned long long itv, struct record_header *record_hdr)
2672 struct stats_net_nfs
2673 *snnc = (struct stats_net_nfs *) a->buf[curr],
2674 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2675 int group[] = {2, 2, 2};
2676 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2677 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2678 "NFS client statistics (3)"};
2679 char *g_title[] = {"call/s", "retrans/s",
2680 "read/s", "write/s",
2681 "access/s", "getatt/s"};
2682 int g_fields[] = {0, 1, 2, 3, 4, 5};
2683 static double *spmin, *spmax;
2685 static int *outsize;
2687 if (action & F_BEGIN) {
2689 * Allocate arrays that will contain the graphs data
2690 * and the min/max values.
2692 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2695 if (action & F_MAIN) {
2696 /* Check for min/max values */
2697 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2698 itv, spmin, spmax, g_fields);
2701 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2702 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2703 out, outsize, svg_p->restart);
2705 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2706 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2707 out + 1, outsize + 1, svg_p->restart);
2709 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2710 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2711 out + 2, outsize + 2, svg_p->restart);
2713 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2714 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2715 out + 3, outsize + 3, svg_p->restart);
2717 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2718 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2719 out + 4, outsize + 4, svg_p->restart);
2721 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2722 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2723 out + 5, outsize + 5, svg_p->restart);
2726 if (action & F_END) {
2727 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2728 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2730 /* Free remaining structures */
2731 free_graphs(out, outsize, spmin, spmax);
2736 ***************************************************************************
2737 * Display NFS server statistics in SVG.
2740 * @a Activity structure with statistics.
2741 * @curr Index in array for current sample statistics.
2742 * @action Action expected from current function.
2743 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2744 * flag indicating that a restart record has been previously
2745 * found (.@restart) and time used for the X axis origin
2747 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2748 * @record_hdr Pointer on record header of current stats sample.
2749 ***************************************************************************
2751 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2752 unsigned long long itv, struct record_header *record_hdr)
2754 struct stats_net_nfsd
2755 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2756 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2757 int group[] = {2, 3, 2, 2, 2};
2758 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2759 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2760 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2761 "NFS server statistics (3)", "NFS server statistics (4)",
2762 "NFS server statistics (5)"};
2763 char *g_title[] = {"scall/s", "badcall/s",
2764 "packet/s", "udp/s", "tcp/s",
2766 "sread/s", "swrite/s",
2767 "saccess/s", "sgetatt/s"};
2768 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2769 static double *spmin, *spmax;
2771 static int *outsize;
2773 if (action & F_BEGIN) {
2775 * Allocate arrays that will contain the graphs data
2776 * and the min/max values.
2778 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2781 if (action & F_MAIN) {
2782 /* Check for min/max values */
2783 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2784 itv, spmin, spmax, g_fields);
2787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2788 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2789 out, outsize, svg_p->restart);
2791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2792 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2793 out + 1, outsize + 1, svg_p->restart);
2795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2796 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2797 out + 2, outsize + 2, svg_p->restart);
2799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2800 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2801 out + 3, outsize + 3, svg_p->restart);
2803 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2804 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2805 out + 4, outsize + 4, svg_p->restart);
2807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2808 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2809 out + 5, outsize + 5, svg_p->restart);
2811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2812 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2813 out + 6, outsize + 6, svg_p->restart);
2815 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2816 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2817 out + 7, outsize + 7, svg_p->restart);
2819 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2820 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2821 out + 8, outsize + 8, svg_p->restart);
2823 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2824 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2825 out + 9, outsize + 9, svg_p->restart);
2827 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2828 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2829 out + 10, outsize + 10, svg_p->restart);
2832 if (action & F_END) {
2833 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2834 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2836 /* Free remaining structures */
2837 free_graphs(out, outsize, spmin, spmax);
2842 ***************************************************************************
2843 * Display network socket statistics in SVG.
2846 * @a Activity structure with statistics.
2847 * @curr Index in array for current sample statistics.
2848 * @action Action expected from current function.
2849 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2850 * flag indicating that a restart record has been previously
2851 * found (.@restart) and time used for the X axis origin
2853 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2854 * @record_hdr Pointer on record header of current stats sample.
2855 ***************************************************************************
2857 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2858 unsigned long long itv, struct record_header *record_hdr)
2860 struct stats_net_sock
2861 *snsc = (struct stats_net_sock *) a->buf[curr];
2862 int group[] = {1, 5};
2863 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2864 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2865 char *g_title[] = {"~totsck",
2866 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2867 int g_fields[] = {0, 1, 5, 2, 3, 4};
2868 static double *spmin, *spmax;
2870 static int *outsize;
2872 if (action & F_BEGIN) {
2874 * Allocate arrays that will contain the graphs data
2875 * and the min/max values.
2877 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2880 if (action & F_MAIN) {
2881 /* Check for min/max values */
2882 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2883 itv, spmin, spmax, g_fields);
2885 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2886 (unsigned long long) snsc->sock_inuse,
2887 out, outsize, svg_p->restart);
2889 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2890 (unsigned long long) snsc->tcp_inuse,
2891 out + 1, outsize + 1, svg_p->restart);
2893 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2894 (unsigned long long) snsc->udp_inuse,
2895 out + 2, outsize + 2, svg_p->restart);
2897 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2898 (unsigned long long) snsc->raw_inuse,
2899 out + 3, outsize + 3, svg_p->restart);
2901 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2902 (unsigned long long) snsc->frag_inuse,
2903 out + 4, outsize + 4, svg_p->restart);
2905 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2906 (unsigned long long) snsc->tcp_tw,
2907 out + 5, outsize + 5, svg_p->restart);
2910 if (action & F_END) {
2911 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2912 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2914 /* Free remaining structures */
2915 free_graphs(out, outsize, spmin, spmax);
2920 ***************************************************************************
2921 * Display IPv4 network statistics in SVG.
2924 * @a Activity structure with statistics.
2925 * @curr Index in array for current sample statistics.
2926 * @action Action expected from current function.
2927 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2928 * flag indicating that a restart record has been previously
2929 * found (.@restart) and time used for the X axis origin
2931 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2932 * @record_hdr Pointer on record header of current stats sample.
2933 ***************************************************************************
2935 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2936 unsigned long long itv, struct record_header *record_hdr)
2939 *snic = (struct stats_net_ip *) a->buf[curr],
2940 *snip = (struct stats_net_ip *) a->buf[!curr];
2941 int group[] = {4, 2, 2};
2942 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2943 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2944 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2945 "asmrq/s", "asmok/s",
2946 "fragok/s", "fragcrt/s"};
2947 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2948 static double *spmin, *spmax;
2950 static int *outsize;
2952 if (action & F_BEGIN) {
2954 * Allocate arrays that will contain the graphs data
2955 * and the min/max values.
2957 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2960 if (action & F_MAIN) {
2961 /* Check for min/max values */
2962 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2963 itv, spmin, spmax, g_fields);
2966 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2967 S_VALUE(snip->InReceives, snic->InReceives, itv),
2968 out, outsize, svg_p->restart);
2970 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2971 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2972 out + 1, outsize + 1, svg_p->restart);
2974 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2975 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2976 out + 2, outsize + 2, svg_p->restart);
2978 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2979 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2980 out + 3, outsize + 3, svg_p->restart);
2982 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2983 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2984 out + 4, outsize + 4, svg_p->restart);
2986 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2987 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2988 out + 5, outsize + 5, svg_p->restart);
2990 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2991 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2992 out + 6, outsize + 6, svg_p->restart);
2994 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2995 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
2996 out + 7, outsize + 7, svg_p->restart);
2999 if (action & F_END) {
3000 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3001 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3003 /* Free remaining structures */
3004 free_graphs(out, outsize, spmin, spmax);
3009 ***************************************************************************
3010 * Display IPv4 network errors statistics in SVG.
3013 * @a Activity structure with statistics.
3014 * @curr Index in array for current sample statistics.
3015 * @action Action expected from current function.
3016 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3017 * flag indicating that a restart record has been previously
3018 * found (.@restart) and time used for the X axis origin
3020 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3021 * @record_hdr Pointer on record header of current stats sample.
3022 ***************************************************************************
3024 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3025 unsigned long long itv, struct record_header *record_hdr)
3027 struct stats_net_eip
3028 *sneic = (struct stats_net_eip *) a->buf[curr],
3029 *sneip = (struct stats_net_eip *) a->buf[!curr];
3030 int group[] = {3, 2, 3};
3031 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3032 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
3033 "IPv4 network errors statistics (3)"};
3034 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3035 "idisc/s", "odisc/s",
3036 "onort/s", "asmf/s", "fragf/s"};
3037 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3038 static double *spmin, *spmax;
3040 static int *outsize;
3042 if (action & F_BEGIN) {
3044 * Allocate arrays that will contain the graphs data
3045 * and the min/max values.
3047 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3050 if (action & F_MAIN) {
3051 /* Check for min/max values */
3052 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3053 itv, spmin, spmax, g_fields);
3056 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3057 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3058 out, outsize, svg_p->restart);
3060 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3061 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3062 out + 1, outsize + 1, svg_p->restart);
3064 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3065 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3066 out + 2, outsize + 2, svg_p->restart);
3068 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3069 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3070 out + 3, outsize + 3, svg_p->restart);
3072 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3073 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3074 out + 4, outsize + 4, svg_p->restart);
3076 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3077 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3078 out + 5, outsize + 5, svg_p->restart);
3080 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3081 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3082 out + 6, outsize + 6, svg_p->restart);
3084 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3085 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3086 out + 7, outsize + 7, svg_p->restart);
3089 if (action & F_END) {
3090 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3091 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3093 /* Free remaining structures */
3094 free_graphs(out, outsize, spmin, spmax);
3099 ***************************************************************************
3100 * Display ICMPv4 network statistics in SVG.
3103 * @a Activity structure with statistics.
3104 * @curr Index in array for current sample statistics.
3105 * @action Action expected from current function.
3106 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3107 * flag indicating that a restart record has been previously
3108 * found (.@restart) and time used for the X axis origin
3110 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3111 * @record_hdr Pointer on record header of current stats sample.
3112 ***************************************************************************
3114 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3115 unsigned long long itv, struct record_header *record_hdr)
3117 struct stats_net_icmp
3118 *snic = (struct stats_net_icmp *) a->buf[curr],
3119 *snip = (struct stats_net_icmp *) a->buf[!curr];
3120 int group[] = {2, 4, 4, 4};
3121 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3123 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3124 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3125 char *g_title[] = {"imsg/s", "omsg/s",
3126 "iech/s", "iechr/s", "oech/s", "oechr/s",
3127 "itm/s", "itmr/s", "otm/s", "otmr/s",
3128 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3129 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3130 static double *spmin, *spmax;
3132 static int *outsize;
3134 if (action & F_BEGIN) {
3136 * Allocate arrays that will contain the graphs data
3137 * and the min/max values.
3139 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3142 if (action & F_MAIN) {
3143 /* Check for min/max values */
3144 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3145 itv, spmin, spmax, g_fields);
3148 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3149 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3150 out, outsize, svg_p->restart);
3152 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3153 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3154 out + 1, outsize + 1, svg_p->restart);
3156 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3157 S_VALUE(snip->InEchos, snic->InEchos, itv),
3158 out + 2, outsize + 2, svg_p->restart);
3160 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3161 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3162 out + 3, outsize + 3, svg_p->restart);
3164 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3165 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3166 out + 4, outsize + 4, svg_p->restart);
3168 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3169 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3170 out + 5, outsize + 5, svg_p->restart);
3172 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3173 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3174 out + 6, outsize + 6, svg_p->restart);
3176 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3177 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3178 out + 7, outsize + 7, svg_p->restart);
3180 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3181 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3182 out + 8, outsize + 8, svg_p->restart);
3184 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3185 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3186 out + 9, outsize + 9, svg_p->restart);
3188 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3189 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3190 out + 10, outsize + 10, svg_p->restart);
3192 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3193 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3194 out + 11, outsize + 11, svg_p->restart);
3196 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3197 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3198 out + 12, outsize + 12, svg_p->restart);
3200 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3201 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3202 out + 13, outsize + 13, svg_p->restart);
3205 if (action & F_END) {
3206 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3207 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3209 /* Free remaining structures */
3210 free_graphs(out, outsize, spmin, spmax);
3215 ***************************************************************************
3216 * Display ICMPv4 network errors statistics in SVG.
3219 * @a Activity structure with statistics.
3220 * @curr Index in array for current sample statistics.
3221 * @action Action expected from current function.
3222 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3223 * flag indicating that a restart record has been previously
3224 * found (.@restart) and time used for the X axis origin
3226 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3227 * @record_hdr Pointer on record header of current stats sample.
3228 ***************************************************************************
3230 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3231 unsigned long long itv, struct record_header *record_hdr)
3233 struct stats_net_eicmp
3234 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3235 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3236 int group[] = {2, 2, 2, 2, 2, 2};
3237 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3238 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3239 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3240 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3241 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3242 char *g_title[] = {"ierr/s", "oerr/s",
3243 "idstunr/s", "odstunr/s",
3244 "itmex/s", "otmex/s",
3245 "iparmpb/s", "oparmpb/s",
3246 "isrcq/s", "osrcq/s",
3247 "iredir/s", "oredir/s"};
3248 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3249 static double *spmin, *spmax;
3251 static int *outsize;
3253 if (action & F_BEGIN) {
3255 * Allocate arrays that will contain the graphs data
3256 * and the min/max values.
3258 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3261 if (action & F_MAIN) {
3262 /* Check for min/max values */
3263 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3264 itv, spmin, spmax, g_fields);
3267 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3268 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3269 out, outsize, svg_p->restart);
3271 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3272 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3273 out + 1, outsize + 1, svg_p->restart);
3275 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3276 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3277 out + 2, outsize + 2, svg_p->restart);
3279 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3280 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3281 out + 3, outsize + 3, svg_p->restart);
3283 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3284 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3285 out + 4, outsize + 4, svg_p->restart);
3287 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3288 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3289 out + 5, outsize + 5, svg_p->restart);
3291 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3292 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3293 out + 6, outsize + 6, svg_p->restart);
3295 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3296 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3297 out + 7, outsize + 7, svg_p->restart);
3299 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3300 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3301 out + 8, outsize + 8, svg_p->restart);
3303 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3304 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3305 out + 9, outsize + 9, svg_p->restart);
3307 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3308 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3309 out + 10, outsize + 10, svg_p->restart);
3311 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3312 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3313 out + 11, outsize + 11, svg_p->restart);
3316 if (action & F_END) {
3317 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3318 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3320 /* Free remaining structures */
3321 free_graphs(out, outsize, spmin, spmax);
3326 ***************************************************************************
3327 * Display TCPv4 network statistics in SVG.
3330 * @a Activity structure with statistics.
3331 * @curr Index in array for current sample statistics.
3332 * @action Action expected from current function.
3333 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3334 * flag indicating that a restart record has been previously
3335 * found (.@restart) and time used for the X axis origin
3337 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3338 * @record_hdr Pointer on record header of current stats sample.
3339 ***************************************************************************
3341 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3342 unsigned long long itv, struct record_header *record_hdr)
3344 struct stats_net_tcp
3345 *sntc = (struct stats_net_tcp *) a->buf[curr],
3346 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3347 int group[] = {2, 2};
3348 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3349 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3350 char *g_title[] = {"active/s", "passive/s",
3351 "iseg/s", "oseg/s"};
3352 int g_fields[] = {0, 1, 2, 3};
3353 static double *spmin, *spmax;
3355 static int *outsize;
3357 if (action & F_BEGIN) {
3359 * Allocate arrays that will contain the graphs data
3360 * and the min/max values.
3362 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3365 if (action & F_MAIN) {
3366 /* Check for min/max values */
3367 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3368 itv, spmin, spmax, g_fields);
3371 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3372 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3373 out, outsize, svg_p->restart);
3375 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3376 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3377 out + 1, outsize + 1, svg_p->restart);
3379 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3380 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3381 out + 2, outsize + 2, svg_p->restart);
3383 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3384 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3385 out + 3, outsize + 3, svg_p->restart);
3388 if (action & F_END) {
3389 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3390 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3392 /* Free remaining structures */
3393 free_graphs(out, outsize, spmin, spmax);
3398 ***************************************************************************
3399 * Display TCPv4 network errors statistics in SVG.
3402 * @a Activity structure with statistics.
3403 * @curr Index in array for current sample statistics.
3404 * @action Action expected from current function.
3405 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3406 * flag indicating that a restart record has been previously
3407 * found (.@restart) and time used for the X axis origin
3409 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3410 * @record_hdr Pointer on record header of current stats sample.
3411 ***************************************************************************
3413 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3414 unsigned long long itv, struct record_header *record_hdr)
3416 struct stats_net_etcp
3417 *snetc = (struct stats_net_etcp *) a->buf[curr],
3418 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3419 int group[] = {2, 3};
3420 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3421 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3422 char *g_title[] = {"atmptf/s", "estres/s",
3423 "retrans/s", "isegerr/s", "orsts/s"};
3424 int g_fields[] = {0, 1, 2, 3, 4};
3425 static double *spmin, *spmax;
3427 static int *outsize;
3429 if (action & F_BEGIN) {
3431 * Allocate arrays that will contain the graphs data
3432 * and the min/max values.
3434 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3437 if (action & F_MAIN) {
3438 /* Check for min/max values */
3439 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3440 itv, spmin, spmax, g_fields);
3443 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3444 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3445 out, outsize, svg_p->restart);
3447 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3448 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3449 out + 1, outsize + 1, svg_p->restart);
3451 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3452 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3453 out + 2, outsize + 2, svg_p->restart);
3455 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3456 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3457 out + 3, outsize + 3, svg_p->restart);
3459 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3460 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3461 out + 4, outsize + 4, svg_p->restart);
3464 if (action & F_END) {
3465 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3466 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3468 /* Free remaining structures */
3469 free_graphs(out, outsize, spmin, spmax);
3474 ***************************************************************************
3475 * Display UDPv4 network statistics in SVG.
3478 * @a Activity structure with statistics.
3479 * @curr Index in array for current sample statistics.
3480 * @action Action expected from current function.
3481 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3482 * flag indicating that a restart record has been previously
3483 * found (.@restart) and time used for the X axis origin
3485 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3486 * @record_hdr Pointer on record header of current stats sample.
3487 ***************************************************************************
3489 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3490 unsigned long long itv, struct record_header *record_hdr)
3492 struct stats_net_udp
3493 *snuc = (struct stats_net_udp *) a->buf[curr],
3494 *snup = (struct stats_net_udp *) a->buf[!curr];
3495 int group[] = {2, 2};
3496 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3497 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3498 char *g_title[] = {"idgm/s", "odgm/s",
3499 "noport/s", "idgmerr/s"};
3500 int g_fields[] = {0, 1, 2, 3};
3501 static double *spmin, *spmax;
3503 static int *outsize;
3505 if (action & F_BEGIN) {
3507 * Allocate arrays that will contain the graphs data
3508 * and the min/max values.
3510 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3513 if (action & F_MAIN) {
3514 /* Check for min/max values */
3515 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3516 itv, spmin, spmax, g_fields);
3519 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3520 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3521 out, outsize, svg_p->restart);
3523 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3524 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3525 out + 1, outsize + 1, svg_p->restart);
3527 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3528 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3529 out + 2, outsize + 2, svg_p->restart);
3531 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3532 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3533 out + 3, outsize + 3, svg_p->restart);
3536 if (action & F_END) {
3537 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3538 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3540 /* Free remaining structures */
3541 free_graphs(out, outsize, spmin, spmax);
3546 ***************************************************************************
3547 * Display IPV6 network socket statistics in SVG.
3550 * @a Activity structure with statistics.
3551 * @curr Index in array for current sample statistics.
3552 * @action Action expected from current function.
3553 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3554 * flag indicating that a restart record has been previously
3555 * found (.@restart) and time used for the X axis origin
3557 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3558 * @record_hdr Pointer on record header of current stats sample.
3559 ***************************************************************************
3561 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3562 unsigned long long itv, struct record_header *record_hdr)
3564 struct stats_net_sock6
3565 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3567 int g_type[] = {SVG_LINE_GRAPH};
3568 char *title[] = {"IPv6 network sockets"};
3569 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3570 int g_fields[] = {0, 1, 2, 3};
3571 static double *spmin, *spmax;
3573 static int *outsize;
3575 if (action & F_BEGIN) {
3577 * Allocate arrays that will contain the graphs data
3578 * and the min/max values.
3580 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3583 if (action & F_MAIN) {
3584 /* Check for min/max values */
3585 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3586 itv, spmin, spmax, g_fields);
3588 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3589 (unsigned long long) snsc->tcp6_inuse,
3590 out, outsize, svg_p->restart);
3592 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3593 (unsigned long long) snsc->udp6_inuse,
3594 out + 1, outsize + 1, svg_p->restart);
3596 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3597 (unsigned long long) snsc->raw6_inuse,
3598 out + 2, outsize + 2, svg_p->restart);
3600 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3601 (unsigned long long) snsc->frag6_inuse,
3602 out + 3, outsize + 3, svg_p->restart);
3605 if (action & F_END) {
3606 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3607 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3609 /* Free remaining structures */
3610 free_graphs(out, outsize, spmin, spmax);
3615 ***************************************************************************
3616 * Display IPv6 network statistics in SVG.
3619 * @a Activity structure with statistics.
3620 * @curr Index in array for current sample statistics.
3621 * @action Action expected from current function.
3622 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3623 * flag indicating that a restart record has been previously
3624 * found (.@restart) and time used for the X axis origin
3626 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3627 * @record_hdr Pointer on record header of current stats sample.
3628 ***************************************************************************
3630 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3631 unsigned long long itv, struct record_header *record_hdr)
3633 struct stats_net_ip6
3634 *snic = (struct stats_net_ip6 *) a->buf[curr],
3635 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3636 int group[] = {4, 2, 2, 2};
3637 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3639 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3640 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3641 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3642 "asmrq6/s", "asmok6/s",
3643 "imcpck6/s", "omcpck6/s",
3644 "fragok6/s", "fragcr6/s"};
3645 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3646 static double *spmin, *spmax;
3648 static int *outsize;
3650 if (action & F_BEGIN) {
3652 * Allocate arrays that will contain the graphs data
3653 * and the min/max values.
3655 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3658 if (action & F_MAIN) {
3659 /* Check for min/max values */
3660 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3661 itv, spmin, spmax, g_fields);
3664 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3665 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3666 out, outsize, svg_p->restart);
3668 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3669 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3670 out + 1, outsize + 1, svg_p->restart);
3672 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3673 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3674 out + 2, outsize + 2, svg_p->restart);
3676 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3677 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3678 out + 3, outsize + 3, svg_p->restart);
3680 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3681 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3682 out + 4, outsize + 4, svg_p->restart);
3684 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3685 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3686 out + 5, outsize + 5, svg_p->restart);
3688 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3689 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3690 out + 6, outsize + 6, svg_p->restart);
3692 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3693 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3694 out + 7, outsize + 7, svg_p->restart);
3696 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3697 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3698 out + 8, outsize + 8, svg_p->restart);
3700 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3701 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3702 out + 9, outsize + 9, svg_p->restart);
3705 if (action & F_END) {
3706 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3707 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3709 /* Free remaining structures */
3710 free_graphs(out, outsize, spmin, spmax);
3715 ***************************************************************************
3716 * Display IPv6 network errors statistics in SVG.
3719 * @a Activity structure with statistics.
3720 * @curr Index in array for current sample statistics.
3721 * @action Action expected from current function.
3722 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3723 * flag indicating that a restart record has been previously
3724 * found (.@restart) and time used for the X axis origin
3726 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3727 * @record_hdr Pointer on record header of current stats sample.
3728 ***************************************************************************
3730 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3731 unsigned long long itv, struct record_header *record_hdr)
3733 struct stats_net_eip6
3734 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3735 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3736 int group[] = {4, 2, 2, 3};
3737 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3739 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3740 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3741 "IPv6 network errors statistics (5)"};
3742 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3743 "idisc6/s", "odisc6/s",
3744 "inort6/s", "onort6/s",
3745 "asmf6/s", "fragf6/s", "itrpck6/s"};
3746 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3747 static double *spmin, *spmax;
3749 static int *outsize;
3751 if (action & F_BEGIN) {
3753 * Allocate arrays that will contain the graphs data
3754 * and the min/max values.
3756 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3759 if (action & F_MAIN) {
3760 /* Check for min/max values */
3761 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3762 itv, spmin, spmax, g_fields);
3765 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3766 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3767 out, outsize, svg_p->restart);
3769 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3770 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3771 out + 1, outsize + 1, svg_p->restart);
3773 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3774 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3775 out + 2, outsize + 2, svg_p->restart);
3777 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3778 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3779 out + 3, outsize + 3, svg_p->restart);
3781 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3782 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3783 out + 4, outsize + 4, svg_p->restart);
3785 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3786 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3787 out + 5, outsize + 5, svg_p->restart);
3789 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3790 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3791 out + 6, outsize + 6, svg_p->restart);
3793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3794 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3795 out + 7, outsize + 7, svg_p->restart);
3797 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3798 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3799 out + 8, outsize + 8, svg_p->restart);
3801 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3802 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3803 out + 9, outsize + 9, svg_p->restart);
3805 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3806 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3807 out + 10, outsize + 10, svg_p->restart);
3810 if (action & F_END) {
3811 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3812 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3814 /* Free remaining structures */
3815 free_graphs(out, outsize, spmin, spmax);
3820 ***************************************************************************
3821 * Display ICMPv6 network statistics in SVG.
3824 * @a Activity structure with statistics.
3825 * @curr Index in array for current sample statistics.
3826 * @action Action expected from current function.
3827 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3828 * flag indicating that a restart record has been previously
3829 * found (.@restart) and time used for the X axis origin
3831 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3832 * @record_hdr Pointer on record header of current stats sample.
3833 ***************************************************************************
3835 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3836 unsigned long long itv, struct record_header *record_hdr)
3838 struct stats_net_icmp6
3839 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3840 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3841 int group[] = {2, 3, 5, 3, 4};
3842 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3843 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3844 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3845 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3846 "ICMPv6 network statistics (5)"};
3847 char *g_title[] = {"imsg6/s", "omsg6/s",
3848 "iech6/s", "iechr6/s", "oechr6/s",
3849 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3850 "irtsol6/s", "ortsol6/s", "irtad6/s",
3851 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3852 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3853 static double *spmin, *spmax;
3855 static int *outsize;
3857 if (action & F_BEGIN) {
3859 * Allocate arrays that will contain the graphs data
3860 * and the min/max values.
3862 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3865 if (action & F_MAIN) {
3866 /* Check for min/max values */
3867 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3868 itv, spmin, spmax, g_fields);
3871 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3872 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3873 out, outsize, svg_p->restart);
3875 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3876 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3877 out + 1, outsize + 1, svg_p->restart);
3879 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3880 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3881 out + 2, outsize + 2, svg_p->restart);
3883 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3884 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3885 out + 3, outsize + 3, svg_p->restart);
3887 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3888 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3889 out + 4, outsize + 4, svg_p->restart);
3891 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3892 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3893 out + 5, outsize + 5, svg_p->restart);
3895 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3896 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3897 out + 6, outsize + 6, svg_p->restart);
3899 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3900 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3901 out + 7, outsize + 7, svg_p->restart);
3903 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3904 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3905 out + 8, outsize + 8, svg_p->restart);
3907 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3908 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3909 out + 9, outsize + 9, svg_p->restart);
3911 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3912 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3913 out + 10, outsize + 10, svg_p->restart);
3915 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3916 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3917 out + 11, outsize + 11, svg_p->restart);
3919 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3920 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3921 out + 12, outsize + 12, svg_p->restart);
3923 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3924 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3925 out + 13, outsize + 13, svg_p->restart);
3927 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3928 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3929 out + 14, outsize + 14, svg_p->restart);
3931 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3932 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3933 out + 15, outsize + 15, svg_p->restart);
3935 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3936 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3937 out + 16, outsize + 16, svg_p->restart);
3940 if (action & F_END) {
3941 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3942 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3944 /* Free remaining structures */
3945 free_graphs(out, outsize, spmin, spmax);
3950 ***************************************************************************
3951 * Display ICMPv6 network errors statistics in SVG.
3954 * @a Activity structure with statistics.
3955 * @curr Index in array for current sample statistics.
3956 * @action Action expected from current function.
3957 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3958 * flag indicating that a restart record has been previously
3959 * found (.@restart) and time used for the X axis origin
3961 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3962 * @record_hdr Pointer on record header of current stats sample.
3963 ***************************************************************************
3965 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3966 unsigned long long itv, struct record_header *record_hdr)
3968 struct stats_net_eicmp6
3969 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3970 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3971 int group[] = {1, 2, 2, 2, 2, 2};
3972 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3973 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3974 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3975 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3976 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3977 char *g_title[] = {"ierr6/s",
3978 "idtunr6/s", "odtunr6/s",
3979 "itmex6/s", "otmex6/s",
3980 "iprmpb6/s", "oprmpb6/s",
3981 "iredir6/s", "oredir6/s",
3982 "ipck2b6/s", "opck2b6/s"};
3983 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3984 static double *spmin, *spmax;
3986 static int *outsize;
3988 if (action & F_BEGIN) {
3990 * Allocate arrays that will contain the graphs data
3991 * and the min/max values.
3993 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3996 if (action & F_MAIN) {
3997 /* Check for min/max values */
3998 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3999 itv, spmin, spmax, g_fields);
4002 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4003 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4004 out, outsize, svg_p->restart);
4006 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4007 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4008 out + 1, outsize + 1, svg_p->restart);
4010 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4011 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4012 out + 2, outsize + 2, svg_p->restart);
4014 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4015 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4016 out + 3, outsize + 3, svg_p->restart);
4018 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4019 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4020 out + 4, outsize + 4, svg_p->restart);
4022 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4023 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4024 out + 5, outsize + 5, svg_p->restart);
4026 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4027 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4028 out + 6, outsize + 6, svg_p->restart);
4030 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4031 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4032 out + 7, outsize + 7, svg_p->restart);
4034 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4035 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4036 out + 8, outsize + 8, svg_p->restart);
4038 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4039 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4040 out + 9, outsize + 9, svg_p->restart);
4042 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4043 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4044 out + 10, outsize + 10, svg_p->restart);
4047 if (action & F_END) {
4048 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4049 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4051 /* Free remaining structures */
4052 free_graphs(out, outsize, spmin, spmax);
4057 ***************************************************************************
4058 * Display UDPv6 network statistics in SVG.
4061 * @a Activity structure with statistics.
4062 * @curr Index in array for current sample statistics.
4063 * @action Action expected from current function.
4064 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4065 * flag indicating that a restart record has been previously
4066 * found (.@restart) and time used for the X axis origin
4068 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4069 * @record_hdr Pointer on record header of current stats sample.
4070 ***************************************************************************
4072 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4073 unsigned long long itv, struct record_header *record_hdr)
4075 struct stats_net_udp6
4076 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4077 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4078 int group[] = {2, 2};
4079 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4080 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
4081 char *g_title[] = {"idgm6/s", "odgm6/s",
4082 "noport6/s", "idgmer6/s"};
4083 int g_fields[] = {0, 1, 2, 3};
4084 static double *spmin, *spmax;
4086 static int *outsize;
4088 if (action & F_BEGIN) {
4090 * Allocate arrays that will contain the graphs data
4091 * and the min/max values.
4093 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4096 if (action & F_MAIN) {
4097 /* Check for min/max values */
4098 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4099 itv, spmin, spmax, g_fields);
4102 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4103 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4104 out, outsize, svg_p->restart);
4106 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4107 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4108 out + 1, outsize + 1, svg_p->restart);
4110 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4111 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4112 out + 2, outsize + 2, svg_p->restart);
4114 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4115 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4116 out + 3, outsize + 3, svg_p->restart);
4119 if (action & F_END) {
4120 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4121 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4123 /* Free remaining structures */
4124 free_graphs(out, outsize, spmin, spmax);
4129 ***************************************************************************
4130 * Display CPU frequency statistics in SVG.
4133 * @a Activity structure with statistics.
4134 * @curr Index in array for current sample statistics.
4135 * @action Action expected from current function.
4136 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4137 * flag indicating that a restart record has been previously
4138 * found (.@restart) and time used for the X axis origin
4140 * @itv Interval of time in 1/100th of a second (unused here).
4141 * @record_hdr Pointer on record header of current stats sample.
4142 ***************************************************************************
4144 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4145 unsigned long long itv, struct record_header *record_hdr)
4147 struct stats_pwr_cpufreq *spc, *spp;
4149 int g_type[] = {SVG_LINE_GRAPH};
4150 char *title[] = {"CPU frequency"};
4151 char *g_title[] = {"MHz"};
4152 static double *spmin, *spmax;
4154 static int *outsize;
4158 if (action & F_BEGIN) {
4160 * Allocate arrays that will contain the graphs data
4161 * and the min/max values.
4163 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4166 if (action & F_MAIN) {
4168 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4170 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4171 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4173 /* Should current CPU (including CPU "all") be displayed? */
4174 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4179 * Note: Don't skip offline CPU here as it is needed
4180 * to make the graph go though 0.
4184 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4185 ((double) spp->cpufreq) / 100,
4186 ((double) spc->cpufreq) / 100,
4187 out + i, outsize + i, svg_p->restart, svg_p->dt,
4188 spmin + i, spmax + i);
4192 if (action & F_END) {
4193 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
4195 /* Should current CPU (including CPU "all") be displayed? */
4196 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4201 /* This is CPU "all" */
4202 strcpy(item_name, "all");
4206 * If the maximum frequency reached by the CPU is 0, then
4207 * the CPU has been offline on the whole period.
4208 * => Don't display it.
4210 if (*(spmax + i) == 0)
4213 sprintf(item_name, "%d", i - 1);
4216 draw_activity_graphs(a->g_nr, g_type,
4217 title, g_title, item_name, group,
4218 spmin + i, spmax + i, out + i, outsize + i,
4219 svg_p, record_hdr, i);
4222 /* Free remaining structures */
4223 free_graphs(out, outsize, spmin, spmax);
4228 ***************************************************************************
4229 * Display fan statistics in SVG.
4232 * @a Activity structure with statistics.
4233 * @curr Index in array for current sample statistics.
4234 * @action Action expected from current function.
4235 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4236 * flag indicating that a restart record has been previously
4237 * found (.@restart) and time used for the X axis origin
4239 * @itv Interval of time in 1/100th of a second (unused here).
4240 * @record_hdr Pointer on record header of current stats sample.
4241 ***************************************************************************
4243 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4244 unsigned long long itv, struct record_header *record_hdr)
4246 struct stats_pwr_fan *spc, *spp;
4248 int g_type[] = {SVG_LINE_GRAPH};
4249 char *title[] = {"Fan speed"};
4250 char *g_title[] = {"~rpm"};
4251 static double *spmin, *spmax;
4253 static int *outsize;
4254 char item_name[MAX_SENSORS_DEV_LEN + 8];
4257 if (action & F_BEGIN) {
4259 * Allocate arrays that will contain the graphs data
4260 * and the min/max values.
4262 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4265 if (action & F_MAIN) {
4267 for (i = 0; i < a->nr[curr]; i++) {
4269 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4270 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4273 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4276 out + i, outsize + i, svg_p->restart, svg_p->dt,
4277 spmin + i, spmax + i);
4281 if (action & F_END) {
4282 for (i = 0; i < svg_p->nr_max; i++) {
4284 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4286 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4287 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4289 draw_activity_graphs(a->g_nr, g_type,
4290 title, g_title, item_name, group,
4291 spmin + i, spmax + i, out + i, outsize + i,
4292 svg_p, record_hdr, FALSE);
4295 /* Free remaining structures */
4296 free_graphs(out, outsize, spmin, spmax);
4301 ***************************************************************************
4302 * Display temperature statistics in SVG.
4305 * @a Activity structure with statistics.
4306 * @curr Index in array for current sample statistics.
4307 * @action Action expected from current function.
4308 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4309 * flag indicating that a restart record has been previously
4310 * found (.@restart) and time used for the X axis origin
4312 * @itv Interval of time in 1/100th of a second (unused here).
4313 * @record_hdr Pointer on record header of current stats sample.
4314 ***************************************************************************
4316 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4317 unsigned long long itv, struct record_header *record_hdr)
4319 struct stats_pwr_temp *spc;
4320 int group[] = {1, 1};
4321 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4322 char *title[] = {"Device temperature (1)",
4323 "Device temperature (2)"};
4324 char *g_title[] = {"~degC",
4326 static double *spmin, *spmax;
4328 static int *outsize;
4329 char item_name[MAX_SENSORS_DEV_LEN + 8];
4333 if (action & F_BEGIN) {
4335 * Allocate arrays that will contain the graphs data
4336 * and the min/max values.
4338 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4341 if (action & F_MAIN) {
4342 /* For each temperature sensor */
4343 for (i = 0; i < a->nr[curr]; i++) {
4345 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4347 /* Look for min/max values */
4348 if (spc->temp < *(spmin + 2 * i)) {
4349 *(spmin + 2 * i) = spc->temp;
4351 if (spc->temp > *(spmax + 2 * i)) {
4352 *(spmax + 2 * i) = spc->temp;
4354 tval = (spc->temp_max - spc->temp_min) ?
4355 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4357 if (tval < *(spmin + 2 * i + 1)) {
4358 *(spmin + 2 * i + 1) = tval;
4360 if (tval > *(spmax + 2 * i + 1)) {
4361 *(spmax + 2 * i + 1) = tval;
4365 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4367 out + 2 * i, outsize + 2 * i, svg_p->restart);
4369 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4371 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4375 if (action & F_END) {
4376 for (i = 0; i < svg_p->nr_max; i++) {
4378 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4380 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4381 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4383 draw_activity_graphs(a->g_nr, g_type,
4384 title, g_title, item_name, group,
4385 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4386 svg_p, record_hdr, FALSE);
4389 /* Free remaining structures */
4390 free_graphs(out, outsize, spmin, spmax);
4395 ***************************************************************************
4396 * Display voltage inputs statistics in SVG.
4399 * @a Activity structure with statistics.
4400 * @curr Index in array for current sample statistics.
4401 * @action Action expected from current function.
4402 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4403 * flag indicating that a restart record has been previously
4404 * found (.@restart) and time used for the X axis origin
4406 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4407 * @record_hdr Pointer on record header of current stats sample.
4408 ***************************************************************************
4410 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4411 unsigned long long itv, struct record_header *record_hdr)
4413 struct stats_pwr_in *spc;
4414 int group[] = {1, 1};
4415 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4416 char *title[] = {"Voltage inputs (1)",
4417 "Voltage inputs (2)"};
4418 char *g_title[] = {"inV",
4420 static double *spmin, *spmax;
4422 static int *outsize;
4423 char item_name[MAX_SENSORS_DEV_LEN + 8];
4427 if (action & F_BEGIN) {
4429 * Allocate arrays that will contain the graphs data
4430 * and the min/max values.
4432 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4435 if (action & F_MAIN) {
4436 /* For each voltage input sensor */
4437 for (i = 0; i < a->nr[curr]; i++) {
4439 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4441 /* Look for min/max values */
4442 if (spc->in < *(spmin + 2 * i)) {
4443 *(spmin + 2 * i) = spc->in;
4445 if (spc->in > *(spmax + 2 * i)) {
4446 *(spmax + 2 * i) = spc->in;
4448 tval = (spc->in_max - spc->in_min) ?
4449 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4451 if (tval < *(spmin + 2 * i + 1)) {
4452 *(spmin + 2 * i + 1) = tval;
4454 if (tval > *(spmax + 2 * i + 1)) {
4455 *(spmax + 2 * i + 1) = tval;
4459 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4461 out + 2 * i, outsize + 2 * i, svg_p->restart);
4463 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4465 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4469 if (action & F_END) {
4470 for (i = 0; i < svg_p->nr_max; i++) {
4472 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4474 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4475 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4477 draw_activity_graphs(a->g_nr, g_type,
4478 title, g_title, item_name, group,
4479 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4480 svg_p, record_hdr, FALSE);
4483 /* Free remaining structures */
4484 free_graphs(out, outsize, spmin, spmax);
4489 ***************************************************************************
4490 * Display huge pages statistics in SVG.
4493 * @a Activity structure with statistics.
4494 * @curr Index in array for current sample statistics.
4495 * @action Action expected from current function.
4496 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4497 * flag indicating that a restart record has been previously
4498 * found (.@restart) and time used for the X axis origin
4500 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4501 * @record_hdr Pointer on record header of current stats sample.
4502 ***************************************************************************
4504 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4505 unsigned long long itv, struct record_header *record_hdr)
4508 *smc = (struct stats_huge *) a->buf[curr];
4509 int group[] = {2, 1};
4510 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4511 char *title[] = {"Huge pages utilization (1)",
4512 "Huge pages utilization (2)"};
4513 char *g_title[] = {"~kbhugfree", "~kbhugused",
4515 int g_fields[] = {0};
4516 unsigned int local_types_nr[] = {0, 1, 0};
4517 static double *spmin, *spmax;
4519 static int *outsize;
4522 if (action & F_BEGIN) {
4524 * Allocate arrays that will contain the graphs data
4525 * and the min/max values.
4527 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4530 if (action & F_MAIN) {
4531 /* Check for min/max values */
4532 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4533 itv, spmin, spmax, g_fields);
4535 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4536 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4538 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4539 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4541 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4542 if (tval < *(spmin + 2)) {
4543 *(spmin + 2) = tval;
4545 if (tval > *(spmax + 2)) {
4546 *(spmax + 2) = tval;
4550 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4551 (unsigned long long) smc->frhkb,
4552 out, outsize, svg_p->restart);
4554 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4555 (unsigned long long) smc->tlhkb - smc->frhkb,
4556 out + 1, outsize + 1, svg_p->restart);
4558 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4560 out + 2, outsize + 2, svg_p->dt);
4563 if (action & F_END) {
4564 draw_activity_graphs(a->g_nr, g_type,
4565 title, g_title, NULL, group,
4566 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4568 /* Free remaining structures */
4569 free_graphs(out, outsize, spmin, spmax);
4574 ***************************************************************************
4575 * Display filesystem statistics in SVG.
4578 * @a Activity structure with statistics.
4579 * @curr Index in array for current sample statistics.
4580 * @action Action expected from current function.
4581 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4582 * flag indicating that a restart record has been previously
4583 * found (.@restart) and time used for the X axis origin
4585 * @itv Interval of time in 1/100th of a second (unused here).
4586 * @record_hdr Pointer on record header of current stats sample.
4587 ***************************************************************************
4589 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4590 unsigned long long itv, struct record_header *record_hdr)
4592 struct stats_filesystem *sfc, *sfp;
4593 int group[] = {2, 2, 2, 1};
4594 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4595 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4596 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4597 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4598 char *g_title[] = {"~MBfsfree", "~MBfsused",
4599 "%ufsused", "%fsused",
4600 "Ifree/1000", "Iused/1000",
4602 static double *spmin, *spmax;
4604 static int *outsize;
4605 char *item_name = NULL;
4607 int i, k, pos, restart;
4609 if (action & F_BEGIN) {
4611 * Allocate arrays (#0..6) that will contain the graphs data
4612 * and the min/max values.
4613 * Also allocate two additional arrays (#7..8) for each filesystem:
4614 * out + 7 will contain the filesystem name,
4615 * out + 8 will contain the mount point.
4617 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
4620 if (action & F_MAIN) {
4621 /* For each filesystem structure */
4622 for (i = 0; i < a->nr[curr]; i++) {
4623 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4625 /* Look for corresponding graph */
4626 for (k = 0; k < svg_p->nr_max; k++) {
4627 item_name = *(out + k * 9 + 7);
4628 if (!strcmp(sfc->fs_name, item_name))
4633 if (k == svg_p->nr_max) {
4634 /* Graph not found: Look for first free entry */
4635 for (k = 0; k < svg_p->nr_max; k++) {
4636 item_name = *(out + k * 9 + 7);
4637 if (!strcmp(item_name, ""))
4640 if (k == svg_p->nr_max) {
4641 /* No free graph entry: Extend all buffers */
4642 reallocate_all_graph_lines(svg_p->nr_max,
4643 &out, &outsize, &spmin, &spmax);
4650 if (!item_name[0]) {
4651 /* Save filesystem name and mount point (if not already done) */
4652 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4653 item_name[CHUNKSIZE - 1] = '\0';
4654 item_name = *(out + pos + 8);
4655 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4656 item_name[CHUNKSIZE - 1] = '\0';
4660 for (k = 0; k < a->nr[!curr]; k++) {
4661 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4662 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4663 /* Filesystem found in previous sample */
4664 restart = svg_p->restart;
4668 /* Check for min/max values */
4670 /* Compute fsfree min/max values */
4671 tval = (double) sfc->f_bfree;
4672 if (tval > *(spmax + pos)) {
4673 *(spmax + pos) = tval;
4675 if (tval < *(spmin + pos)) {
4676 *(spmin + pos) = tval;
4678 /* Compute fsused min/max values */
4679 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4680 if (tval > *(spmax + pos + 1)) {
4681 *(spmax + pos + 1) = tval;
4683 if (tval < *(spmin + pos + 1)) {
4684 *(spmin + pos + 1) = tval;
4686 /* Compute %ufsused min/max values */
4687 tval = sfc->f_blocks ?
4688 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4689 if (tval > *(spmax + pos + 2)) {
4690 *(spmax + pos + 2) = tval;
4692 if (tval < *(spmin + pos + 2)) {
4693 *(spmin + pos + 2) = tval;
4695 /* Compute %fsused min/max values */
4696 tval = sfc->f_blocks ?
4697 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4698 if (tval > *(spmax + pos + 3)) {
4699 *(spmax + pos + 3) = tval;
4701 if (tval < *(spmin + pos + 3)) {
4702 *(spmin + pos + 3) = tval;
4704 /* Compute Ifree min/max values */
4705 tval = (double) sfc->f_ffree;
4706 if (tval > *(spmax + pos + 4)) {
4707 *(spmax + pos + 4) = tval;
4709 if (tval < *(spmin + pos + 4)) {
4710 *(spmin + pos + 4) = tval;
4712 /* Compute Iused min/max values */
4713 tval = (double) (sfc->f_files - sfc->f_ffree);
4714 if (tval > *(spmax + pos + 5)) {
4715 *(spmax + pos + 5) = tval;
4717 if (tval < *(spmin + pos + 5)) {
4718 *(spmin + pos + 5) = tval;
4720 /* Compute %Iused min/max values */
4721 tval = sfc->f_files ?
4722 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4723 if (tval > *(spmax + pos + 6)) {
4724 *(spmax + pos + 6) = tval;
4726 if (tval < *(spmin + pos + 6)) {
4727 *(spmin + pos + 6) = tval;
4731 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4732 (double) sfc->f_bfree / 1024 / 1024,
4733 out + pos, outsize + pos, restart);
4735 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4736 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4737 out + pos + 1, outsize + pos + 1, restart);
4739 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4742 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4743 out + pos + 2, outsize + pos + 2, svg_p->dt);
4745 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4748 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4749 out + pos + 3, outsize + pos + 3, svg_p->dt);
4751 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4752 ((double) sfc->f_ffree) / 1000,
4753 out + pos + 4, outsize + pos + 4, restart);
4755 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4756 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4757 out + pos + 5, outsize + pos + 5, restart);
4759 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4762 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4763 out + pos + 6, outsize + pos + 6, svg_p->dt);
4767 if (action & F_END) {
4769 for (i = 0; i < svg_p->nr_max; i++) {
4771 /* Check if there is something to display */
4776 /* Conversion B -> MB and inodes/1000 */
4777 for (k = 0; k < 2; k++) {
4778 *(spmin + pos + k) /= (1024 * 1024);
4779 *(spmax + pos + k) /= (1024 * 1024);
4780 *(spmin + pos + 4 + k) /= 1000;
4781 *(spmax + pos + 4 + k) /= 1000;
4784 if (DISPLAY_MOUNT(a->opt_flags)) {
4785 item_name = *(out + pos + 8);
4788 item_name = *(out + pos + 7);
4791 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4792 spmin + pos, spmax + pos, out + pos, outsize + pos,
4793 svg_p, record_hdr, FALSE);
4796 /* Free remaining structures */
4797 free_graphs(out, outsize, spmin, spmax);
4802 ***************************************************************************
4803 * Display Fibre Channel HBA statistics in SVG.
4806 * @a Activity structure with statistics.
4807 * @curr Index in array for current sample statistics.
4808 * @action Action expected from current function.
4809 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4810 * flag indicating that a restart record has been previously
4811 * found (.@restart) and time used for the X axis origin
4813 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4814 * @record_hdr Pointer on record header of current stats sample.
4815 ***************************************************************************
4817 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4818 unsigned long long itv, struct record_header *record_hdr)
4820 struct stats_fchost *sfcc, *sfcp;
4821 int group[] = {2, 2};
4822 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4823 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4824 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4825 "fch_rxw/s", "fch_txw/s"};
4826 int g_fields[] = {0, 1, 2, 3};
4827 static double *spmin, *spmax;
4829 static int *outsize;
4831 int i, j, j0, k, found, pos, restart, *unregistered;
4833 if (action & F_BEGIN) {
4835 * Allocate arrays (#0..3) that will contain the graphs data
4836 * and the min/max values.
4837 * Also allocate one additional array (#4) that will contain
4838 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4839 * has either still not been registered, or has been unregistered
4842 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
4845 if (action & F_MAIN) {
4846 restart = svg_p->restart;
4848 * Mark previously registered interfaces as now
4849 * possibly unregistered for all graphs.
4851 for (k = 0; k < svg_p->nr_max; k++) {
4852 unregistered = outsize + k * 5 + 4;
4853 if (*unregistered == FALSE) {
4854 *unregistered = MAYBE;
4858 /* For each FC HBA */
4859 for (i = 0; i < a->nr[curr]; i++) {
4863 if (a->nr[!curr] > 0) {
4864 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4866 /* Look for corresponding graph */
4867 for (k = 0; k < svg_p->nr_max; k++) {
4868 item_name = *(out + k * 5 + 4);
4869 if (!strcmp(sfcc->fchost_name, item_name))
4873 if (k == svg_p->nr_max) {
4874 /* Graph not found: Look for first free entry */
4875 for (k = 0; k < svg_p->nr_max; k++) {
4876 item_name = *(out + k * 5 + 4);
4877 if (!strcmp(item_name, ""))
4880 if (k == svg_p->nr_max) {
4881 /* No free graph entry: Extend all buffers */
4882 reallocate_all_graph_lines(svg_p->nr_max,
4883 &out, &outsize, &spmin, &spmax);
4889 unregistered = outsize + pos + 4;
4891 /* Look for corresponding structure in previous iteration */
4894 if (j >= a->nr[!curr]) {
4895 j = a->nr[!curr] - 1;
4901 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4902 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4906 if (++j >= a->nr[!curr]) {
4917 * If current interface was marked as previously unregistered,
4918 * then set restart variable to TRUE so that the graph will be
4919 * discontinuous, and mark it as now registered.
4921 if (*unregistered == TRUE) {
4924 *unregistered = FALSE;
4926 item_name = *(out + pos + 4);
4927 if (!item_name[0]) {
4928 /* Save FC HBA name */
4929 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4930 item_name[CHUNKSIZE - 1] = '\0';
4933 /* Look for min/max values */
4934 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4935 itv, spmin + pos, spmax + pos, g_fields);
4938 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4939 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4940 out + pos, outsize + pos, restart);
4942 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4943 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4944 out + pos + 1, outsize + pos + 1, restart);
4946 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4947 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4948 out + pos + 2, outsize + pos + 2, restart);
4950 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4951 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4952 out + pos + 3, outsize + pos + 3, restart);
4955 /* Mark interfaces not seen here as now unregistered */
4956 for (k = 0; k < svg_p->nr_max; k++) {
4957 unregistered = outsize + k * 5 + 4;
4958 if (*unregistered != FALSE) {
4959 *unregistered = TRUE;
4964 if (action & F_END) {
4965 for (i = 0; i < svg_p->nr_max; i++) {
4967 /* Check if there is something to display */
4972 item_name = *(out + pos + 4);
4973 draw_activity_graphs(a->g_nr, g_type,
4974 title, g_title, item_name, group,
4975 spmin + pos, spmax + pos, out + pos, outsize + pos,
4976 svg_p, record_hdr, FALSE);
4979 /* Free remaining structures */
4980 free_graphs(out, outsize, spmin, spmax);
4985 ***************************************************************************
4986 * Display softnet statistics in SVG.
4989 * @a Activity structure with statistics.
4990 * @curr Index in array for current sample statistics.
4991 * @action Action expected from current function.
4992 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4993 * flag indicating that a restart record has been previously
4994 * found (.@restart) and time used for the X axis origin
4996 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4997 * @record_hdr Pointer on record header of current stats sample.
4998 ***************************************************************************
5000 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5001 unsigned long long itv, struct record_header *record_hdr)
5003 struct stats_softnet *ssnc, *ssnp;
5004 int group[] = {2, 3};
5005 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5006 char *title[] = {"Software-based network processing statistics (1)",
5007 "Software-based network processing statistics (2)"};
5008 char *g_title[] = {"total/s", "dropd/s",
5009 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5010 int g_fields[] = {0, 1, 2, 3, 4};
5011 static double *spmin, *spmax;
5013 static int *outsize;
5015 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5018 if (action & F_BEGIN) {
5020 * Allocate arrays that will contain the graphs data
5021 * and the min/max values.
5023 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
5026 if (action & F_MAIN) {
5027 /* @nr[curr] cannot normally be greater than @nr_ini */
5028 if (a->nr[curr] > a->nr_ini) {
5029 a->nr_ini = a->nr[curr];
5032 /* Compute statistics for CPU "all" */
5033 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5036 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5038 /* Should current CPU (including CPU "all") be displayed? */
5039 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
5040 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
5044 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5045 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5049 /* Check for min/max values */
5050 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5051 itv, spmin + pos, spmax + pos, g_fields);
5054 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5055 S_VALUE(ssnp->processed, ssnc->processed, itv),
5056 out + pos, outsize + pos, svg_p->restart);
5058 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5059 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5060 out + pos + 1, outsize + pos + 1, svg_p->restart);
5062 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5063 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5064 out + pos + 2, outsize + pos + 2, svg_p->restart);
5066 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5067 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5068 out + pos + 3, outsize + pos + 3, svg_p->restart);
5070 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5071 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5072 out + pos + 4, outsize + pos + 4, svg_p->restart);
5076 if (action & F_END) {
5077 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
5079 /* Should current CPU (including CPU "all") be displayed? */
5080 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5087 /* This is CPU "all" */
5088 strcpy(item_name, "all");
5091 sprintf(item_name, "%d", i - 1);
5094 draw_activity_graphs(a->g_nr, g_type,
5095 title, g_title, item_name, group,
5096 spmin + pos, spmax + pos, out + pos, outsize + pos,
5097 svg_p, record_hdr, FALSE);
5100 /* Free remaining structures */
5101 free_graphs(out, outsize, spmin, spmax);