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);
1135 if (!deltot_jiffies) {
1136 /* CPU "all" cannot be tickless */
1142 * Recalculate interval for current proc.
1143 * If result is 0 then current CPU is a tickless one.
1145 deltot_jiffies = get_per_cpu_interval(scc, scp);
1147 if (!deltot_jiffies) { /* Current CPU is tickless */
1149 val = 100.0; /* Tickless CPU: %idle = 100% */
1151 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1154 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1158 /* Check min/max values for %user, etc. */
1159 for (k = 0; k < j; k++) {
1160 if (0.0 < *(spmin + pos + k)) {
1161 *(spmin + pos + k) = 0.0;
1163 if (0.0 > *(spmax + pos + k)) {
1164 *(spmax + pos + k) = 0.0;
1169 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1171 out + pos + j, outsize + pos + j, svg_p->dt,
1172 spmin + pos + j, spmax + pos + j);
1177 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1179 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1180 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1181 out + pos, outsize + pos, svg_p->dt,
1182 spmin + pos, spmax + pos);
1186 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1188 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1190 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1191 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1192 out + pos, outsize + pos, svg_p->dt,
1193 spmin + pos, spmax + pos);
1196 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1198 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1199 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1200 out + pos + 1, outsize + pos + 1, svg_p->dt,
1201 spmin + pos + 1, spmax + pos + 1);
1205 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1207 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1209 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1210 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1211 out + pos + 1, outsize + pos + 1, svg_p->dt,
1212 spmin + pos + 1, spmax + pos + 1);
1215 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1217 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1219 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1220 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1222 out + pos + 2, outsize + pos + 2, svg_p->dt,
1223 spmin + pos + 2, spmax + pos + 2);
1227 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1228 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1229 out + pos + 2, outsize + pos + 2, svg_p->dt,
1230 spmin + pos + 2, spmax + pos + 2);
1234 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1235 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1236 out + pos + 3, outsize + pos + 3, svg_p->dt,
1237 spmin + pos + 3, spmax + pos + 3);
1239 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1240 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1241 out + pos + 4, outsize + pos + 4, svg_p->dt,
1242 spmin + pos + 4, spmax + pos + 4);
1244 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1246 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1247 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1248 out + pos + 5, outsize + pos + 5, svg_p->dt,
1249 spmin + pos + 5, spmax + pos + 5);
1251 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1252 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1253 out + pos + 6, outsize + pos + 6, svg_p->dt,
1254 spmin + pos + 6, spmax + pos + 6);
1256 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1257 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1258 out + pos + 7, outsize + pos + 7, svg_p->dt,
1259 spmin + pos + 7, spmax + pos + 7);
1261 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1262 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1263 out + pos + 8, outsize + pos + 8, svg_p->dt,
1264 spmin + pos + 8, spmax + pos + 8);
1273 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1275 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1276 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1277 out + pos + j, outsize + pos + j, svg_p->dt,
1278 spmin + pos + j, spmax + pos + j);
1282 if (action & F_END) {
1283 if (DISPLAY_IDLE(flags)) {
1284 /* Include additional %idle field */
1289 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
1291 /* Should current CPU (including CPU "all") be displayed? */
1292 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1298 /* This is CPU "all" */
1299 strcpy(item_name, "all");
1302 sprintf(item_name, "%d", i - 1);
1305 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1306 draw_activity_graphs(a->g_nr, g_type,
1307 title, g_title1, item_name, group1,
1308 spmin + pos, spmax + pos, out + pos, outsize + pos,
1309 svg_p, record_hdr, i);
1312 draw_activity_graphs(a->g_nr, g_type,
1313 title, g_title2, item_name, group2,
1314 spmin + pos, spmax + pos, out + pos, outsize + pos,
1315 svg_p, record_hdr, i);
1319 /* Free remaining structures */
1320 free_graphs(out, outsize, spmin, spmax);
1325 ***************************************************************************
1326 * Display task creation and context switch statistics in SVG.
1329 * @a Activity structure with statistics.
1330 * @curr Index in array for current sample statistics.
1331 * @action Action expected from current function.
1332 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1333 * flag indicating that a restart record has been previously
1334 * found (.@restart) and time used for the X axis origin
1336 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1337 * @record_hdr Pointer on record header of current stats sample.
1338 ***************************************************************************
1340 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1341 unsigned long long itv, struct record_header *record_hdr)
1344 *spc = (struct stats_pcsw *) a->buf[curr],
1345 *spp = (struct stats_pcsw *) a->buf[!curr];
1346 int group[] = {1, 1};
1347 int g_fields[] = {1, 0};
1348 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1349 char *title[] = {"Task creation", "Switching activity"};
1350 char *g_title[] = {"proc/s",
1352 static double *spmin, *spmax;
1354 static int *outsize;
1356 if (action & F_BEGIN) {
1358 * Allocate arrays that will contain the graphs data
1359 * and the min/max values.
1361 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1364 if (action & F_MAIN) {
1365 /* Check for min/max values */
1366 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1367 itv, spmin, spmax, g_fields);
1369 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1370 S_VALUE(spp->processes, spc->processes, itv),
1371 out, outsize, svg_p->restart);
1373 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1374 S_VALUE(spp->context_switch, spc->context_switch, itv),
1375 out + 1, outsize + 1, svg_p->restart);
1378 if (action & F_END) {
1379 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1380 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1382 /* Free remaining structures */
1383 free_graphs(out, outsize, spmin, spmax);
1388 ***************************************************************************
1389 * Display swap statistics in SVG.
1392 * @a Activity structure with statistics.
1393 * @curr Index in array for current sample statistics.
1394 * @action Action expected from current function.
1395 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1396 * flag indicating that a restart record has been previously
1397 * found (.@restart) and time used for the X axis origin
1399 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1400 * @record_hdr Pointer on record header of current stats sample.
1401 ***************************************************************************
1403 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1404 unsigned long long itv, struct record_header *record_hdr)
1407 *ssc = (struct stats_swap *) a->buf[curr],
1408 *ssp = (struct stats_swap *) a->buf[!curr];
1410 int g_type[] = {SVG_LINE_GRAPH};
1411 char *title[] = {"Swap activity"};
1412 char *g_title[] = {"pswpin/s", "pswpout/s" };
1413 int g_fields[] = {0, 1};
1414 static double *spmin, *spmax;
1416 static int *outsize;
1418 if (action & F_BEGIN) {
1420 * Allocate arrays that will contain the graphs data
1421 * and the min/max values.
1423 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1426 if (action & F_MAIN) {
1427 /* Check for min/max values */
1428 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1429 itv, spmin, spmax, g_fields);
1431 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1432 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1433 out, outsize, svg_p->restart);
1435 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1436 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1437 out + 1, outsize + 1, svg_p->restart);
1440 if (action & F_END) {
1441 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1442 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1444 /* Free remaining structures */
1445 free_graphs(out, outsize, spmin, spmax);
1450 ***************************************************************************
1451 * Display paging statistics in SVG.
1454 * @a Activity structure with statistics.
1455 * @curr Index in array for current sample statistics.
1456 * @action Action expected from current function.
1457 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1458 * flag indicating that a restart record has been previously
1459 * found (.@restart) and time used for the X axis origin
1461 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1462 * @record_hdr Pointer on record header of current stats sample.
1463 ***************************************************************************
1465 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1466 unsigned long long itv, struct record_header *record_hdr)
1469 *spc = (struct stats_paging *) a->buf[curr],
1470 *spp = (struct stats_paging *) a->buf[!curr];
1471 int group[] = {2, 2, 4};
1472 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1473 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1474 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1475 "fault/s", "majflt/s",
1476 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1477 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1478 static double *spmin, *spmax;
1480 static int *outsize;
1482 if (action & F_BEGIN) {
1484 * Allocate arrays that will contain the graphs data
1485 * and the min/max values.
1487 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1490 if (action & F_MAIN) {
1491 /* Check for min/max values */
1492 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1493 itv, spmin, spmax, g_fields);
1495 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1496 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1497 out, outsize, svg_p->restart);
1499 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1500 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1501 out + 1, outsize + 1, svg_p->restart);
1503 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1504 S_VALUE(spp->pgfault, spc->pgfault, itv),
1505 out + 2, outsize + 2, svg_p->restart);
1507 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1508 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1509 out + 3, outsize + 3, svg_p->restart);
1511 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1512 S_VALUE(spp->pgfree, spc->pgfree, itv),
1513 out + 4, outsize + 4, svg_p->restart);
1515 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1516 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1517 out + 5, outsize + 5, svg_p->restart);
1519 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1520 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1521 out + 6, outsize + 6, svg_p->restart);
1523 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1524 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1525 out + 7, outsize + 7, svg_p->restart);
1528 if (action & F_END) {
1529 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1530 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1532 /* Free remaining structures */
1533 free_graphs(out, outsize, spmin, spmax);
1538 ***************************************************************************
1539 * Display I/O and transfer rate statistics in SVG.
1542 * @a Activity structure with statistics.
1543 * @curr Index in array for current sample statistics.
1544 * @action Action expected from current function.
1545 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1546 * flag indicating that a restart record has been previously
1547 * found (.@restart) and time used for the X axis origin
1549 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1550 * @record_hdr Pointer on record header of current stats sample.
1551 ***************************************************************************
1553 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1554 unsigned long long itv, struct record_header *record_hdr)
1557 *sic = (struct stats_io *) a->buf[curr],
1558 *sip = (struct stats_io *) a->buf[!curr];
1559 int group[] = {3, 2};
1560 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1561 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1562 char *g_title[] = {"tps", "rtps", "wtps",
1563 "bread/s", "bwrtn/s"};
1564 int g_fields[] = {0, 1, 2, 3, 4};
1565 static double *spmin, *spmax;
1567 static int *outsize;
1569 if (action & F_BEGIN) {
1571 * Allocate arrays that will contain the graphs data
1572 * and the min/max values.
1574 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1577 if (action & F_MAIN) {
1578 /* Check for min/max values */
1579 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1580 itv, spmin, spmax, g_fields);
1583 * If we get negative values, this is probably because
1584 * one or more devices/filesystems have been unmounted.
1585 * We display 0.0 in this case though we should rather tell
1586 * the user that the value cannot be calculated here.
1589 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1590 sic->dk_drive < sip->dk_drive ? 0.0 :
1591 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1592 out, outsize, svg_p->restart);
1594 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1595 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1596 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1597 out + 1, outsize + 1, svg_p->restart);
1599 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1600 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1601 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1602 out + 2, outsize + 2, svg_p->restart);
1604 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1605 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1606 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1607 out + 3, outsize + 3, svg_p->restart);
1609 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1610 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1611 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1612 out + 4, outsize + 4, svg_p->restart);
1615 if (action & F_END) {
1616 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1617 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1619 /* Free remaining structures */
1620 free_graphs(out, outsize, spmin, spmax);
1625 ***************************************************************************
1626 * Display memory statistics in SVG.
1629 * @a Activity structure with statistics.
1630 * @curr Index in array for current sample statistics.
1631 * @action Action expected from current function.
1632 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1633 * flag indicating that a restart record has been previously
1634 * found (.@restart) and time used for the X axis origin
1636 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1637 * @record_hdr Pointer on record header of current stats sample.
1638 ***************************************************************************
1640 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1641 unsigned long long itv, struct record_header *record_hdr)
1644 *smc = (struct stats_memory *) a->buf[curr];
1645 int group1[] = {3, 1, 3, 1, 3, 5};
1646 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1647 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1648 int group2[] = {3, 1, 1};
1649 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1650 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1651 "Memory utilization (3)", "Memory utilization (4)",
1652 "Memory utilization (5)", "Memory utilization (6)"};
1653 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1654 "Swap utilization (3)"};
1655 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1656 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1657 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1659 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1661 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1662 static double *spmin, *spmax;
1664 static int *outsize;
1667 unsigned long long nousedmem;
1669 if (action & F_BEGIN) {
1671 * Allocate arrays that will contain the graphs data
1672 * and the min/max values.
1674 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1677 if (action & F_MAIN) {
1678 /* Check for min/max values */
1679 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1680 itv, spmin, spmax, g_fields);
1681 /* Compute %memused min/max values */
1682 nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
1683 if (nousedmem > smc->tlmkb) {
1684 nousedmem = smc->tlmkb;
1686 tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
1687 if (tval > *(spmax + 3)) {
1688 *(spmax + 3) = tval;
1690 if (tval < *(spmin + 3)) {
1691 *(spmin + 3) = tval;
1693 /* Compute %commit min/max values */
1694 tval = (smc->tlmkb + smc->tlskb) ?
1695 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1696 if (tval > *(spmax + 7)) {
1697 *(spmax + 7) = tval;
1699 if (tval < *(spmin + 7)) {
1700 *(spmin + 7) = tval;
1702 /* Compute %swpused min/max values */
1704 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1705 if (tval > *(spmax + 19)) {
1706 *(spmax + 19) = tval;
1708 if (tval < *(spmin + 19)) {
1709 *(spmin + 19) = tval;
1711 /* Compute %swpcad min/max values */
1712 tval = (smc->tlskb - smc->frskb) ?
1713 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1714 if (tval > *(spmax + 20)) {
1715 *(spmax + 20) = tval;
1717 if (tval < *(spmin + 20)) {
1718 *(spmin + 20) = tval;
1720 /* Compute memused min/max values in MB */
1721 tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
1722 if (tval > *(spmax + 2)) {
1723 *(spmax + 2) = tval;
1725 if (tval < *(spmin + 2)) {
1726 *(spmin + 2) = tval;
1728 /* Compute swpused min/max values in MB */
1729 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1730 if (tval > *(spmax + 17)) {
1731 *(spmax + 17) = tval;
1733 if (tval < *(spmin + 17)) {
1734 *(spmin + 17) = tval;
1738 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1739 ((double) smc->frmkb) / 1024,
1740 out, outsize, svg_p->restart);
1742 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1743 ((double) (smc->tlmkb - nousedmem)) / 1024,
1744 out + 2, outsize + 2, svg_p->restart);
1746 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1747 ((double) smc->availablekb) / 1024,
1748 out + 1, outsize + 1, svg_p->restart);
1750 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1751 ((double) smc->bufkb) / 1024,
1752 out + 4, outsize + 4, svg_p->restart);
1754 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1755 ((double) smc->camkb) / 1024,
1756 out + 5, outsize + 5, svg_p->restart);
1758 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1759 ((double) smc->frskb) / 1024,
1760 out + 16, outsize + 16, svg_p->restart);
1762 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1763 ((double) (smc->tlskb - smc->frskb)) / 1024,
1764 out + 17, outsize + 17, svg_p->restart);
1766 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1767 ((double) smc->caskb) / 1024,
1768 out + 18, outsize + 18, svg_p->restart);
1770 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1771 ((double) smc->comkb) / 1024,
1772 out + 6, outsize + 6, svg_p->restart);
1774 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1775 ((double) smc->activekb) / 1024,
1776 out + 8, outsize + 8, svg_p->restart);
1778 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1779 ((double) smc->inactkb) / 1024,
1780 out + 9, outsize + 9, svg_p->restart);
1782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1783 ((double) smc->dirtykb) / 1024,
1784 out + 10, outsize + 10, svg_p->restart);
1786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1787 ((double) smc->anonpgkb) / 1024,
1788 out + 11, outsize + 11, svg_p->restart);
1790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1791 ((double) smc->slabkb) / 1024,
1792 out + 12, outsize + 12, svg_p->restart);
1794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1795 ((double) smc->kstackkb) / 1024,
1796 out + 13, outsize + 13, svg_p->restart);
1798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1799 ((double) smc->pgtblkb) / 1024,
1800 out + 14, outsize + 14, svg_p->restart);
1802 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1803 ((double) smc->vmusedkb) / 1024,
1804 out + 15, outsize + 15, svg_p->restart);
1806 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1809 SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
1810 out + 3, outsize + 3, svg_p->dt);
1812 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1814 (smc->tlmkb + smc->tlskb) ?
1815 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1816 out + 7, outsize + 7, svg_p->dt);
1818 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1821 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1822 out + 19, outsize + 19, svg_p->dt);
1824 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1826 (smc->tlskb - smc->frskb) ?
1827 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1828 out + 20, outsize + 20, svg_p->dt);
1831 if (action & F_END) {
1833 /* Conversion kB -> MB */
1834 for (i = 0; i < 17; i++) {
1835 *(spmin + g_fields[i]) /= 1024;
1836 *(spmax + g_fields[i]) /= 1024;
1839 if (DISPLAY_MEMORY(a->opt_flags)) {
1840 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1841 g_type1, title1, g_title1, NULL, group1,
1842 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1845 if (DISPLAY_SWAP(a->opt_flags)) {
1846 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1847 spmin + 16, spmax + 16, out + 16, outsize + 16,
1848 svg_p, record_hdr, FALSE);
1851 /* Free remaining structures */
1852 free_graphs(out, outsize, spmin, spmax);
1857 ***************************************************************************
1858 * Display kernel tables statistics in SVG.
1861 * @a Activity structure with statistics.
1862 * @curr Index in array for current sample statistics.
1863 * @action Action expected from current function.
1864 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1865 * flag indicating that a restart record has been previously
1866 * found (.@restart) and time used for the X axis origin
1868 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1869 * @record_hdr Pointer on record header of current stats sample.
1870 ***************************************************************************
1872 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1873 unsigned long long itv, struct record_header *record_hdr)
1875 struct stats_ktables
1876 *skc = (struct stats_ktables *) a->buf[curr];
1877 int group[] = {3, 1};
1878 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1879 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1880 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1882 int g_fields[] = {1, 2, 0, 3};
1883 static double *spmin, *spmax;
1885 static int *outsize;
1887 if (action & F_BEGIN) {
1889 * Allocate arrays that will contain the graphs data
1890 * and the min/max values.
1892 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1895 if (action & F_MAIN) {
1896 /* Check for min/max values */
1897 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1898 itv, spmin, spmax, g_fields);
1900 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1901 (unsigned long long) skc->dentry_stat,
1902 out, outsize, svg_p->restart);
1904 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1905 (unsigned long long) skc->file_used,
1906 out + 1, outsize + 1, svg_p->restart);
1908 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1909 (unsigned long long) skc->inode_used,
1910 out + 2, outsize + 2, svg_p->restart);
1912 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1913 (unsigned long long) skc->pty_nr,
1914 out + 3, outsize + 3, svg_p->restart);
1917 if (action & F_END) {
1918 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1919 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
1921 /* Free remaining structures */
1922 free_graphs(out, outsize, spmin, spmax);
1927 ***************************************************************************
1928 * Display queue and load statistics in SVG.
1931 * @a Activity structure with statistics.
1932 * @curr Index in array for current sample statistics.
1933 * @action Action expected from current function.
1934 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1935 * flag indicating that a restart record has been previously
1936 * found (.@restart) and time used for the X axis origin
1938 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1939 * @record_hdr Pointer on record header of current stats sample.
1940 ***************************************************************************
1942 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1943 unsigned long long itv, struct record_header *record_hdr)
1946 *sqc = (struct stats_queue *) a->buf[curr];
1947 int group[] = {2, 1, 3};
1948 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1949 char *title[] = {"Queue length", "Task list", "Load average"};
1950 char *g_title[] = {"~runq-sz", "~blocked",
1952 "ldavg-1", "ldavg-5", "ldavg-15"};
1953 int g_fields[] = {0, 1, 2, 3, 4, 5};
1954 static double *spmin, *spmax;
1956 static int *outsize;
1958 if (action & F_BEGIN) {
1960 * Allocate arrays that will contain the graphs data
1961 * and the min/max values.
1963 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1966 if (action & F_MAIN) {
1967 /* Check for min/max values */
1968 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1969 itv, spmin, spmax, g_fields);
1971 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1972 (unsigned long long) sqc->nr_running,
1973 out, outsize, svg_p->restart);
1975 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1976 (unsigned long long) sqc->procs_blocked,
1977 out + 1, outsize + 1, svg_p->restart);
1979 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1980 (unsigned long long) sqc->nr_threads,
1981 out + 2, outsize + 2, svg_p->restart);
1983 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1984 (double) sqc->load_avg_1 / 100,
1985 out + 3, outsize + 3, svg_p->restart);
1987 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1988 (double) sqc->load_avg_5 / 100,
1989 out + 4, outsize + 4, svg_p->restart);
1991 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1992 (double) sqc->load_avg_15 / 100,
1993 out + 5, outsize + 5, svg_p->restart);
1996 if (action & F_END) {
1997 /* Fix min/max values for load average */
1998 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1999 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
2000 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
2002 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2003 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2005 /* Free remaining structures */
2006 free_graphs(out, outsize, spmin, spmax);
2011 ***************************************************************************
2012 * Display disk statistics in SVG.
2015 * @a Activity structure with statistics.
2016 * @curr Index in array for current sample statistics.
2017 * @action Action expected from current function.
2018 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2019 * flag indicating that a restart record has been previously
2020 * found (.@restart) and time used for the X axis origin
2022 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2023 * @record_hdr Pointer on record header of current stats sample.
2024 ***************************************************************************
2026 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2027 unsigned long long itv, struct record_header *record_hdr)
2029 struct stats_disk *sdc, *sdp, sdpzero;
2030 struct ext_disk_stats xds;
2031 int group[] = {1, 2, 2, 2, 1};
2032 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2033 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2034 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
2035 "Disk statistics (3)", "Disk statistics (4)",
2036 "Disk statistics (5)"};
2037 char *g_title[] = {"tps",
2039 "areq-sz", "aqu-sz",
2042 int g_fields[] = {0, 1, 2};
2043 unsigned int local_types_nr[] = {1, 0, 0};
2044 static double *spmin, *spmax;
2046 static int *outsize;
2047 char *item_name, *persist_dev_name;
2048 double rkB, wkB, aqusz;
2049 int i, j, k, pos, restart, *unregistered;
2051 if (action & F_BEGIN) {
2053 * Allocate arrays (#0..7) that will contain the graphs data
2054 * and the min/max values.
2055 * Also allocate one additional array (#8) for each disk device:
2056 * spmax + 8 will contain the device major number,
2057 * spmin + 8 will contain the device minor number,
2058 * outsize + 8 will contain a positive value (TRUE) if the device
2059 * has either still not been registered, or has been unregistered.
2061 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2064 if (action & F_MAIN) {
2065 memset(&sdpzero, 0, STATS_DISK_SIZE);
2066 restart = svg_p->restart;
2068 * Mark previously registered devices as now
2069 * possibly unregistered for all graphs.
2071 for (k = 0; k < svg_p->nr_max; k++) {
2072 unregistered = outsize + k * 9 + 8;
2073 if (*unregistered == FALSE) {
2074 *unregistered = MAYBE;
2078 /* For each device structure */
2079 for (i = 0; i < a->nr[curr]; i++) {
2080 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2082 /* Look for corresponding graph */
2083 for (k = 0; k < svg_p->nr_max; k++) {
2084 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2085 (sdc->minor == *(spmin + k * 9 + 8)))
2089 if (k == svg_p->nr_max) {
2090 /* Graph not found: Look for first free entry */
2091 for (k = 0; k < svg_p->nr_max; k++) {
2092 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2095 if (k == svg_p->nr_max) {
2096 /* No free graph entry: Extend all buffers */
2097 reallocate_all_graph_lines(svg_p->nr_max,
2098 &out, &outsize, &spmin, &spmax);
2103 unregistered = outsize + pos + 8;
2105 j = check_disk_reg(a, curr, !curr, i);
2107 /* This is a newly registered interface. Previous stats are zero */
2111 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2115 * If current device was marked as previously unregistered,
2116 * then set restart variable to TRUE so that the graph will be
2117 * discontinuous, and mark it as now registered.
2119 if (*unregistered == TRUE) {
2122 *unregistered = FALSE;
2124 if (*(spmax + pos + 8) == -DBL_MAX) {
2125 /* Save device major and minor numbers (if not already done) */
2126 *(spmax + pos + 8) = sdc->major;
2127 *(spmin + pos + 8) = sdc->minor;
2130 /* Check for min/max values */
2131 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2132 itv, spmin + pos, spmax + pos, g_fields);
2134 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2135 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2136 if (rkB < *(spmin + pos + 1)) {
2137 *(spmin + pos + 1) = rkB;
2139 if (rkB > *(spmax + pos + 1)) {
2140 *(spmax + pos + 1) = rkB;
2142 if (wkB < *(spmin + pos + 2)) {
2143 *(spmin + pos + 2) = wkB;
2145 if (wkB > *(spmax + pos + 2)) {
2146 *(spmax + pos + 2) = wkB;
2149 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2150 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2151 *(spmin + pos + 3) = xds.arqsz / 2;
2153 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2154 *(spmax + pos + 3) = xds.arqsz / 2;
2156 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2157 if (aqusz < *(spmin + pos + 4)) {
2158 *(spmin + pos + 4) = aqusz;
2160 if (aqusz > *(spmax + pos + 4)) {
2161 *(spmax + pos + 4) = aqusz;
2163 if (xds.await < *(spmin + pos + 5)) {
2164 *(spmin + pos + 5) = xds.await;
2166 if (xds.await > *(spmax + pos + 5)) {
2167 *(spmax + pos + 5) = xds.await;
2169 if (xds.svctm < *(spmin + pos + 6)) {
2170 *(spmin + pos + 6) = xds.svctm;
2172 if (xds.svctm > *(spmax + pos + 6)) {
2173 *(spmax + pos + 6) = xds.svctm;
2175 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2176 *(spmin + pos + 7) = xds.util / 10.0;
2178 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2179 *(spmax + pos + 7) = xds.util / 10.0;
2183 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2184 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2185 out + pos, outsize + pos, restart);
2187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2188 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2189 out + pos + 1, outsize + pos + 1, restart);
2191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2192 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2193 out + pos + 2, outsize + pos + 2, restart);
2195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2197 out + pos + 3, outsize + pos + 3, restart);
2199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2201 out + pos + 4, outsize + pos + 4, restart);
2203 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2205 out + pos + 5, outsize + pos + 5, restart);
2207 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2209 out + pos + 6, outsize + pos + 6, restart);
2211 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2212 0.0, xds.util / 10.0,
2213 out + pos + 7, outsize + pos + 7, svg_p->dt);
2216 /* Mark devices not seen here as now unregistered */
2217 for (k = 0; k < svg_p->nr_max; k++) {
2218 unregistered = outsize + k * 9 + 8;
2219 if (*unregistered != FALSE) {
2220 *unregistered = TRUE;
2225 if (action & F_END) {
2226 for (i = 0; i < svg_p->nr_max; i++) {
2227 /* Check if there is something to display */
2233 persist_dev_name = NULL;
2235 if (DISPLAY_PERSIST_NAME_S(flags)) {
2236 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2240 if (persist_dev_name) {
2241 item_name = persist_dev_name;
2244 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2245 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2249 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2250 USE_PRETTY_OPTION(flags));
2254 draw_activity_graphs(a->g_nr, g_type,
2255 title, g_title, item_name, group,
2256 spmin + pos, spmax + pos, out + pos, outsize + pos,
2257 svg_p, record_hdr, FALSE);
2260 /* Free remaining structures */
2261 free_graphs(out, outsize, spmin, spmax);
2266 ***************************************************************************
2267 * Display network interfaces statistics in SVG.
2270 * @a Activity structure with statistics.
2271 * @curr Index in array for current sample statistics.
2272 * @action Action expected from current function.
2273 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2274 * flag indicating that a restart record has been previously
2275 * found (.@restart) and time used for the X axis origin
2277 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2278 * @record_hdr Pointer on record header of current stats sample.
2279 ***************************************************************************
2281 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2282 unsigned long long itv, struct record_header *record_hdr)
2284 struct stats_net_dev *sndc, *sndp, sndzero;
2285 int group[] = {2, 2, 3, 1};
2286 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2288 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2289 "Network statistics (3)", "Network statistics (4)"};
2290 char *g_title[] = {"rxpck/s", "txpck/s",
2292 "rxcmp/s", "txcmp/s", "rxmcst/s",
2294 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2295 unsigned int local_types_nr[] = {7, 0, 0};
2296 static double *spmin, *spmax;
2298 static int *outsize;
2300 double rxkb, txkb, ifutil;
2301 int i, j, k, pos, restart, *unregistered;
2303 if (action & F_BEGIN) {
2305 * Allocate arrays (#0..7) that will contain the graphs data
2306 * and the min/max values.
2307 * Also allocate one additional array (#8) for each interface:
2308 * out + 8 will contain the interface name,
2309 * outsize + 8 will contain a positive value (TRUE) if the interface
2310 * has either still not been registered, or has been unregistered.
2312 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2315 if (action & F_MAIN) {
2316 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2317 restart = svg_p->restart;
2319 * Mark previously registered interfaces as now
2320 * possibly unregistered for all graphs.
2322 for (k = 0; k < svg_p->nr_max; k++) {
2323 unregistered = outsize + k * 9 + 8;
2324 if (*unregistered == FALSE) {
2325 *unregistered = MAYBE;
2329 /* For each network interfaces structure */
2330 for (i = 0; i < a->nr[curr]; i++) {
2331 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2333 /* Look for corresponding graph */
2334 for (k = 0; k < svg_p->nr_max; k++) {
2335 item_name = *(out + k * 9 + 8);
2336 if (!strcmp(sndc->interface, item_name))
2340 if (k == svg_p->nr_max) {
2341 /* Graph not found: Look for first free entry */
2342 for (k = 0; k < svg_p->nr_max; k++) {
2343 item_name = *(out + k * 9 + 8);
2344 if (!strcmp(item_name, ""))
2347 if (k == svg_p->nr_max) {
2348 /* No free graph entry: Extend all buffers */
2349 reallocate_all_graph_lines(svg_p->nr_max,
2350 &out, &outsize, &spmin, &spmax);
2356 unregistered = outsize + pos + 8;
2358 j = check_net_dev_reg(a, curr, !curr, i);
2360 /* This is a newly registered interface. Previous stats are zero */
2364 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2368 * If current interface was marked as previously unregistered,
2369 * then set restart variable to TRUE so that the graph will be
2370 * discontinuous, and mark it as now registered.
2372 if (*unregistered == TRUE) {
2375 *unregistered = FALSE;
2377 if (!item_name[0]) {
2378 /* Save network interface name (if not already done) */
2379 strncpy(item_name, sndc->interface, CHUNKSIZE);
2380 item_name[CHUNKSIZE - 1] = '\0';
2383 /* Check for min/max values */
2384 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2385 itv, spmin + pos, spmax + pos, g_fields);
2387 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2388 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2389 ifutil = compute_ifutil(sndc, rxkb, txkb);
2390 if (ifutil < *(spmin + pos + 7)) {
2391 *(spmin + pos + 7) = ifutil;
2393 if (ifutil > *(spmax + pos + 7)) {
2394 *(spmax + pos + 7) = ifutil;
2398 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2399 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2400 out + pos, outsize + pos, restart);
2402 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2403 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2404 out + pos + 1, outsize + pos + 1, restart);
2406 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2408 out + pos + 2, outsize + pos + 2, restart);
2410 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2412 out + pos + 3, outsize + pos + 3, restart);
2414 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2415 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2416 out + pos + 4, outsize + pos + 4, restart);
2418 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2419 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2420 out + pos + 5, outsize + pos + 5, restart);
2422 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2423 S_VALUE(sndp->multicast, sndc->multicast, itv),
2424 out + pos + 6, outsize + pos + 6, restart);
2426 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2428 out + pos + 7, outsize + pos + 7, svg_p->dt);
2431 /* Mark interfaces not seen here as now unregistered */
2432 for (k = 0; k < svg_p->nr_max; k++) {
2433 unregistered = outsize + k * 9 + 8;
2434 if (*unregistered != FALSE) {
2435 *unregistered = TRUE;
2440 if (action & F_END) {
2441 for (i = 0; i < svg_p->nr_max; i++) {
2443 * Check if there is something to display.
2444 * Don't test sndc->interface because maybe the network
2445 * interface has been registered later.
2451 /* Recalculate min and max values in kB, not in B */
2452 *(spmin + pos + 2) /= 1024;
2453 *(spmax + pos + 2) /= 1024;
2454 *(spmin + pos + 3) /= 1024;
2455 *(spmax + pos + 3) /= 1024;
2457 item_name = *(out + pos + 8);
2458 draw_activity_graphs(a->g_nr, g_type,
2459 title, g_title, item_name, group,
2460 spmin + pos, spmax + pos, out + pos, outsize + pos,
2461 svg_p, record_hdr, FALSE);
2464 /* Free remaining structures */
2465 free_graphs(out, outsize, spmin, spmax);
2470 ***************************************************************************
2471 * Display network interface errors statistics in SVG.
2474 * @a Activity structure with statistics.
2475 * @curr Index in array for current sample statistics.
2476 * @action Action expected from current function.
2477 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2478 * flag indicating that a restart record has been previously
2479 * found (.@restart) and time used for the X axis origin
2481 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2482 * @record_hdr Pointer on record header of current stats sample.
2483 ***************************************************************************
2485 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2486 unsigned long long itv, struct record_header *record_hdr)
2488 struct stats_net_edev *snedc, *snedp, snedzero;
2489 int group[] = {2, 2, 2, 3};
2490 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2492 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2493 "Network errors statistics (3)", "Network errors statistics (4)"};
2494 char *g_title[] = {"rxerr/s", "txerr/s",
2495 "rxdrop/s", "txdrop/s",
2496 "rxfifo/s", "txfifo/s",
2497 "coll/s", "txcarr/s", "rxfram/s"};
2498 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2499 static double *spmin, *spmax;
2501 static int *outsize;
2503 int i, j, k, pos, restart, *unregistered;
2505 if (action & F_BEGIN) {
2507 * Allocate arrays (#0..8) that will contain the graphs data
2508 * and the min/max values.
2509 * Also allocate one additional array (#9) for each interface:
2510 * out + 9 will contain the interface name,
2511 * outsize + 9 will contain a positive value (TRUE) if the interface
2512 * has either still not been registered, or has been unregistered.
2514 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
2517 if (action & F_MAIN) {
2518 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2519 restart = svg_p->restart;
2521 * Mark previously registered interfaces as now
2522 * possibly unregistered for all graphs.
2524 for (k = 0; k < svg_p->nr_max; k++) {
2525 unregistered = outsize + k * 10 + 9;
2526 if (*unregistered == FALSE) {
2527 *unregistered = MAYBE;
2531 /* For each network interfaces structure */
2532 for (i = 0; i < a->nr[curr]; i++) {
2533 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2534 if (!strcmp(snedc->interface, ""))
2535 /* Empty structure: This is the end of the list */
2538 /* Look for corresponding graph */
2539 for (k = 0; k < svg_p->nr_max; k++) {
2540 item_name = *(out + k * 10 + 9);
2541 if (!strcmp(snedc->interface, item_name))
2545 if (k == svg_p->nr_max) {
2546 /* Graph not found: Look for first free entry */
2547 for (k = 0; k < svg_p->nr_max; k++) {
2548 item_name = *(out + k * 10 + 9);
2549 if (!strcmp(item_name, ""))
2552 if (k == svg_p->nr_max) {
2553 /* No free graph entry: Extend all buffers */
2554 reallocate_all_graph_lines(svg_p->nr_max,
2555 &out, &outsize, &spmin, &spmax);
2561 unregistered = outsize + pos + 9;
2563 j = check_net_edev_reg(a, curr, !curr, i);
2565 /* This is a newly registered interface. Previous stats are zero */
2569 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2573 * If current interface was marked as previously unregistered,
2574 * then set restart variable to TRUE so that the graph will be
2575 * discontinuous, and mark it as now registered.
2577 if (*unregistered == TRUE) {
2580 *unregistered = FALSE;
2582 if (!item_name[0]) {
2583 /* Save network interface name (if not already done) */
2584 strncpy(item_name, snedc->interface, CHUNKSIZE);
2585 item_name[CHUNKSIZE - 1] = '\0';
2588 /* Check for min/max values */
2589 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2590 itv, spmin + pos, spmax + pos, g_fields);
2593 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2594 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2595 out + pos, outsize + pos, restart);
2597 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2598 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2599 out + pos + 1, outsize + pos + 1, restart);
2601 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2602 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2603 out + pos + 2, outsize + pos + 2, restart);
2605 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2606 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2607 out + pos + 3, outsize + pos + 3, restart);
2609 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2610 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2611 out + pos + 4, outsize + pos + 4, restart);
2613 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2614 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2615 out + pos + 5, outsize + pos + 5, restart);
2617 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2618 S_VALUE(snedp->collisions, snedc->collisions, itv),
2619 out + pos + 6, outsize + pos + 6, restart);
2621 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2622 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2623 out + pos + 7, outsize + pos + 7, restart);
2625 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2626 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2627 out + pos + 8, outsize + pos + 8, restart);
2630 /* Mark interfaces not seen here as now unregistered */
2631 for (k = 0; k < svg_p->nr_max; k++) {
2632 unregistered = outsize + k * 10 + 9;
2633 if (*unregistered != FALSE) {
2634 *unregistered = TRUE;
2639 if (action & F_END) {
2640 for (i = 0; i < svg_p->nr_max; i++) {
2642 * Check if there is something to display.
2643 * Don't test snedc->interface because maybe the network
2644 * interface has been registered later.
2650 item_name = *(out + pos + 9);
2651 draw_activity_graphs(a->g_nr, g_type,
2652 title, g_title, item_name, group,
2653 spmin + pos, spmax + pos, out + pos, outsize + pos,
2654 svg_p, record_hdr, FALSE);
2657 /* Free remaining structures */
2658 free_graphs(out, outsize, spmin, spmax);
2663 ***************************************************************************
2664 * Display NFS client statistics in SVG.
2667 * @a Activity structure with statistics.
2668 * @curr Index in array for current sample statistics.
2669 * @action Action expected from current function.
2670 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2671 * flag indicating that a restart record has been previously
2672 * found (.@restart) and time used for the X axis origin
2674 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2675 * @record_hdr Pointer on record header of current stats sample.
2676 ***************************************************************************
2678 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2679 unsigned long long itv, struct record_header *record_hdr)
2681 struct stats_net_nfs
2682 *snnc = (struct stats_net_nfs *) a->buf[curr],
2683 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2684 int group[] = {2, 2, 2};
2685 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2686 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2687 "NFS client statistics (3)"};
2688 char *g_title[] = {"call/s", "retrans/s",
2689 "read/s", "write/s",
2690 "access/s", "getatt/s"};
2691 int g_fields[] = {0, 1, 2, 3, 4, 5};
2692 static double *spmin, *spmax;
2694 static int *outsize;
2696 if (action & F_BEGIN) {
2698 * Allocate arrays that will contain the graphs data
2699 * and the min/max values.
2701 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2704 if (action & F_MAIN) {
2705 /* Check for min/max values */
2706 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2707 itv, spmin, spmax, g_fields);
2710 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2711 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2712 out, outsize, svg_p->restart);
2714 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2715 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2716 out + 1, outsize + 1, svg_p->restart);
2718 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2719 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2720 out + 2, outsize + 2, svg_p->restart);
2722 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2723 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2724 out + 3, outsize + 3, svg_p->restart);
2726 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2727 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2728 out + 4, outsize + 4, svg_p->restart);
2730 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2731 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2732 out + 5, outsize + 5, svg_p->restart);
2735 if (action & F_END) {
2736 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2737 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2739 /* Free remaining structures */
2740 free_graphs(out, outsize, spmin, spmax);
2745 ***************************************************************************
2746 * Display NFS server statistics in SVG.
2749 * @a Activity structure with statistics.
2750 * @curr Index in array for current sample statistics.
2751 * @action Action expected from current function.
2752 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2753 * flag indicating that a restart record has been previously
2754 * found (.@restart) and time used for the X axis origin
2756 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2757 * @record_hdr Pointer on record header of current stats sample.
2758 ***************************************************************************
2760 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2761 unsigned long long itv, struct record_header *record_hdr)
2763 struct stats_net_nfsd
2764 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2765 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2766 int group[] = {2, 3, 2, 2, 2};
2767 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2768 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2769 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2770 "NFS server statistics (3)", "NFS server statistics (4)",
2771 "NFS server statistics (5)"};
2772 char *g_title[] = {"scall/s", "badcall/s",
2773 "packet/s", "udp/s", "tcp/s",
2775 "sread/s", "swrite/s",
2776 "saccess/s", "sgetatt/s"};
2777 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2778 static double *spmin, *spmax;
2780 static int *outsize;
2782 if (action & F_BEGIN) {
2784 * Allocate arrays that will contain the graphs data
2785 * and the min/max values.
2787 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2790 if (action & F_MAIN) {
2791 /* Check for min/max values */
2792 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2793 itv, spmin, spmax, g_fields);
2796 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2797 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2798 out, outsize, svg_p->restart);
2800 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2801 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2802 out + 1, outsize + 1, svg_p->restart);
2804 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2805 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2806 out + 2, outsize + 2, svg_p->restart);
2808 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2809 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2810 out + 3, outsize + 3, svg_p->restart);
2812 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2813 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2814 out + 4, outsize + 4, svg_p->restart);
2816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2817 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2818 out + 5, outsize + 5, svg_p->restart);
2820 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2821 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2822 out + 6, outsize + 6, svg_p->restart);
2824 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2825 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2826 out + 7, outsize + 7, svg_p->restart);
2828 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2829 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2830 out + 8, outsize + 8, svg_p->restart);
2832 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2833 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2834 out + 9, outsize + 9, svg_p->restart);
2836 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2837 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2838 out + 10, outsize + 10, svg_p->restart);
2841 if (action & F_END) {
2842 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2843 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2845 /* Free remaining structures */
2846 free_graphs(out, outsize, spmin, spmax);
2851 ***************************************************************************
2852 * Display network socket statistics in SVG.
2855 * @a Activity structure with statistics.
2856 * @curr Index in array for current sample statistics.
2857 * @action Action expected from current function.
2858 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2859 * flag indicating that a restart record has been previously
2860 * found (.@restart) and time used for the X axis origin
2862 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2863 * @record_hdr Pointer on record header of current stats sample.
2864 ***************************************************************************
2866 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2867 unsigned long long itv, struct record_header *record_hdr)
2869 struct stats_net_sock
2870 *snsc = (struct stats_net_sock *) a->buf[curr];
2871 int group[] = {1, 5};
2872 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2873 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2874 char *g_title[] = {"~totsck",
2875 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2876 int g_fields[] = {0, 1, 5, 2, 3, 4};
2877 static double *spmin, *spmax;
2879 static int *outsize;
2881 if (action & F_BEGIN) {
2883 * Allocate arrays that will contain the graphs data
2884 * and the min/max values.
2886 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2889 if (action & F_MAIN) {
2890 /* Check for min/max values */
2891 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2892 itv, spmin, spmax, g_fields);
2894 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2895 (unsigned long long) snsc->sock_inuse,
2896 out, outsize, svg_p->restart);
2898 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2899 (unsigned long long) snsc->tcp_inuse,
2900 out + 1, outsize + 1, svg_p->restart);
2902 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2903 (unsigned long long) snsc->udp_inuse,
2904 out + 2, outsize + 2, svg_p->restart);
2906 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2907 (unsigned long long) snsc->raw_inuse,
2908 out + 3, outsize + 3, svg_p->restart);
2910 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2911 (unsigned long long) snsc->frag_inuse,
2912 out + 4, outsize + 4, svg_p->restart);
2914 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2915 (unsigned long long) snsc->tcp_tw,
2916 out + 5, outsize + 5, svg_p->restart);
2919 if (action & F_END) {
2920 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2921 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
2923 /* Free remaining structures */
2924 free_graphs(out, outsize, spmin, spmax);
2929 ***************************************************************************
2930 * Display IPv4 network statistics in SVG.
2933 * @a Activity structure with statistics.
2934 * @curr Index in array for current sample statistics.
2935 * @action Action expected from current function.
2936 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2937 * flag indicating that a restart record has been previously
2938 * found (.@restart) and time used for the X axis origin
2940 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2941 * @record_hdr Pointer on record header of current stats sample.
2942 ***************************************************************************
2944 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2945 unsigned long long itv, struct record_header *record_hdr)
2948 *snic = (struct stats_net_ip *) a->buf[curr],
2949 *snip = (struct stats_net_ip *) a->buf[!curr];
2950 int group[] = {4, 2, 2};
2951 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2952 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2953 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2954 "asmrq/s", "asmok/s",
2955 "fragok/s", "fragcrt/s"};
2956 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2957 static double *spmin, *spmax;
2959 static int *outsize;
2961 if (action & F_BEGIN) {
2963 * Allocate arrays that will contain the graphs data
2964 * and the min/max values.
2966 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2969 if (action & F_MAIN) {
2970 /* Check for min/max values */
2971 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2972 itv, spmin, spmax, g_fields);
2975 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2976 S_VALUE(snip->InReceives, snic->InReceives, itv),
2977 out, outsize, svg_p->restart);
2979 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2980 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2981 out + 1, outsize + 1, svg_p->restart);
2983 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2984 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2985 out + 2, outsize + 2, svg_p->restart);
2987 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2988 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2989 out + 3, outsize + 3, svg_p->restart);
2991 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2992 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2993 out + 4, outsize + 4, svg_p->restart);
2995 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2996 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2997 out + 5, outsize + 5, svg_p->restart);
2999 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3000 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
3001 out + 6, outsize + 6, svg_p->restart);
3003 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3004 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3005 out + 7, outsize + 7, svg_p->restart);
3008 if (action & F_END) {
3009 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3010 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3012 /* Free remaining structures */
3013 free_graphs(out, outsize, spmin, spmax);
3018 ***************************************************************************
3019 * Display IPv4 network errors statistics in SVG.
3022 * @a Activity structure with statistics.
3023 * @curr Index in array for current sample statistics.
3024 * @action Action expected from current function.
3025 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3026 * flag indicating that a restart record has been previously
3027 * found (.@restart) and time used for the X axis origin
3029 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3030 * @record_hdr Pointer on record header of current stats sample.
3031 ***************************************************************************
3033 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3034 unsigned long long itv, struct record_header *record_hdr)
3036 struct stats_net_eip
3037 *sneic = (struct stats_net_eip *) a->buf[curr],
3038 *sneip = (struct stats_net_eip *) a->buf[!curr];
3039 int group[] = {3, 2, 3};
3040 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3041 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
3042 "IPv4 network errors statistics (3)"};
3043 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3044 "idisc/s", "odisc/s",
3045 "onort/s", "asmf/s", "fragf/s"};
3046 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3047 static double *spmin, *spmax;
3049 static int *outsize;
3051 if (action & F_BEGIN) {
3053 * Allocate arrays that will contain the graphs data
3054 * and the min/max values.
3056 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3059 if (action & F_MAIN) {
3060 /* Check for min/max values */
3061 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3062 itv, spmin, spmax, g_fields);
3065 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3066 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3067 out, outsize, svg_p->restart);
3069 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3070 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3071 out + 1, outsize + 1, svg_p->restart);
3073 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3074 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3075 out + 2, outsize + 2, svg_p->restart);
3077 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3078 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3079 out + 3, outsize + 3, svg_p->restart);
3081 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3082 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3083 out + 4, outsize + 4, svg_p->restart);
3085 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3086 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3087 out + 5, outsize + 5, svg_p->restart);
3089 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3090 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3091 out + 6, outsize + 6, svg_p->restart);
3093 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3094 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3095 out + 7, outsize + 7, svg_p->restart);
3098 if (action & F_END) {
3099 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3100 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3102 /* Free remaining structures */
3103 free_graphs(out, outsize, spmin, spmax);
3108 ***************************************************************************
3109 * Display ICMPv4 network statistics in SVG.
3112 * @a Activity structure with statistics.
3113 * @curr Index in array for current sample statistics.
3114 * @action Action expected from current function.
3115 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3116 * flag indicating that a restart record has been previously
3117 * found (.@restart) and time used for the X axis origin
3119 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3120 * @record_hdr Pointer on record header of current stats sample.
3121 ***************************************************************************
3123 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3124 unsigned long long itv, struct record_header *record_hdr)
3126 struct stats_net_icmp
3127 *snic = (struct stats_net_icmp *) a->buf[curr],
3128 *snip = (struct stats_net_icmp *) a->buf[!curr];
3129 int group[] = {2, 4, 4, 4};
3130 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3132 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3133 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3134 char *g_title[] = {"imsg/s", "omsg/s",
3135 "iech/s", "iechr/s", "oech/s", "oechr/s",
3136 "itm/s", "itmr/s", "otm/s", "otmr/s",
3137 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3138 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3139 static double *spmin, *spmax;
3141 static int *outsize;
3143 if (action & F_BEGIN) {
3145 * Allocate arrays that will contain the graphs data
3146 * and the min/max values.
3148 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3151 if (action & F_MAIN) {
3152 /* Check for min/max values */
3153 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3154 itv, spmin, spmax, g_fields);
3157 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3158 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3159 out, outsize, svg_p->restart);
3161 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3162 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3163 out + 1, outsize + 1, svg_p->restart);
3165 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3166 S_VALUE(snip->InEchos, snic->InEchos, itv),
3167 out + 2, outsize + 2, svg_p->restart);
3169 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3170 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3171 out + 3, outsize + 3, svg_p->restart);
3173 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3174 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3175 out + 4, outsize + 4, svg_p->restart);
3177 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3178 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3179 out + 5, outsize + 5, svg_p->restart);
3181 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3182 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3183 out + 6, outsize + 6, svg_p->restart);
3185 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3186 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3187 out + 7, outsize + 7, svg_p->restart);
3189 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3190 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3191 out + 8, outsize + 8, svg_p->restart);
3193 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3194 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3195 out + 9, outsize + 9, svg_p->restart);
3197 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3198 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3199 out + 10, outsize + 10, svg_p->restart);
3201 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3202 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3203 out + 11, outsize + 11, svg_p->restart);
3205 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3206 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3207 out + 12, outsize + 12, svg_p->restart);
3209 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3210 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3211 out + 13, outsize + 13, svg_p->restart);
3214 if (action & F_END) {
3215 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3216 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3218 /* Free remaining structures */
3219 free_graphs(out, outsize, spmin, spmax);
3224 ***************************************************************************
3225 * Display ICMPv4 network errors statistics in SVG.
3228 * @a Activity structure with statistics.
3229 * @curr Index in array for current sample statistics.
3230 * @action Action expected from current function.
3231 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3232 * flag indicating that a restart record has been previously
3233 * found (.@restart) and time used for the X axis origin
3235 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3236 * @record_hdr Pointer on record header of current stats sample.
3237 ***************************************************************************
3239 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3240 unsigned long long itv, struct record_header *record_hdr)
3242 struct stats_net_eicmp
3243 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3244 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3245 int group[] = {2, 2, 2, 2, 2, 2};
3246 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3247 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3248 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3249 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3250 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3251 char *g_title[] = {"ierr/s", "oerr/s",
3252 "idstunr/s", "odstunr/s",
3253 "itmex/s", "otmex/s",
3254 "iparmpb/s", "oparmpb/s",
3255 "isrcq/s", "osrcq/s",
3256 "iredir/s", "oredir/s"};
3257 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3258 static double *spmin, *spmax;
3260 static int *outsize;
3262 if (action & F_BEGIN) {
3264 * Allocate arrays that will contain the graphs data
3265 * and the min/max values.
3267 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3270 if (action & F_MAIN) {
3271 /* Check for min/max values */
3272 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3273 itv, spmin, spmax, g_fields);
3276 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3277 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3278 out, outsize, svg_p->restart);
3280 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3281 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3282 out + 1, outsize + 1, svg_p->restart);
3284 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3285 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3286 out + 2, outsize + 2, svg_p->restart);
3288 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3289 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3290 out + 3, outsize + 3, svg_p->restart);
3292 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3293 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3294 out + 4, outsize + 4, svg_p->restart);
3296 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3297 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3298 out + 5, outsize + 5, svg_p->restart);
3300 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3301 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3302 out + 6, outsize + 6, svg_p->restart);
3304 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3305 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3306 out + 7, outsize + 7, svg_p->restart);
3308 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3309 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3310 out + 8, outsize + 8, svg_p->restart);
3312 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3313 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3314 out + 9, outsize + 9, svg_p->restart);
3316 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3317 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3318 out + 10, outsize + 10, svg_p->restart);
3320 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3321 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3322 out + 11, outsize + 11, svg_p->restart);
3325 if (action & F_END) {
3326 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3327 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3329 /* Free remaining structures */
3330 free_graphs(out, outsize, spmin, spmax);
3335 ***************************************************************************
3336 * Display TCPv4 network statistics in SVG.
3339 * @a Activity structure with statistics.
3340 * @curr Index in array for current sample statistics.
3341 * @action Action expected from current function.
3342 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3343 * flag indicating that a restart record has been previously
3344 * found (.@restart) and time used for the X axis origin
3346 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3347 * @record_hdr Pointer on record header of current stats sample.
3348 ***************************************************************************
3350 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3351 unsigned long long itv, struct record_header *record_hdr)
3353 struct stats_net_tcp
3354 *sntc = (struct stats_net_tcp *) a->buf[curr],
3355 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3356 int group[] = {2, 2};
3357 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3358 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3359 char *g_title[] = {"active/s", "passive/s",
3360 "iseg/s", "oseg/s"};
3361 int g_fields[] = {0, 1, 2, 3};
3362 static double *spmin, *spmax;
3364 static int *outsize;
3366 if (action & F_BEGIN) {
3368 * Allocate arrays that will contain the graphs data
3369 * and the min/max values.
3371 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3374 if (action & F_MAIN) {
3375 /* Check for min/max values */
3376 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3377 itv, spmin, spmax, g_fields);
3380 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3381 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3382 out, outsize, svg_p->restart);
3384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3385 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3386 out + 1, outsize + 1, svg_p->restart);
3388 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3389 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3390 out + 2, outsize + 2, svg_p->restart);
3392 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3393 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3394 out + 3, outsize + 3, svg_p->restart);
3397 if (action & F_END) {
3398 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3399 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3401 /* Free remaining structures */
3402 free_graphs(out, outsize, spmin, spmax);
3407 ***************************************************************************
3408 * Display TCPv4 network errors statistics in SVG.
3411 * @a Activity structure with statistics.
3412 * @curr Index in array for current sample statistics.
3413 * @action Action expected from current function.
3414 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3415 * flag indicating that a restart record has been previously
3416 * found (.@restart) and time used for the X axis origin
3418 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3419 * @record_hdr Pointer on record header of current stats sample.
3420 ***************************************************************************
3422 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3423 unsigned long long itv, struct record_header *record_hdr)
3425 struct stats_net_etcp
3426 *snetc = (struct stats_net_etcp *) a->buf[curr],
3427 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3428 int group[] = {2, 3};
3429 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3430 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3431 char *g_title[] = {"atmptf/s", "estres/s",
3432 "retrans/s", "isegerr/s", "orsts/s"};
3433 int g_fields[] = {0, 1, 2, 3, 4};
3434 static double *spmin, *spmax;
3436 static int *outsize;
3438 if (action & F_BEGIN) {
3440 * Allocate arrays that will contain the graphs data
3441 * and the min/max values.
3443 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3446 if (action & F_MAIN) {
3447 /* Check for min/max values */
3448 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3449 itv, spmin, spmax, g_fields);
3452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3453 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3454 out, outsize, svg_p->restart);
3456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3457 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3458 out + 1, outsize + 1, svg_p->restart);
3460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3461 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3462 out + 2, outsize + 2, svg_p->restart);
3464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3465 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3466 out + 3, outsize + 3, svg_p->restart);
3468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3469 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3470 out + 4, outsize + 4, svg_p->restart);
3473 if (action & F_END) {
3474 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3475 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3477 /* Free remaining structures */
3478 free_graphs(out, outsize, spmin, spmax);
3483 ***************************************************************************
3484 * Display UDPv4 network statistics in SVG.
3487 * @a Activity structure with statistics.
3488 * @curr Index in array for current sample statistics.
3489 * @action Action expected from current function.
3490 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3491 * flag indicating that a restart record has been previously
3492 * found (.@restart) and time used for the X axis origin
3494 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3495 * @record_hdr Pointer on record header of current stats sample.
3496 ***************************************************************************
3498 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3499 unsigned long long itv, struct record_header *record_hdr)
3501 struct stats_net_udp
3502 *snuc = (struct stats_net_udp *) a->buf[curr],
3503 *snup = (struct stats_net_udp *) a->buf[!curr];
3504 int group[] = {2, 2};
3505 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3506 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3507 char *g_title[] = {"idgm/s", "odgm/s",
3508 "noport/s", "idgmerr/s"};
3509 int g_fields[] = {0, 1, 2, 3};
3510 static double *spmin, *spmax;
3512 static int *outsize;
3514 if (action & F_BEGIN) {
3516 * Allocate arrays that will contain the graphs data
3517 * and the min/max values.
3519 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3522 if (action & F_MAIN) {
3523 /* Check for min/max values */
3524 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3525 itv, spmin, spmax, g_fields);
3528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3529 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3530 out, outsize, svg_p->restart);
3532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3533 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3534 out + 1, outsize + 1, svg_p->restart);
3536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3537 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3538 out + 2, outsize + 2, svg_p->restart);
3540 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3541 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3542 out + 3, outsize + 3, svg_p->restart);
3545 if (action & F_END) {
3546 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3547 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3549 /* Free remaining structures */
3550 free_graphs(out, outsize, spmin, spmax);
3555 ***************************************************************************
3556 * Display IPV6 network socket statistics in SVG.
3559 * @a Activity structure with statistics.
3560 * @curr Index in array for current sample statistics.
3561 * @action Action expected from current function.
3562 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3563 * flag indicating that a restart record has been previously
3564 * found (.@restart) and time used for the X axis origin
3566 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3567 * @record_hdr Pointer on record header of current stats sample.
3568 ***************************************************************************
3570 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3571 unsigned long long itv, struct record_header *record_hdr)
3573 struct stats_net_sock6
3574 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3576 int g_type[] = {SVG_LINE_GRAPH};
3577 char *title[] = {"IPv6 network sockets"};
3578 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3579 int g_fields[] = {0, 1, 2, 3};
3580 static double *spmin, *spmax;
3582 static int *outsize;
3584 if (action & F_BEGIN) {
3586 * Allocate arrays that will contain the graphs data
3587 * and the min/max values.
3589 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3592 if (action & F_MAIN) {
3593 /* Check for min/max values */
3594 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3595 itv, spmin, spmax, g_fields);
3597 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3598 (unsigned long long) snsc->tcp6_inuse,
3599 out, outsize, svg_p->restart);
3601 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3602 (unsigned long long) snsc->udp6_inuse,
3603 out + 1, outsize + 1, svg_p->restart);
3605 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3606 (unsigned long long) snsc->raw6_inuse,
3607 out + 2, outsize + 2, svg_p->restart);
3609 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3610 (unsigned long long) snsc->frag6_inuse,
3611 out + 3, outsize + 3, svg_p->restart);
3614 if (action & F_END) {
3615 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3616 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3618 /* Free remaining structures */
3619 free_graphs(out, outsize, spmin, spmax);
3624 ***************************************************************************
3625 * Display IPv6 network statistics in SVG.
3628 * @a Activity structure with statistics.
3629 * @curr Index in array for current sample statistics.
3630 * @action Action expected from current function.
3631 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3632 * flag indicating that a restart record has been previously
3633 * found (.@restart) and time used for the X axis origin
3635 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3636 * @record_hdr Pointer on record header of current stats sample.
3637 ***************************************************************************
3639 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3640 unsigned long long itv, struct record_header *record_hdr)
3642 struct stats_net_ip6
3643 *snic = (struct stats_net_ip6 *) a->buf[curr],
3644 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3645 int group[] = {4, 2, 2, 2};
3646 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3648 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3649 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3650 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3651 "asmrq6/s", "asmok6/s",
3652 "imcpck6/s", "omcpck6/s",
3653 "fragok6/s", "fragcr6/s"};
3654 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3655 static double *spmin, *spmax;
3657 static int *outsize;
3659 if (action & F_BEGIN) {
3661 * Allocate arrays that will contain the graphs data
3662 * and the min/max values.
3664 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3667 if (action & F_MAIN) {
3668 /* Check for min/max values */
3669 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3670 itv, spmin, spmax, g_fields);
3673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3674 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3675 out, outsize, svg_p->restart);
3677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3678 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3679 out + 1, outsize + 1, svg_p->restart);
3681 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3682 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3683 out + 2, outsize + 2, svg_p->restart);
3685 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3686 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3687 out + 3, outsize + 3, svg_p->restart);
3689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3690 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3691 out + 4, outsize + 4, svg_p->restart);
3693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3694 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3695 out + 5, outsize + 5, svg_p->restart);
3697 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3698 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3699 out + 6, outsize + 6, svg_p->restart);
3701 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3702 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3703 out + 7, outsize + 7, svg_p->restart);
3705 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3706 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3707 out + 8, outsize + 8, svg_p->restart);
3709 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3710 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3711 out + 9, outsize + 9, svg_p->restart);
3714 if (action & F_END) {
3715 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3716 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3718 /* Free remaining structures */
3719 free_graphs(out, outsize, spmin, spmax);
3724 ***************************************************************************
3725 * Display IPv6 network errors statistics in SVG.
3728 * @a Activity structure with statistics.
3729 * @curr Index in array for current sample statistics.
3730 * @action Action expected from current function.
3731 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3732 * flag indicating that a restart record has been previously
3733 * found (.@restart) and time used for the X axis origin
3735 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3736 * @record_hdr Pointer on record header of current stats sample.
3737 ***************************************************************************
3739 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3740 unsigned long long itv, struct record_header *record_hdr)
3742 struct stats_net_eip6
3743 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3744 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3745 int group[] = {4, 2, 2, 3};
3746 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3748 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3749 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3750 "IPv6 network errors statistics (5)"};
3751 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3752 "idisc6/s", "odisc6/s",
3753 "inort6/s", "onort6/s",
3754 "asmf6/s", "fragf6/s", "itrpck6/s"};
3755 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3756 static double *spmin, *spmax;
3758 static int *outsize;
3760 if (action & F_BEGIN) {
3762 * Allocate arrays that will contain the graphs data
3763 * and the min/max values.
3765 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3768 if (action & F_MAIN) {
3769 /* Check for min/max values */
3770 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3771 itv, spmin, spmax, g_fields);
3774 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3775 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3776 out, outsize, svg_p->restart);
3778 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3779 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3780 out + 1, outsize + 1, svg_p->restart);
3782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3783 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3784 out + 2, outsize + 2, svg_p->restart);
3786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3787 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3788 out + 3, outsize + 3, svg_p->restart);
3790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3791 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3792 out + 4, outsize + 4, svg_p->restart);
3794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3795 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3796 out + 5, outsize + 5, svg_p->restart);
3798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3799 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3800 out + 6, outsize + 6, svg_p->restart);
3802 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3803 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3804 out + 7, outsize + 7, svg_p->restart);
3806 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3807 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3808 out + 8, outsize + 8, svg_p->restart);
3810 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3811 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3812 out + 9, outsize + 9, svg_p->restart);
3814 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3815 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3816 out + 10, outsize + 10, svg_p->restart);
3819 if (action & F_END) {
3820 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3821 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3823 /* Free remaining structures */
3824 free_graphs(out, outsize, spmin, spmax);
3829 ***************************************************************************
3830 * Display ICMPv6 network statistics in SVG.
3833 * @a Activity structure with statistics.
3834 * @curr Index in array for current sample statistics.
3835 * @action Action expected from current function.
3836 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3837 * flag indicating that a restart record has been previously
3838 * found (.@restart) and time used for the X axis origin
3840 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3841 * @record_hdr Pointer on record header of current stats sample.
3842 ***************************************************************************
3844 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3845 unsigned long long itv, struct record_header *record_hdr)
3847 struct stats_net_icmp6
3848 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3849 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3850 int group[] = {2, 3, 5, 3, 4};
3851 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3852 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3853 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3854 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3855 "ICMPv6 network statistics (5)"};
3856 char *g_title[] = {"imsg6/s", "omsg6/s",
3857 "iech6/s", "iechr6/s", "oechr6/s",
3858 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3859 "irtsol6/s", "ortsol6/s", "irtad6/s",
3860 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3861 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3862 static double *spmin, *spmax;
3864 static int *outsize;
3866 if (action & F_BEGIN) {
3868 * Allocate arrays that will contain the graphs data
3869 * and the min/max values.
3871 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3874 if (action & F_MAIN) {
3875 /* Check for min/max values */
3876 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3877 itv, spmin, spmax, g_fields);
3880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3881 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3882 out, outsize, svg_p->restart);
3884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3885 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3886 out + 1, outsize + 1, svg_p->restart);
3888 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3889 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3890 out + 2, outsize + 2, svg_p->restart);
3892 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3893 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3894 out + 3, outsize + 3, svg_p->restart);
3896 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3897 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3898 out + 4, outsize + 4, svg_p->restart);
3900 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3901 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3902 out + 5, outsize + 5, svg_p->restart);
3904 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3905 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3906 out + 6, outsize + 6, svg_p->restart);
3908 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3909 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3910 out + 7, outsize + 7, svg_p->restart);
3912 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3913 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3914 out + 8, outsize + 8, svg_p->restart);
3916 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3917 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3918 out + 9, outsize + 9, svg_p->restart);
3920 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3921 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3922 out + 10, outsize + 10, svg_p->restart);
3924 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3925 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3926 out + 11, outsize + 11, svg_p->restart);
3928 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3929 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3930 out + 12, outsize + 12, svg_p->restart);
3932 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3933 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3934 out + 13, outsize + 13, svg_p->restart);
3936 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3937 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3938 out + 14, outsize + 14, svg_p->restart);
3940 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3941 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3942 out + 15, outsize + 15, svg_p->restart);
3944 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3945 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3946 out + 16, outsize + 16, svg_p->restart);
3949 if (action & F_END) {
3950 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3951 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
3953 /* Free remaining structures */
3954 free_graphs(out, outsize, spmin, spmax);
3959 ***************************************************************************
3960 * Display ICMPv6 network errors statistics in SVG.
3963 * @a Activity structure with statistics.
3964 * @curr Index in array for current sample statistics.
3965 * @action Action expected from current function.
3966 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3967 * flag indicating that a restart record has been previously
3968 * found (.@restart) and time used for the X axis origin
3970 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3971 * @record_hdr Pointer on record header of current stats sample.
3972 ***************************************************************************
3974 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3975 unsigned long long itv, struct record_header *record_hdr)
3977 struct stats_net_eicmp6
3978 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3979 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3980 int group[] = {1, 2, 2, 2, 2, 2};
3981 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3982 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3983 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3984 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3985 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3986 char *g_title[] = {"ierr6/s",
3987 "idtunr6/s", "odtunr6/s",
3988 "itmex6/s", "otmex6/s",
3989 "iprmpb6/s", "oprmpb6/s",
3990 "iredir6/s", "oredir6/s",
3991 "ipck2b6/s", "opck2b6/s"};
3992 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3993 static double *spmin, *spmax;
3995 static int *outsize;
3997 if (action & F_BEGIN) {
3999 * Allocate arrays that will contain the graphs data
4000 * and the min/max values.
4002 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4005 if (action & F_MAIN) {
4006 /* Check for min/max values */
4007 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4008 itv, spmin, spmax, g_fields);
4011 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4012 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4013 out, outsize, svg_p->restart);
4015 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4016 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4017 out + 1, outsize + 1, svg_p->restart);
4019 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4020 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4021 out + 2, outsize + 2, svg_p->restart);
4023 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4024 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4025 out + 3, outsize + 3, svg_p->restart);
4027 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4028 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4029 out + 4, outsize + 4, svg_p->restart);
4031 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4032 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4033 out + 5, outsize + 5, svg_p->restart);
4035 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4036 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4037 out + 6, outsize + 6, svg_p->restart);
4039 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4040 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4041 out + 7, outsize + 7, svg_p->restart);
4043 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4044 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4045 out + 8, outsize + 8, svg_p->restart);
4047 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4048 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4049 out + 9, outsize + 9, svg_p->restart);
4051 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4052 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4053 out + 10, outsize + 10, svg_p->restart);
4056 if (action & F_END) {
4057 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4058 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4060 /* Free remaining structures */
4061 free_graphs(out, outsize, spmin, spmax);
4066 ***************************************************************************
4067 * Display UDPv6 network statistics in SVG.
4070 * @a Activity structure with statistics.
4071 * @curr Index in array for current sample statistics.
4072 * @action Action expected from current function.
4073 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4074 * flag indicating that a restart record has been previously
4075 * found (.@restart) and time used for the X axis origin
4077 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4078 * @record_hdr Pointer on record header of current stats sample.
4079 ***************************************************************************
4081 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4082 unsigned long long itv, struct record_header *record_hdr)
4084 struct stats_net_udp6
4085 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4086 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4087 int group[] = {2, 2};
4088 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4089 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
4090 char *g_title[] = {"idgm6/s", "odgm6/s",
4091 "noport6/s", "idgmer6/s"};
4092 int g_fields[] = {0, 1, 2, 3};
4093 static double *spmin, *spmax;
4095 static int *outsize;
4097 if (action & F_BEGIN) {
4099 * Allocate arrays that will contain the graphs data
4100 * and the min/max values.
4102 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4105 if (action & F_MAIN) {
4106 /* Check for min/max values */
4107 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4108 itv, spmin, spmax, g_fields);
4111 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4112 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4113 out, outsize, svg_p->restart);
4115 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4116 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4117 out + 1, outsize + 1, svg_p->restart);
4119 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4120 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4121 out + 2, outsize + 2, svg_p->restart);
4123 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4124 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4125 out + 3, outsize + 3, svg_p->restart);
4128 if (action & F_END) {
4129 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4130 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4132 /* Free remaining structures */
4133 free_graphs(out, outsize, spmin, spmax);
4138 ***************************************************************************
4139 * Display CPU frequency statistics in SVG.
4142 * @a Activity structure with statistics.
4143 * @curr Index in array for current sample statistics.
4144 * @action Action expected from current function.
4145 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4146 * flag indicating that a restart record has been previously
4147 * found (.@restart) and time used for the X axis origin
4149 * @itv Interval of time in 1/100th of a second (unused here).
4150 * @record_hdr Pointer on record header of current stats sample.
4151 ***************************************************************************
4153 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4154 unsigned long long itv, struct record_header *record_hdr)
4156 struct stats_pwr_cpufreq *spc, *spp;
4158 int g_type[] = {SVG_LINE_GRAPH};
4159 char *title[] = {"CPU frequency"};
4160 char *g_title[] = {"MHz"};
4161 static double *spmin, *spmax;
4163 static int *outsize;
4167 if (action & F_BEGIN) {
4169 * Allocate arrays that will contain the graphs data
4170 * and the min/max values.
4172 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4175 if (action & F_MAIN) {
4177 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4179 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4180 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4182 /* Should current CPU (including CPU "all") be displayed? */
4183 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4188 * Note: Don't skip offline CPU here as it is needed
4189 * to make the graph go though 0.
4193 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4194 ((double) spp->cpufreq) / 100,
4195 ((double) spc->cpufreq) / 100,
4196 out + i, outsize + i, svg_p->restart, svg_p->dt,
4197 spmin + i, spmax + i);
4201 if (action & F_END) {
4202 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
4204 /* Should current CPU (including CPU "all") be displayed? */
4205 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4210 /* This is CPU "all" */
4211 strcpy(item_name, "all");
4215 * If the maximum frequency reached by the CPU is 0, then
4216 * the CPU has been offline on the whole period.
4217 * => Don't display it.
4219 if (*(spmax + i) == 0)
4222 sprintf(item_name, "%d", i - 1);
4225 draw_activity_graphs(a->g_nr, g_type,
4226 title, g_title, item_name, group,
4227 spmin + i, spmax + i, out + i, outsize + i,
4228 svg_p, record_hdr, i);
4231 /* Free remaining structures */
4232 free_graphs(out, outsize, spmin, spmax);
4237 ***************************************************************************
4238 * Display fan statistics in SVG.
4241 * @a Activity structure with statistics.
4242 * @curr Index in array for current sample statistics.
4243 * @action Action expected from current function.
4244 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4245 * flag indicating that a restart record has been previously
4246 * found (.@restart) and time used for the X axis origin
4248 * @itv Interval of time in 1/100th of a second (unused here).
4249 * @record_hdr Pointer on record header of current stats sample.
4250 ***************************************************************************
4252 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4253 unsigned long long itv, struct record_header *record_hdr)
4255 struct stats_pwr_fan *spc, *spp;
4257 int g_type[] = {SVG_LINE_GRAPH};
4258 char *title[] = {"Fan speed"};
4259 char *g_title[] = {"~rpm"};
4260 static double *spmin, *spmax;
4262 static int *outsize;
4263 char item_name[MAX_SENSORS_DEV_LEN + 8];
4266 if (action & F_BEGIN) {
4268 * Allocate arrays that will contain the graphs data
4269 * and the min/max values.
4271 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4274 if (action & F_MAIN) {
4276 for (i = 0; i < a->nr[curr]; i++) {
4278 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4279 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4282 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4285 out + i, outsize + i, svg_p->restart, svg_p->dt,
4286 spmin + i, spmax + i);
4290 if (action & F_END) {
4291 for (i = 0; i < svg_p->nr_max; i++) {
4293 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4295 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4296 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4298 draw_activity_graphs(a->g_nr, g_type,
4299 title, g_title, item_name, group,
4300 spmin + i, spmax + i, out + i, outsize + i,
4301 svg_p, record_hdr, FALSE);
4304 /* Free remaining structures */
4305 free_graphs(out, outsize, spmin, spmax);
4310 ***************************************************************************
4311 * Display temperature statistics in SVG.
4314 * @a Activity structure with statistics.
4315 * @curr Index in array for current sample statistics.
4316 * @action Action expected from current function.
4317 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4318 * flag indicating that a restart record has been previously
4319 * found (.@restart) and time used for the X axis origin
4321 * @itv Interval of time in 1/100th of a second (unused here).
4322 * @record_hdr Pointer on record header of current stats sample.
4323 ***************************************************************************
4325 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4326 unsigned long long itv, struct record_header *record_hdr)
4328 struct stats_pwr_temp *spc;
4329 int group[] = {1, 1};
4330 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4331 char *title[] = {"Device temperature (1)",
4332 "Device temperature (2)"};
4333 char *g_title[] = {"~degC",
4335 static double *spmin, *spmax;
4337 static int *outsize;
4338 char item_name[MAX_SENSORS_DEV_LEN + 8];
4342 if (action & F_BEGIN) {
4344 * Allocate arrays that will contain the graphs data
4345 * and the min/max values.
4347 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4350 if (action & F_MAIN) {
4351 /* For each temperature sensor */
4352 for (i = 0; i < a->nr[curr]; i++) {
4354 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4356 /* Look for min/max values */
4357 if (spc->temp < *(spmin + 2 * i)) {
4358 *(spmin + 2 * i) = spc->temp;
4360 if (spc->temp > *(spmax + 2 * i)) {
4361 *(spmax + 2 * i) = spc->temp;
4363 tval = (spc->temp_max - spc->temp_min) ?
4364 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4366 if (tval < *(spmin + 2 * i + 1)) {
4367 *(spmin + 2 * i + 1) = tval;
4369 if (tval > *(spmax + 2 * i + 1)) {
4370 *(spmax + 2 * i + 1) = tval;
4374 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4376 out + 2 * i, outsize + 2 * i, svg_p->restart);
4378 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4380 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4384 if (action & F_END) {
4385 for (i = 0; i < svg_p->nr_max; i++) {
4387 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4389 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4390 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4392 draw_activity_graphs(a->g_nr, g_type,
4393 title, g_title, item_name, group,
4394 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4395 svg_p, record_hdr, FALSE);
4398 /* Free remaining structures */
4399 free_graphs(out, outsize, spmin, spmax);
4404 ***************************************************************************
4405 * Display voltage inputs statistics in SVG.
4408 * @a Activity structure with statistics.
4409 * @curr Index in array for current sample statistics.
4410 * @action Action expected from current function.
4411 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4412 * flag indicating that a restart record has been previously
4413 * found (.@restart) and time used for the X axis origin
4415 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4416 * @record_hdr Pointer on record header of current stats sample.
4417 ***************************************************************************
4419 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4420 unsigned long long itv, struct record_header *record_hdr)
4422 struct stats_pwr_in *spc;
4423 int group[] = {1, 1};
4424 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4425 char *title[] = {"Voltage inputs (1)",
4426 "Voltage inputs (2)"};
4427 char *g_title[] = {"inV",
4429 static double *spmin, *spmax;
4431 static int *outsize;
4432 char item_name[MAX_SENSORS_DEV_LEN + 8];
4436 if (action & F_BEGIN) {
4438 * Allocate arrays that will contain the graphs data
4439 * and the min/max values.
4441 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4444 if (action & F_MAIN) {
4445 /* For each voltage input sensor */
4446 for (i = 0; i < a->nr[curr]; i++) {
4448 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4450 /* Look for min/max values */
4451 if (spc->in < *(spmin + 2 * i)) {
4452 *(spmin + 2 * i) = spc->in;
4454 if (spc->in > *(spmax + 2 * i)) {
4455 *(spmax + 2 * i) = spc->in;
4457 tval = (spc->in_max - spc->in_min) ?
4458 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4460 if (tval < *(spmin + 2 * i + 1)) {
4461 *(spmin + 2 * i + 1) = tval;
4463 if (tval > *(spmax + 2 * i + 1)) {
4464 *(spmax + 2 * i + 1) = tval;
4468 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4470 out + 2 * i, outsize + 2 * i, svg_p->restart);
4472 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4474 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4478 if (action & F_END) {
4479 for (i = 0; i < svg_p->nr_max; i++) {
4481 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4483 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4484 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4486 draw_activity_graphs(a->g_nr, g_type,
4487 title, g_title, item_name, group,
4488 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4489 svg_p, record_hdr, FALSE);
4492 /* Free remaining structures */
4493 free_graphs(out, outsize, spmin, spmax);
4498 ***************************************************************************
4499 * Display huge pages statistics in SVG.
4502 * @a Activity structure with statistics.
4503 * @curr Index in array for current sample statistics.
4504 * @action Action expected from current function.
4505 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4506 * flag indicating that a restart record has been previously
4507 * found (.@restart) and time used for the X axis origin
4509 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4510 * @record_hdr Pointer on record header of current stats sample.
4511 ***************************************************************************
4513 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4514 unsigned long long itv, struct record_header *record_hdr)
4517 *smc = (struct stats_huge *) a->buf[curr];
4518 int group[] = {2, 1};
4519 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4520 char *title[] = {"Huge pages utilization (1)",
4521 "Huge pages utilization (2)"};
4522 char *g_title[] = {"~kbhugfree", "~kbhugused",
4524 int g_fields[] = {0};
4525 unsigned int local_types_nr[] = {0, 1, 0};
4526 static double *spmin, *spmax;
4528 static int *outsize;
4531 if (action & F_BEGIN) {
4533 * Allocate arrays that will contain the graphs data
4534 * and the min/max values.
4536 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4539 if (action & F_MAIN) {
4540 /* Check for min/max values */
4541 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4542 itv, spmin, spmax, g_fields);
4544 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4545 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4547 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4548 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4550 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4551 if (tval < *(spmin + 2)) {
4552 *(spmin + 2) = tval;
4554 if (tval > *(spmax + 2)) {
4555 *(spmax + 2) = tval;
4559 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4560 (unsigned long long) smc->frhkb,
4561 out, outsize, svg_p->restart);
4563 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4564 (unsigned long long) smc->tlhkb - smc->frhkb,
4565 out + 1, outsize + 1, svg_p->restart);
4567 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4569 out + 2, outsize + 2, svg_p->dt);
4572 if (action & F_END) {
4573 draw_activity_graphs(a->g_nr, g_type,
4574 title, g_title, NULL, group,
4575 spmin, spmax, out, outsize, svg_p, record_hdr, FALSE);
4577 /* Free remaining structures */
4578 free_graphs(out, outsize, spmin, spmax);
4583 ***************************************************************************
4584 * Display filesystem statistics in SVG.
4587 * @a Activity structure with statistics.
4588 * @curr Index in array for current sample statistics.
4589 * @action Action expected from current function.
4590 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4591 * flag indicating that a restart record has been previously
4592 * found (.@restart) and time used for the X axis origin
4594 * @itv Interval of time in 1/100th of a second (unused here).
4595 * @record_hdr Pointer on record header of current stats sample.
4596 ***************************************************************************
4598 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4599 unsigned long long itv, struct record_header *record_hdr)
4601 struct stats_filesystem *sfc, *sfp;
4602 int group[] = {2, 2, 2, 1};
4603 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4604 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4605 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4606 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4607 char *g_title[] = {"~MBfsfree", "~MBfsused",
4608 "%ufsused", "%fsused",
4609 "Ifree/1000", "Iused/1000",
4611 static double *spmin, *spmax;
4613 static int *outsize;
4614 char *item_name = NULL;
4616 int i, k, pos, restart;
4618 if (action & F_BEGIN) {
4620 * Allocate arrays (#0..6) that will contain the graphs data
4621 * and the min/max values.
4622 * Also allocate two additional arrays (#7..8) for each filesystem:
4623 * out + 7 will contain the filesystem name,
4624 * out + 8 will contain the mount point.
4626 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
4629 if (action & F_MAIN) {
4630 /* For each filesystem structure */
4631 for (i = 0; i < a->nr[curr]; i++) {
4632 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4634 /* Look for corresponding graph */
4635 for (k = 0; k < svg_p->nr_max; k++) {
4636 item_name = *(out + k * 9 + 7);
4637 if (!strcmp(sfc->fs_name, item_name))
4642 if (k == svg_p->nr_max) {
4643 /* Graph not found: Look for first free entry */
4644 for (k = 0; k < svg_p->nr_max; k++) {
4645 item_name = *(out + k * 9 + 7);
4646 if (!strcmp(item_name, ""))
4649 if (k == svg_p->nr_max) {
4650 /* No free graph entry: Extend all buffers */
4651 reallocate_all_graph_lines(svg_p->nr_max,
4652 &out, &outsize, &spmin, &spmax);
4659 if (!item_name[0]) {
4660 /* Save filesystem name and mount point (if not already done) */
4661 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4662 item_name[CHUNKSIZE - 1] = '\0';
4663 item_name = *(out + pos + 8);
4664 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4665 item_name[CHUNKSIZE - 1] = '\0';
4669 for (k = 0; k < a->nr[!curr]; k++) {
4670 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4671 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4672 /* Filesystem found in previous sample */
4673 restart = svg_p->restart;
4677 /* Check for min/max values */
4679 /* Compute fsfree min/max values */
4680 tval = (double) sfc->f_bfree;
4681 if (tval > *(spmax + pos)) {
4682 *(spmax + pos) = tval;
4684 if (tval < *(spmin + pos)) {
4685 *(spmin + pos) = tval;
4687 /* Compute fsused min/max values */
4688 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4689 if (tval > *(spmax + pos + 1)) {
4690 *(spmax + pos + 1) = tval;
4692 if (tval < *(spmin + pos + 1)) {
4693 *(spmin + pos + 1) = tval;
4695 /* Compute %ufsused min/max values */
4696 tval = sfc->f_blocks ?
4697 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4698 if (tval > *(spmax + pos + 2)) {
4699 *(spmax + pos + 2) = tval;
4701 if (tval < *(spmin + pos + 2)) {
4702 *(spmin + pos + 2) = tval;
4704 /* Compute %fsused min/max values */
4705 tval = sfc->f_blocks ?
4706 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4707 if (tval > *(spmax + pos + 3)) {
4708 *(spmax + pos + 3) = tval;
4710 if (tval < *(spmin + pos + 3)) {
4711 *(spmin + pos + 3) = tval;
4713 /* Compute Ifree min/max values */
4714 tval = (double) sfc->f_ffree;
4715 if (tval > *(spmax + pos + 4)) {
4716 *(spmax + pos + 4) = tval;
4718 if (tval < *(spmin + pos + 4)) {
4719 *(spmin + pos + 4) = tval;
4721 /* Compute Iused min/max values */
4722 tval = (double) (sfc->f_files - sfc->f_ffree);
4723 if (tval > *(spmax + pos + 5)) {
4724 *(spmax + pos + 5) = tval;
4726 if (tval < *(spmin + pos + 5)) {
4727 *(spmin + pos + 5) = tval;
4729 /* Compute %Iused min/max values */
4730 tval = sfc->f_files ?
4731 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4732 if (tval > *(spmax + pos + 6)) {
4733 *(spmax + pos + 6) = tval;
4735 if (tval < *(spmin + pos + 6)) {
4736 *(spmin + pos + 6) = tval;
4740 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4741 (double) sfc->f_bfree / 1024 / 1024,
4742 out + pos, outsize + pos, restart);
4744 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4745 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4746 out + pos + 1, outsize + pos + 1, restart);
4748 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4751 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4752 out + pos + 2, outsize + pos + 2, svg_p->dt);
4754 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4757 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4758 out + pos + 3, outsize + pos + 3, svg_p->dt);
4760 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4761 ((double) sfc->f_ffree) / 1000,
4762 out + pos + 4, outsize + pos + 4, restart);
4764 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4765 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4766 out + pos + 5, outsize + pos + 5, restart);
4768 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4771 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4772 out + pos + 6, outsize + pos + 6, svg_p->dt);
4776 if (action & F_END) {
4778 for (i = 0; i < svg_p->nr_max; i++) {
4780 /* Check if there is something to display */
4785 /* Conversion B -> MB and inodes/1000 */
4786 for (k = 0; k < 2; k++) {
4787 *(spmin + pos + k) /= (1024 * 1024);
4788 *(spmax + pos + k) /= (1024 * 1024);
4789 *(spmin + pos + 4 + k) /= 1000;
4790 *(spmax + pos + 4 + k) /= 1000;
4793 if (DISPLAY_MOUNT(a->opt_flags)) {
4794 item_name = *(out + pos + 8);
4797 item_name = *(out + pos + 7);
4800 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4801 spmin + pos, spmax + pos, out + pos, outsize + pos,
4802 svg_p, record_hdr, FALSE);
4805 /* Free remaining structures */
4806 free_graphs(out, outsize, spmin, spmax);
4811 ***************************************************************************
4812 * Display Fibre Channel HBA statistics in SVG.
4815 * @a Activity structure with statistics.
4816 * @curr Index in array for current sample statistics.
4817 * @action Action expected from current function.
4818 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4819 * flag indicating that a restart record has been previously
4820 * found (.@restart) and time used for the X axis origin
4822 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4823 * @record_hdr Pointer on record header of current stats sample.
4824 ***************************************************************************
4826 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4827 unsigned long long itv, struct record_header *record_hdr)
4829 struct stats_fchost *sfcc, *sfcp;
4830 int group[] = {2, 2};
4831 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4832 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4833 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4834 "fch_rxw/s", "fch_txw/s"};
4835 int g_fields[] = {0, 1, 2, 3};
4836 static double *spmin, *spmax;
4838 static int *outsize;
4840 int i, j, j0, k, found, pos, restart, *unregistered;
4842 if (action & F_BEGIN) {
4844 * Allocate arrays (#0..3) that will contain the graphs data
4845 * and the min/max values.
4846 * Also allocate one additional array (#4) that will contain
4847 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4848 * has either still not been registered, or has been unregistered
4851 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
4854 if (action & F_MAIN) {
4855 restart = svg_p->restart;
4857 * Mark previously registered interfaces as now
4858 * possibly unregistered for all graphs.
4860 for (k = 0; k < svg_p->nr_max; k++) {
4861 unregistered = outsize + k * 5 + 4;
4862 if (*unregistered == FALSE) {
4863 *unregistered = MAYBE;
4867 /* For each FC HBA */
4868 for (i = 0; i < a->nr[curr]; i++) {
4872 if (a->nr[!curr] > 0) {
4873 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4875 /* Look for corresponding graph */
4876 for (k = 0; k < svg_p->nr_max; k++) {
4877 item_name = *(out + k * 5 + 4);
4878 if (!strcmp(sfcc->fchost_name, item_name))
4882 if (k == svg_p->nr_max) {
4883 /* Graph not found: Look for first free entry */
4884 for (k = 0; k < svg_p->nr_max; k++) {
4885 item_name = *(out + k * 5 + 4);
4886 if (!strcmp(item_name, ""))
4889 if (k == svg_p->nr_max) {
4890 /* No free graph entry: Extend all buffers */
4891 reallocate_all_graph_lines(svg_p->nr_max,
4892 &out, &outsize, &spmin, &spmax);
4898 unregistered = outsize + pos + 4;
4900 /* Look for corresponding structure in previous iteration */
4903 if (j >= a->nr[!curr]) {
4904 j = a->nr[!curr] - 1;
4910 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4911 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4915 if (++j >= a->nr[!curr]) {
4926 * If current interface was marked as previously unregistered,
4927 * then set restart variable to TRUE so that the graph will be
4928 * discontinuous, and mark it as now registered.
4930 if (*unregistered == TRUE) {
4933 *unregistered = FALSE;
4935 item_name = *(out + pos + 4);
4936 if (!item_name[0]) {
4937 /* Save FC HBA name */
4938 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4939 item_name[CHUNKSIZE - 1] = '\0';
4942 /* Look for min/max values */
4943 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4944 itv, spmin + pos, spmax + pos, g_fields);
4947 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4948 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4949 out + pos, outsize + pos, restart);
4951 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4952 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4953 out + pos + 1, outsize + pos + 1, restart);
4955 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4956 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4957 out + pos + 2, outsize + pos + 2, restart);
4959 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4960 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4961 out + pos + 3, outsize + pos + 3, restart);
4964 /* Mark interfaces not seen here as now unregistered */
4965 for (k = 0; k < svg_p->nr_max; k++) {
4966 unregistered = outsize + k * 5 + 4;
4967 if (*unregistered != FALSE) {
4968 *unregistered = TRUE;
4973 if (action & F_END) {
4974 for (i = 0; i < svg_p->nr_max; i++) {
4976 /* Check if there is something to display */
4981 item_name = *(out + pos + 4);
4982 draw_activity_graphs(a->g_nr, g_type,
4983 title, g_title, item_name, group,
4984 spmin + pos, spmax + pos, out + pos, outsize + pos,
4985 svg_p, record_hdr, FALSE);
4988 /* Free remaining structures */
4989 free_graphs(out, outsize, spmin, spmax);
4994 ***************************************************************************
4995 * Display softnet statistics in SVG.
4998 * @a Activity structure with statistics.
4999 * @curr Index in array for current sample statistics.
5000 * @action Action expected from current function.
5001 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
5002 * flag indicating that a restart record has been previously
5003 * found (.@restart) and time used for the X axis origin
5005 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
5006 * @record_hdr Pointer on record header of current stats sample.
5007 ***************************************************************************
5009 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
5010 unsigned long long itv, struct record_header *record_hdr)
5012 struct stats_softnet *ssnc, *ssnp;
5013 int group[] = {2, 3};
5014 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
5015 char *title[] = {"Software-based network processing statistics (1)",
5016 "Software-based network processing statistics (2)"};
5017 char *g_title[] = {"total/s", "dropd/s",
5018 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5019 int g_fields[] = {0, 1, 2, 3, 4};
5020 static double *spmin, *spmax;
5022 static int *outsize;
5024 unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
5027 if (action & F_BEGIN) {
5029 * Allocate arrays that will contain the graphs data
5030 * and the min/max values.
5032 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
5035 if (action & F_MAIN) {
5036 /* @nr[curr] cannot normally be greater than @nr_ini */
5037 if (a->nr[curr] > a->nr_ini) {
5038 a->nr_ini = a->nr[curr];
5041 /* Compute statistics for CPU "all" */
5042 get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
5045 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
5047 /* Should current CPU (including CPU "all") be displayed? */
5048 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
5049 offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
5053 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5054 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5058 /* Check for min/max values */
5059 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5060 itv, spmin + pos, spmax + pos, g_fields);
5063 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5064 S_VALUE(ssnp->processed, ssnc->processed, itv),
5065 out + pos, outsize + pos, svg_p->restart);
5067 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5068 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5069 out + pos + 1, outsize + pos + 1, svg_p->restart);
5071 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5072 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5073 out + pos + 2, outsize + pos + 2, svg_p->restart);
5075 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5076 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5077 out + pos + 3, outsize + pos + 3, svg_p->restart);
5079 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5080 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5081 out + pos + 4, outsize + pos + 4, svg_p->restart);
5085 if (action & F_END) {
5086 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
5088 /* Should current CPU (including CPU "all") be displayed? */
5089 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5096 /* This is CPU "all" */
5097 strcpy(item_name, "all");
5100 sprintf(item_name, "%d", i - 1);
5103 draw_activity_graphs(a->g_nr, g_type,
5104 title, g_title, item_name, group,
5105 spmin + pos, spmax + pos, out + pos, outsize + pos,
5106 svg_p, record_hdr, FALSE);
5109 /* Free remaining structures */
5110 free_graphs(out, outsize, spmin, spmax);