2 * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
3 * (C) 2016-2017 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 Number of vertical lines to display.
661 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
662 ***************************************************************************
664 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
666 struct record_header stamp;
668 char cur_time[TIMESTAMP_LEN];
671 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
673 for (j = 0; (j <= v_gridnr) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
675 /* Display vertical lines */
676 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
677 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
678 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
679 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
680 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
682 * Display graduations.
683 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
684 * In this case, we should rather display the exact time instead of only the hour.
686 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
687 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
688 "text-anchor: start\">%2d:00</text>\n",
689 (long) (xpos * j * xfactor) - 15, rectime.tm_hour);
692 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
693 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
694 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
696 stamp.ust_time += xpos;
699 if (!PRINT_LOCAL_TIME(flags)) {
700 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
701 "text-anchor: end\">UTC</text>\n");
706 ***************************************************************************
707 * Calculate the value on the Y axis between two horizontal lines that will
708 * make the graph background grid.
711 * @lmax Max value reached for this graph.
714 * @dp Number of decimal places for Y graduations.
717 * Value between two horizontal lines.
718 ***************************************************************************
720 double ygrid(double lmax, int *dp)
731 n = (long) (lmax / SVG_H_GRIDNR);
734 return (lmax / SVG_H_GRIDNR);
736 snprintf(val, 32, "%ld", n);
743 return ((double) (((long) (n / e)) * e));
747 ***************************************************************************
748 * Calculate the value on the X axis between two vertical lines that will
749 * make the graph background grid.
752 * @timestart First data timestamp (X coordinate of the first data point).
753 * @timeend Last data timestamp (X coordinate of the last data point).
754 * @v_gridnr Number of vertical lines to display. Its value is normally
755 * SVG_V_GRIDNR, except when option "oneday" is used, in which
756 * case it is set to 12.
759 * Value between two vertical lines.
760 ***************************************************************************
762 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
764 if ((timeend - timestart) <= v_gridnr)
767 return ((timeend - timestart) / v_gridnr);
771 ***************************************************************************
772 * Free global graphs structures.
775 * @out Pointer on array of chars for each graph definition.
776 * @outsize Size of array of chars for each graph definition.
777 * @spmin Array containing min values for graphs.
778 * @spmax Array containing max values for graphs.
779 ***************************************************************************
781 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
798 ***************************************************************************
799 * Skip current view where all graphs have only zero values. This function
800 * is called when option "skipempty" has been used, or when "No data" have
801 * been found for current view.
804 * @out Pointer on array of chars for each graph definition.
805 * @pos Position of current view in the array of graphs definitions.
806 * @group Number of graphs in current view.
809 * @pos Position of next view in the array of graphs definitions.
810 ***************************************************************************
812 void skip_current_view(char **out, int *pos, int group)
817 for (j = 0; j < group; j++) {
818 out_p = *(out + *pos + j);
820 /* Even if not displayed, current graph data have to be freed */
828 ***************************************************************************
829 * Display all graphs for current activity.
832 * @g_nr Number of views to display.
833 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
834 * @title Titles for each set of graphs.
835 * @g_title Titles for each graph.
836 * @item_name Item (network interface, etc.) name.
837 * @group Indicate how graphs are grouped together to make sets.
838 * @spmin Array containing min values for graphs.
839 * @spmax Array containing max values for graphs.
840 * @out Pointer on array of chars for each graph definition.
841 * @outsize Size of array of chars for each graph definition.
842 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
843 * time for the first sample of stats (.@ust_time_first), and
844 * times used as start and end values on the X axis
845 * (.@ust_time_ref and .@ust_time_end).
846 * @record_hdr Pointer on record header of current stats sample.
847 ***************************************************************************
849 void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
850 int group[], double *spmin, double *spmax, char **out, int *outsize,
851 struct svg_parm *svg_p, struct record_header *record_hdr)
854 int i, j, dp, pos = 0, views_nr = 0;
855 int v_gridnr, xv, yv;
856 unsigned int asfactor[16];
858 double lmax, xfactor, yfactor, ypos, gmin, gmax;
859 char val[32], cur_date[TIMESTAMP_LEN];
861 /* Translate to proper position for current activity */
862 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
864 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
866 /* For each view which is part of current activity */
867 for (i = 0; i < g_nr; i++) {
869 /* Get global min and max value for current view */
870 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
872 /* Don't display empty views if requested */
873 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
874 skip_current_view(out, &pos, group[i]);
877 /* Increment number of views actually displayed */
880 /* Compute top left position of view */
881 if (PACK_VIEWS(flags)) {
882 xv = (views_nr - 1) * SVG_T_XSIZE;
887 yv = (views_nr - 1) * SVG_T_YSIZE;
890 /* Graph background */
891 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
892 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
895 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
896 xv, 20 + yv, title[i]);
898 printf(" [%s]", item_name);
901 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
902 "(Min, Max values)</tspan>\n</text>\n",
903 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
906 * At least two samples are needed.
907 * And a min and max value should have been found.
909 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
910 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
912 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
913 xv, yv + SVG_M_YSIZE);
914 skip_current_view(out, &pos, group[i]);
919 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
920 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
921 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
922 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
924 /* Autoscaling graphs if needed */
925 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
928 for (j = 0; j < group[i]; j++) {
929 /* Set dp to TRUE (1) if current metric is based on integer values */
930 dp = (g_title[pos + j][0] == '~');
931 snprintf(val, 32, "x%u ", asfactor[j]);
932 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
933 "%s %s(%.*f, %.*f)</text>\n",
934 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
935 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
936 asfactor[j] == 1 ? "" : val,
937 !dp * 2, *(spmin + pos + j) * asfactor[j],
938 !dp * 2, *(spmax + pos + j) * asfactor[j]);
941 if (DISPLAY_INFO(flags)) {
942 /* Display additional info (hostname, date) */
943 printf("<text x=\"%d\" y=\"%d\" "
944 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
946 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
947 svg_p->file_hdr->sa_nodename);
949 /* Get report date */
950 set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
951 cur_date, sizeof(cur_date));
952 printf("<tspan x=\"%d\" y=\"%d\" "
953 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
954 "%s</tspan>\n</text>\n",
955 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
959 /* Translate to proper position for current graph within current activity */
960 printf("<g transform=\"translate(%d,%d)\">\n",
961 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
964 if (g_type[i] == SVG_LINE_GRAPH) {
965 /* For line graphs */
967 /* If all values are zero then set current max value to 1 */
973 /* Max value cannot be too small, else Y graduations will be meaningless */
974 if (lmax < SVG_H_GRIDNR * 0.01) {
975 lmax = SVG_H_GRIDNR * 0.01;
977 ypos = ygrid(lmax, &dp);
980 /* For bar graphs (used for %values) */
981 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
982 dp = 0; /* No decimals */
984 /* Max should be always 100% except for percentage values greater than 100% */
992 yfactor = (double) -SVG_G_YSIZE / lmax;
994 /* Display horizontal lines and graduations */
995 display_hgrid(ypos, yfactor, lmax, dp);
997 /* Set number of vertical lines to 12 when option "oneday" is used */
998 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1000 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1001 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1003 /* Display vertical lines and graduations */
1004 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1006 /* Draw current graphs set */
1007 for (j = 0; j < group[i]; j++) {
1008 out_p = *(out + pos + j);
1009 if (g_type[i] == SVG_LINE_GRAPH) {
1011 printf("<path id=\"g%dp%d\" d=\"%s\" "
1012 "style=\"vector-effect: non-scaling-stroke; "
1013 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1014 "transform=\"scale(%f,%f)\"/>\n",
1015 svg_p->graph_no, pos + j, out_p,
1016 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
1018 yfactor * asfactor[j]);
1020 else if (*out_p) { /* Ignore flat bars */
1022 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1023 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1024 printf("%s\n", out_p);
1034 /* For next row of views */
1035 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1039 ***************************************************************************
1040 * Display CPU statistics in SVG.
1043 * @a Activity structure with statistics.
1044 * @curr Index in array for current sample statistics.
1045 * @action Action expected from current function.
1046 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1047 * flag indicating that a restart record has been previously
1048 * found (.@restart), and time used for the X axis origin
1050 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1052 * @record_hdr Pointer on record header of current stats sample.
1053 ***************************************************************************
1055 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1056 unsigned long long itv, struct record_header *record_hdr)
1058 struct stats_cpu *scc, *scp;
1059 unsigned long long tot_jiffies_c, tot_jiffies_p;
1060 unsigned long long deltot_jiffies;
1063 int g_type[] = {SVG_BAR_GRAPH};
1064 char *title[] = {"CPU load"};
1065 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1066 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1067 static double *spmin, *spmax;
1069 static int *outsize;
1074 if (action & F_BEGIN) {
1076 * Allocate arrays that will contain the graphs data
1077 * and the min/max values.
1079 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
1082 if (action & F_MAIN) {
1084 /* @nr[curr] cannot normally be greater than @nr_ini */
1085 if (a->nr[curr] > a->nr_ini) {
1086 a->nr_ini = a->nr[curr];
1090 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1092 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1093 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1095 /* Should current CPU (including CPU "all") be displayed? */
1096 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1101 * Yes: Compute the total number of jiffies spent by current processor.
1102 * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
1103 * already include them.
1105 tot_jiffies_c = scc->cpu_user + scc->cpu_nice +
1106 scc->cpu_sys + scc->cpu_idle +
1107 scc->cpu_iowait + scc->cpu_hardirq +
1108 scc->cpu_steal + scc->cpu_softirq;
1109 tot_jiffies_p = scp->cpu_user + scp->cpu_nice +
1110 scp->cpu_sys + scp->cpu_idle +
1111 scp->cpu_iowait + scp->cpu_hardirq +
1112 scp->cpu_steal + scp->cpu_softirq;
1114 /* Total number of jiffies spent on the interval */
1115 deltot_jiffies = get_interval(tot_jiffies_p, tot_jiffies_c);
1120 if (i) { /* Don't test CPU "all" here */
1122 * If the CPU is offline then it is omited from /proc/stat:
1123 * All the fields couldn't have been read and the sum of them is zero.
1124 * (Remember that guest/guest_nice times are already included in
1127 if (tot_jiffies_c == 0) {
1129 * Set current struct fields (which have been set to zero)
1130 * to values from previous iteration. Hence their values won't
1131 * jump from zero when the CPU comes back online.
1135 /* An offline CPU is not displayed */
1138 if (tot_jiffies_p == 0)
1139 /* CPU has just come back online */
1143 * Recalculate interval for current proc.
1144 * If result is 0 then current CPU is a tickless one.
1146 deltot_jiffies = get_per_cpu_interval(scc, scp);
1148 if (!deltot_jiffies) { /* Current CPU is tickless */
1150 val = 100.0; /* Tickless CPU: %idle = 100% */
1152 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1155 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1159 /* Check min/max values for %user, etc. */
1160 for (k = 0; k < j; k++) {
1161 if (0.0 < *(spmin + pos + k)) {
1162 *(spmin + pos + k) = 0.0;
1164 if (0.0 > *(spmax + pos + k)) {
1165 *(spmax + pos + k) = 0.0;
1170 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1172 out + pos + j, outsize + pos + j, svg_p->dt,
1173 spmin + pos + j, spmax + pos + j);
1178 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1180 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1181 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1182 out + pos, outsize + pos, svg_p->dt,
1183 spmin + pos, spmax + pos);
1187 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1189 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1191 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1192 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1193 out + pos, outsize + pos, svg_p->dt,
1194 spmin + pos, spmax + pos);
1197 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1199 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1200 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1201 out + pos + 1, outsize + pos + 1, svg_p->dt,
1202 spmin + pos + 1, spmax + pos + 1);
1206 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1208 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1210 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1211 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1212 out + pos + 1, outsize + pos + 1, svg_p->dt,
1213 spmin + pos + 1, spmax + pos + 1);
1216 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1218 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1220 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1221 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1223 out + pos + 2, outsize + pos + 2, svg_p->dt,
1224 spmin + pos + 2, spmax + pos + 2);
1228 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1229 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1230 out + pos + 2, outsize + pos + 2, svg_p->dt,
1231 spmin + pos + 2, spmax + pos + 2);
1235 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1236 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1237 out + pos + 3, outsize + pos + 3, svg_p->dt,
1238 spmin + pos + 3, spmax + pos + 3);
1240 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1241 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1242 out + pos + 4, outsize + pos + 4, svg_p->dt,
1243 spmin + pos + 4, spmax + pos + 4);
1245 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1247 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1248 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1249 out + pos + 5, outsize + pos + 5, svg_p->dt,
1250 spmin + pos + 5, spmax + pos + 5);
1252 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1253 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1254 out + pos + 6, outsize + pos + 6, svg_p->dt,
1255 spmin + pos + 6, spmax + pos + 6);
1257 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1258 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1259 out + pos + 7, outsize + pos + 7, svg_p->dt,
1260 spmin + pos + 7, spmax + pos + 7);
1262 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1263 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1264 out + pos + 8, outsize + pos + 8, svg_p->dt,
1265 spmin + pos + 8, spmax + pos + 8);
1274 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1276 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1277 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1278 out + pos + j, outsize + pos + j, svg_p->dt,
1279 spmin + pos + j, spmax + pos + j);
1283 if (action & F_END) {
1284 if (DISPLAY_IDLE(flags)) {
1285 /* Include additional %idle field */
1290 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
1292 /* Should current CPU (including CPU "all") be displayed? */
1293 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1299 /* This is CPU "all" */
1300 strcpy(item_name, "all");
1303 sprintf(item_name, "%d", i - 1);
1306 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1307 draw_activity_graphs(a->g_nr, g_type,
1308 title, g_title1, item_name, group1,
1309 spmin + pos, spmax + pos, out + pos, outsize + pos,
1313 draw_activity_graphs(a->g_nr, g_type,
1314 title, g_title2, item_name, group2,
1315 spmin + pos, spmax + pos, out + pos, outsize + pos,
1320 /* Free remaining structures */
1321 free_graphs(out, outsize, spmin, spmax);
1326 ***************************************************************************
1327 * Display task creation and context switch statistics in SVG.
1330 * @a Activity structure with statistics.
1331 * @curr Index in array for current sample statistics.
1332 * @action Action expected from current function.
1333 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1334 * flag indicating that a restart record has been previously
1335 * found (.@restart) and time used for the X axis origin
1337 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1338 * @record_hdr Pointer on record header of current stats sample.
1339 ***************************************************************************
1341 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1342 unsigned long long itv, struct record_header *record_hdr)
1345 *spc = (struct stats_pcsw *) a->buf[curr],
1346 *spp = (struct stats_pcsw *) a->buf[!curr];
1347 int group[] = {1, 1};
1348 int g_fields[] = {1, 0};
1349 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1350 char *title[] = {"Task creation", "Switching activity"};
1351 char *g_title[] = {"proc/s",
1353 static double *spmin, *spmax;
1355 static int *outsize;
1357 if (action & F_BEGIN) {
1359 * Allocate arrays that will contain the graphs data
1360 * and the min/max values.
1362 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1365 if (action & F_MAIN) {
1366 /* Check for min/max values */
1367 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1368 itv, spmin, spmax, g_fields);
1370 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1371 S_VALUE(spp->processes, spc->processes, itv),
1372 out, outsize, svg_p->restart);
1374 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1375 S_VALUE(spp->context_switch, spc->context_switch, itv),
1376 out + 1, outsize + 1, svg_p->restart);
1379 if (action & F_END) {
1380 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1381 spmin, spmax, out, outsize, svg_p, record_hdr);
1383 /* Free remaining structures */
1384 free_graphs(out, outsize, spmin, spmax);
1389 ***************************************************************************
1390 * Display swap statistics in SVG.
1393 * @a Activity structure with statistics.
1394 * @curr Index in array for current sample statistics.
1395 * @action Action expected from current function.
1396 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1397 * flag indicating that a restart record has been previously
1398 * found (.@restart) and time used for the X axis origin
1400 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1401 * @record_hdr Pointer on record header of current stats sample.
1402 ***************************************************************************
1404 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1405 unsigned long long itv, struct record_header *record_hdr)
1408 *ssc = (struct stats_swap *) a->buf[curr],
1409 *ssp = (struct stats_swap *) a->buf[!curr];
1411 int g_type[] = {SVG_LINE_GRAPH};
1412 char *title[] = {"Swap activity"};
1413 char *g_title[] = {"pswpin/s", "pswpout/s" };
1414 int g_fields[] = {0, 1};
1415 static double *spmin, *spmax;
1417 static int *outsize;
1419 if (action & F_BEGIN) {
1421 * Allocate arrays that will contain the graphs data
1422 * and the min/max values.
1424 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1427 if (action & F_MAIN) {
1428 /* Check for min/max values */
1429 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1430 itv, spmin, spmax, g_fields);
1432 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1433 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1434 out, outsize, svg_p->restart);
1436 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1437 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1438 out + 1, outsize + 1, svg_p->restart);
1441 if (action & F_END) {
1442 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1443 spmin, spmax, out, outsize, svg_p, record_hdr);
1445 /* Free remaining structures */
1446 free_graphs(out, outsize, spmin, spmax);
1451 ***************************************************************************
1452 * Display paging statistics in SVG.
1455 * @a Activity structure with statistics.
1456 * @curr Index in array for current sample statistics.
1457 * @action Action expected from current function.
1458 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1459 * flag indicating that a restart record has been previously
1460 * found (.@restart) and time used for the X axis origin
1462 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1463 * @record_hdr Pointer on record header of current stats sample.
1464 ***************************************************************************
1466 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1467 unsigned long long itv, struct record_header *record_hdr)
1470 *spc = (struct stats_paging *) a->buf[curr],
1471 *spp = (struct stats_paging *) a->buf[!curr];
1472 int group[] = {2, 2, 4};
1473 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1474 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1475 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1476 "fault/s", "majflt/s",
1477 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1478 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1479 static double *spmin, *spmax;
1481 static int *outsize;
1483 if (action & F_BEGIN) {
1485 * Allocate arrays that will contain the graphs data
1486 * and the min/max values.
1488 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1491 if (action & F_MAIN) {
1492 /* Check for min/max values */
1493 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1494 itv, spmin, spmax, g_fields);
1496 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1497 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1498 out, outsize, svg_p->restart);
1500 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1501 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1502 out + 1, outsize + 1, svg_p->restart);
1504 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1505 S_VALUE(spp->pgfault, spc->pgfault, itv),
1506 out + 2, outsize + 2, svg_p->restart);
1508 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1509 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1510 out + 3, outsize + 3, svg_p->restart);
1512 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1513 S_VALUE(spp->pgfree, spc->pgfree, itv),
1514 out + 4, outsize + 4, svg_p->restart);
1516 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1517 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1518 out + 5, outsize + 5, svg_p->restart);
1520 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1521 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1522 out + 6, outsize + 6, svg_p->restart);
1524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1525 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1526 out + 7, outsize + 7, svg_p->restart);
1529 if (action & F_END) {
1530 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1531 spmin, spmax, out, outsize, svg_p, record_hdr);
1533 /* Free remaining structures */
1534 free_graphs(out, outsize, spmin, spmax);
1539 ***************************************************************************
1540 * Display I/O and transfer rate statistics in SVG.
1543 * @a Activity structure with statistics.
1544 * @curr Index in array for current sample statistics.
1545 * @action Action expected from current function.
1546 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1547 * flag indicating that a restart record has been previously
1548 * found (.@restart) and time used for the X axis origin
1550 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1551 * @record_hdr Pointer on record header of current stats sample.
1552 ***************************************************************************
1554 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1555 unsigned long long itv, struct record_header *record_hdr)
1558 *sic = (struct stats_io *) a->buf[curr],
1559 *sip = (struct stats_io *) a->buf[!curr];
1560 int group[] = {3, 2};
1561 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1562 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1563 char *g_title[] = {"tps", "rtps", "wtps",
1564 "bread/s", "bwrtn/s"};
1565 int g_fields[] = {0, 1, 2, 3, 4};
1566 static double *spmin, *spmax;
1568 static int *outsize;
1570 if (action & F_BEGIN) {
1572 * Allocate arrays that will contain the graphs data
1573 * and the min/max values.
1575 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1578 if (action & F_MAIN) {
1579 /* Check for min/max values */
1580 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1581 itv, spmin, spmax, g_fields);
1584 * If we get negative values, this is probably because
1585 * one or more devices/filesystems have been unmounted.
1586 * We display 0.0 in this case though we should rather tell
1587 * the user that the value cannot be calculated here.
1590 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1591 sic->dk_drive < sip->dk_drive ? 0.0 :
1592 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1593 out, outsize, svg_p->restart);
1595 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1596 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1597 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1598 out + 1, outsize + 1, svg_p->restart);
1600 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1601 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1602 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1603 out + 2, outsize + 2, svg_p->restart);
1605 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1606 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1607 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1608 out + 3, outsize + 3, svg_p->restart);
1610 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1611 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1612 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1613 out + 4, outsize + 4, svg_p->restart);
1616 if (action & F_END) {
1617 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1618 spmin, spmax, out, outsize, svg_p, record_hdr);
1620 /* Free remaining structures */
1621 free_graphs(out, outsize, spmin, spmax);
1626 ***************************************************************************
1627 * Display memory statistics in SVG.
1630 * @a Activity structure with statistics.
1631 * @curr Index in array for current sample statistics.
1632 * @action Action expected from current function.
1633 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1634 * flag indicating that a restart record has been previously
1635 * found (.@restart) and time used for the X axis origin
1637 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1638 * @record_hdr Pointer on record header of current stats sample.
1639 ***************************************************************************
1641 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1642 unsigned long long itv, struct record_header *record_hdr)
1645 *smc = (struct stats_memory *) a->buf[curr];
1646 int group1[] = {3, 1, 3, 1, 3, 5};
1647 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1648 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1649 int group2[] = {3, 1, 1};
1650 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1651 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1652 "Memory utilization (3)", "Memory utilization (4)",
1653 "Memory utilization (5)", "Memory utilization (6)"};
1654 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1655 "Swap utilization (3)"};
1656 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1657 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1658 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1660 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1662 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1663 static double *spmin, *spmax;
1665 static int *outsize;
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 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1683 if (tval > *(spmax + 3)) {
1684 *(spmax + 3) = tval;
1686 if (tval < *(spmin + 3)) {
1687 *(spmin + 3) = tval;
1689 /* Compute %commit min/max values */
1690 tval = (smc->tlmkb + smc->tlskb) ?
1691 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1692 if (tval > *(spmax + 7)) {
1693 *(spmax + 7) = tval;
1695 if (tval < *(spmin + 7)) {
1696 *(spmin + 7) = tval;
1698 /* Compute %swpused min/max values */
1700 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1701 if (tval > *(spmax + 19)) {
1702 *(spmax + 19) = tval;
1704 if (tval < *(spmin + 19)) {
1705 *(spmin + 19) = tval;
1707 /* Compute %swpcad min/max values */
1708 tval = (smc->tlskb - smc->frskb) ?
1709 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1710 if (tval > *(spmax + 20)) {
1711 *(spmax + 20) = tval;
1713 if (tval < *(spmin + 20)) {
1714 *(spmin + 20) = tval;
1716 /* Compute memused min/max values in MB */
1717 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1718 if (tval > *(spmax + 2)) {
1719 *(spmax + 2) = tval;
1721 if (tval < *(spmin + 2)) {
1722 *(spmin + 2) = tval;
1724 /* Compute swpused min/max values in MB */
1725 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1726 if (tval > *(spmax + 17)) {
1727 *(spmax + 17) = tval;
1729 if (tval < *(spmin + 17)) {
1730 *(spmin + 17) = tval;
1734 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1735 ((double) smc->frmkb) / 1024,
1736 out, outsize, svg_p->restart);
1738 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1739 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1740 out + 2, outsize + 2, svg_p->restart);
1742 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1743 ((double) smc->availablekb) / 1024,
1744 out + 1, outsize + 1, svg_p->restart);
1746 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1747 ((double) smc->bufkb) / 1024,
1748 out + 4, outsize + 4, svg_p->restart);
1750 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1751 ((double) smc->camkb) / 1024,
1752 out + 5, outsize + 5, svg_p->restart);
1754 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1755 ((double) smc->frskb) / 1024,
1756 out + 16, outsize + 16, svg_p->restart);
1758 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1759 ((double) (smc->tlskb - smc->frskb)) / 1024,
1760 out + 17, outsize + 17, svg_p->restart);
1762 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1763 ((double) smc->caskb) / 1024,
1764 out + 18, outsize + 18, svg_p->restart);
1766 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1767 ((double) smc->comkb) / 1024,
1768 out + 6, outsize + 6, svg_p->restart);
1770 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1771 ((double) smc->activekb) / 1024,
1772 out + 8, outsize + 8, svg_p->restart);
1774 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1775 ((double) smc->inactkb) / 1024,
1776 out + 9, outsize + 9, svg_p->restart);
1778 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1779 ((double) smc->dirtykb) / 1024,
1780 out + 10, outsize + 10, svg_p->restart);
1782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1783 ((double) smc->anonpgkb) / 1024,
1784 out + 11, outsize + 11, svg_p->restart);
1786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1787 ((double) smc->slabkb) / 1024,
1788 out + 12, outsize + 12, svg_p->restart);
1790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1791 ((double) smc->kstackkb) / 1024,
1792 out + 13, outsize + 13, svg_p->restart);
1794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1795 ((double) smc->pgtblkb) / 1024,
1796 out + 14, outsize + 14, svg_p->restart);
1798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1799 ((double) smc->vmusedkb) / 1024,
1800 out + 15, outsize + 15, svg_p->restart);
1802 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1805 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1806 out + 3, outsize + 3, svg_p->dt);
1808 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1810 (smc->tlmkb + smc->tlskb) ?
1811 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1812 out + 7, outsize + 7, svg_p->dt);
1814 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1817 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1818 out + 19, outsize + 19, svg_p->dt);
1820 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1822 (smc->tlskb - smc->frskb) ?
1823 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1824 out + 20, outsize + 20, svg_p->dt);
1827 if (action & F_END) {
1829 /* Conversion kB -> MB */
1830 for (i = 0; i < 17; i++) {
1831 *(spmin + g_fields[i]) /= 1024;
1832 *(spmax + g_fields[i]) /= 1024;
1835 if (DISPLAY_MEMORY(a->opt_flags)) {
1836 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1837 g_type1, title1, g_title1, NULL, group1,
1838 spmin, spmax, out, outsize, svg_p, record_hdr);
1841 if (DISPLAY_SWAP(a->opt_flags)) {
1842 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1843 spmin + 16, spmax + 16, out + 16, outsize + 16,
1847 /* Free remaining structures */
1848 free_graphs(out, outsize, spmin, spmax);
1853 ***************************************************************************
1854 * Display kernel tables statistics in SVG.
1857 * @a Activity structure with statistics.
1858 * @curr Index in array for current sample statistics.
1859 * @action Action expected from current function.
1860 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1861 * flag indicating that a restart record has been previously
1862 * found (.@restart) and time used for the X axis origin
1864 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1865 * @record_hdr Pointer on record header of current stats sample.
1866 ***************************************************************************
1868 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1869 unsigned long long itv, struct record_header *record_hdr)
1871 struct stats_ktables
1872 *skc = (struct stats_ktables *) a->buf[curr];
1873 int group[] = {3, 1};
1874 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1875 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1876 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1878 int g_fields[] = {1, 2, 0, 3};
1879 static double *spmin, *spmax;
1881 static int *outsize;
1883 if (action & F_BEGIN) {
1885 * Allocate arrays that will contain the graphs data
1886 * and the min/max values.
1888 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1891 if (action & F_MAIN) {
1892 /* Check for min/max values */
1893 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1894 itv, spmin, spmax, g_fields);
1896 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1897 (unsigned long long) skc->dentry_stat,
1898 out, outsize, svg_p->restart);
1900 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1901 (unsigned long long) skc->file_used,
1902 out + 1, outsize + 1, svg_p->restart);
1904 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1905 (unsigned long long) skc->inode_used,
1906 out + 2, outsize + 2, svg_p->restart);
1908 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1909 (unsigned long long) skc->pty_nr,
1910 out + 3, outsize + 3, svg_p->restart);
1913 if (action & F_END) {
1914 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1915 spmin, spmax, out, outsize, svg_p, record_hdr);
1917 /* Free remaining structures */
1918 free_graphs(out, outsize, spmin, spmax);
1923 ***************************************************************************
1924 * Display queue and load statistics in SVG.
1927 * @a Activity structure with statistics.
1928 * @curr Index in array for current sample statistics.
1929 * @action Action expected from current function.
1930 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1931 * flag indicating that a restart record has been previously
1932 * found (.@restart) and time used for the X axis origin
1934 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1935 * @record_hdr Pointer on record header of current stats sample.
1936 ***************************************************************************
1938 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1939 unsigned long long itv, struct record_header *record_hdr)
1942 *sqc = (struct stats_queue *) a->buf[curr];
1943 int group[] = {2, 1, 3};
1944 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1945 char *title[] = {"Queue length", "Task list", "Load average"};
1946 char *g_title[] = {"~runq-sz", "~blocked",
1948 "ldavg-1", "ldavg-5", "ldavg-15"};
1949 int g_fields[] = {0, 1, 3, 4, 5, 2};
1950 static double *spmin, *spmax;
1952 static int *outsize;
1954 if (action & F_BEGIN) {
1956 * Allocate arrays that will contain the graphs data
1957 * and the min/max values.
1959 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1962 if (action & F_MAIN) {
1963 /* Check for min/max values */
1964 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1965 itv, spmin, spmax, g_fields);
1967 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1968 (unsigned long long) sqc->nr_running,
1969 out, outsize, svg_p->restart);
1971 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1972 (unsigned long long) sqc->procs_blocked,
1973 out + 1, outsize + 1, svg_p->restart);
1975 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1976 (unsigned long long) sqc->nr_threads,
1977 out + 2, outsize + 2, svg_p->restart);
1979 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1980 (double) sqc->load_avg_1 / 100,
1981 out + 3, outsize + 3, svg_p->restart);
1983 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1984 (double) sqc->load_avg_5 / 100,
1985 out + 4, outsize + 4, svg_p->restart);
1987 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1988 (double) sqc->load_avg_15 / 100,
1989 out + 5, outsize + 5, svg_p->restart);
1992 if (action & F_END) {
1993 /* Fix min/max values for load average */
1994 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1995 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1996 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1998 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1999 spmin, spmax, out, outsize, svg_p, record_hdr);
2001 /* Free remaining structures */
2002 free_graphs(out, outsize, spmin, spmax);
2007 ***************************************************************************
2008 * Display disk statistics in SVG.
2011 * @a Activity structure with statistics.
2012 * @curr Index in array for current sample statistics.
2013 * @action Action expected from current function.
2014 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2015 * flag indicating that a restart record has been previously
2016 * found (.@restart) and time used for the X axis origin
2018 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2019 * @record_hdr Pointer on record header of current stats sample.
2020 ***************************************************************************
2022 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2023 unsigned long long itv, struct record_header *record_hdr)
2025 struct stats_disk *sdc, *sdp, sdpzero;
2026 struct ext_disk_stats xds;
2027 int group[] = {1, 2, 2, 2, 1};
2028 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2029 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2030 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
2031 "Disk statistics (3)", "Disk statistics (4)",
2032 "Disk statistics (5)"};
2033 char *g_title[] = {"tps",
2035 "areq-sz", "aqu-sz",
2038 int g_fields[] = {0, 1, 2};
2039 unsigned int local_types_nr[] = {1, 0, 0};
2040 static double *spmin, *spmax;
2042 static int *outsize;
2043 char *item_name, *persist_dev_name;
2044 double rkB, wkB, aqusz;
2045 int i, j, k, pos, restart, *unregistered;
2047 if (action & F_BEGIN) {
2049 * Allocate arrays (#0..7) that will contain the graphs data
2050 * and the min/max values.
2051 * Also allocate one additional array (#8) for each disk device:
2052 * spmax + 8 will contain the device major number,
2053 * spmin + 8 will contain the device minor number,
2054 * outsize + 8 will contain a positive value (TRUE) if the device
2055 * has either still not been registered, or has been unregistered.
2057 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2060 if (action & F_MAIN) {
2061 memset(&sdpzero, 0, STATS_DISK_SIZE);
2062 restart = svg_p->restart;
2064 * Mark previously registered devices as now
2065 * possibly unregistered for all graphs.
2067 for (k = 0; k < svg_p->nr_max; k++) {
2068 unregistered = outsize + k * 9 + 8;
2069 if (*unregistered == FALSE) {
2070 *unregistered = MAYBE;
2074 /* For each device structure */
2075 for (i = 0; i < a->nr[curr]; i++) {
2076 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2078 /* Look for corresponding graph */
2079 for (k = 0; k < svg_p->nr_max; k++) {
2080 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2081 (sdc->minor == *(spmin + k * 9 + 8)))
2085 if (k == svg_p->nr_max) {
2086 /* Graph not found: Look for first free entry */
2087 for (k = 0; k < svg_p->nr_max; k++) {
2088 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2091 if (k == svg_p->nr_max) {
2092 /* No free graph entry: Extend all buffers */
2093 reallocate_all_graph_lines(svg_p->nr_max,
2094 &out, &outsize, &spmin, &spmax);
2099 unregistered = outsize + pos + 8;
2101 j = check_disk_reg(a, curr, !curr, i);
2103 /* This is a newly registered interface. Previous stats are zero */
2107 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2111 * If current device was marked as previously unregistered,
2112 * then set restart variable to TRUE so that the graph will be
2113 * discontinuous, and mark it as now registered.
2115 if (*unregistered == TRUE) {
2118 *unregistered = FALSE;
2120 if (*(spmax + pos + 8) == -DBL_MAX) {
2121 /* Save device major and minor numbers (if not already done) */
2122 *(spmax + pos + 8) = sdc->major;
2123 *(spmin + pos + 8) = sdc->minor;
2126 /* Check for min/max values */
2127 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2128 itv, spmin + pos, spmax + pos, g_fields);
2130 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2131 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2132 if (rkB < *(spmin + pos + 1)) {
2133 *(spmin + pos + 1) = rkB;
2135 if (rkB > *(spmax + pos + 1)) {
2136 *(spmax + pos + 1) = rkB;
2138 if (wkB < *(spmin + pos + 2)) {
2139 *(spmin + pos + 2) = wkB;
2141 if (wkB > *(spmax + pos + 2)) {
2142 *(spmax + pos + 2) = wkB;
2145 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2146 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2147 *(spmin + pos + 3) = xds.arqsz / 2;
2149 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2150 *(spmax + pos + 3) = xds.arqsz / 2;
2152 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2153 if (aqusz < *(spmin + pos + 4)) {
2154 *(spmin + pos + 4) = aqusz;
2156 if (aqusz > *(spmax + pos + 4)) {
2157 *(spmax + pos + 4) = aqusz;
2159 if (xds.await < *(spmin + pos + 5)) {
2160 *(spmin + pos + 5) = xds.await;
2162 if (xds.await > *(spmax + pos + 5)) {
2163 *(spmax + pos + 5) = xds.await;
2165 if (xds.svctm < *(spmin + pos + 6)) {
2166 *(spmin + pos + 6) = xds.svctm;
2168 if (xds.svctm > *(spmax + pos + 6)) {
2169 *(spmax + pos + 6) = xds.svctm;
2171 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2172 *(spmin + pos + 7) = xds.util / 10.0;
2174 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2175 *(spmax + pos + 7) = xds.util / 10.0;
2179 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2180 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2181 out + pos, outsize + pos, restart);
2183 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2184 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2185 out + pos + 1, outsize + pos + 1, restart);
2187 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2188 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2189 out + pos + 2, outsize + pos + 2, restart);
2191 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2193 out + pos + 3, outsize + pos + 3, restart);
2195 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2197 out + pos + 4, outsize + pos + 4, restart);
2199 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2201 out + pos + 5, outsize + pos + 5, restart);
2203 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2205 out + pos + 6, outsize + pos + 6, restart);
2207 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2208 0.0, xds.util / 10.0,
2209 out + pos + 7, outsize + pos + 7, svg_p->dt);
2212 /* Mark devices not seen here as now unregistered */
2213 for (k = 0; k < svg_p->nr_max; k++) {
2214 unregistered = outsize + k * 9 + 8;
2215 if (*unregistered != FALSE) {
2216 *unregistered = TRUE;
2221 if (action & F_END) {
2222 for (i = 0; i < svg_p->nr_max; i++) {
2223 /* Check if there is something to display */
2229 persist_dev_name = NULL;
2231 if (DISPLAY_PERSIST_NAME_S(flags)) {
2232 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2236 if (persist_dev_name) {
2237 item_name = persist_dev_name;
2240 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2241 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2245 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2246 USE_PRETTY_OPTION(flags));
2250 draw_activity_graphs(a->g_nr, g_type,
2251 title, g_title, item_name, group,
2252 spmin + pos, spmax + pos, out + pos, outsize + pos,
2256 /* Free remaining structures */
2257 free_graphs(out, outsize, spmin, spmax);
2262 ***************************************************************************
2263 * Display network interfaces statistics in SVG.
2266 * @a Activity structure with statistics.
2267 * @curr Index in array for current sample statistics.
2268 * @action Action expected from current function.
2269 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2270 * flag indicating that a restart record has been previously
2271 * found (.@restart) and time used for the X axis origin
2273 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2274 * @record_hdr Pointer on record header of current stats sample.
2275 ***************************************************************************
2277 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2278 unsigned long long itv, struct record_header *record_hdr)
2280 struct stats_net_dev *sndc, *sndp, sndzero;
2281 int group[] = {2, 2, 3, 1};
2282 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2284 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2285 "Network statistics (3)", "Network statistics (4)"};
2286 char *g_title[] = {"rxpck/s", "txpck/s",
2288 "rxcmp/s", "txcmp/s", "rxmcst/s",
2290 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2291 unsigned int local_types_nr[] = {7, 0, 0};
2292 static double *spmin, *spmax;
2294 static int *outsize;
2296 double rxkb, txkb, ifutil;
2297 int i, j, k, pos, restart, *unregistered;
2299 if (action & F_BEGIN) {
2301 * Allocate arrays (#0..7) that will contain the graphs data
2302 * and the min/max values.
2303 * Also allocate one additional array (#8) for each interface:
2304 * out + 8 will contain the interface name,
2305 * outsize + 8 will contain a positive value (TRUE) if the interface
2306 * has either still not been registered, or has been unregistered.
2308 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2311 if (action & F_MAIN) {
2312 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2313 restart = svg_p->restart;
2315 * Mark previously registered interfaces as now
2316 * possibly unregistered for all graphs.
2318 for (k = 0; k < svg_p->nr_max; k++) {
2319 unregistered = outsize + k * 9 + 8;
2320 if (*unregistered == FALSE) {
2321 *unregistered = MAYBE;
2325 /* For each network interfaces structure */
2326 for (i = 0; i < a->nr[curr]; i++) {
2327 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2329 /* Look for corresponding graph */
2330 for (k = 0; k < svg_p->nr_max; k++) {
2331 item_name = *(out + k * 9 + 8);
2332 if (!strcmp(sndc->interface, item_name))
2336 if (k == svg_p->nr_max) {
2337 /* Graph not found: Look for first free entry */
2338 for (k = 0; k < svg_p->nr_max; k++) {
2339 item_name = *(out + k * 9 + 8);
2340 if (!strcmp(item_name, ""))
2343 if (k == svg_p->nr_max) {
2344 /* No free graph entry: Extend all buffers */
2345 reallocate_all_graph_lines(svg_p->nr_max,
2346 &out, &outsize, &spmin, &spmax);
2352 unregistered = outsize + pos + 8;
2354 j = check_net_dev_reg(a, curr, !curr, i);
2356 /* This is a newly registered interface. Previous stats are zero */
2360 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2364 * If current interface was marked as previously unregistered,
2365 * then set restart variable to TRUE so that the graph will be
2366 * discontinuous, and mark it as now registered.
2368 if (*unregistered == TRUE) {
2371 *unregistered = FALSE;
2373 if (!item_name[0]) {
2374 /* Save network interface name (if not already done) */
2375 strncpy(item_name, sndc->interface, CHUNKSIZE);
2376 item_name[CHUNKSIZE - 1] = '\0';
2379 /* Check for min/max values */
2380 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2381 itv, spmin + pos, spmax + pos, g_fields);
2383 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2384 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2385 ifutil = compute_ifutil(sndc, rxkb, txkb);
2386 if (ifutil < *(spmin + pos + 7)) {
2387 *(spmin + pos + 7) = ifutil;
2389 if (ifutil > *(spmax + pos + 7)) {
2390 *(spmax + pos + 7) = ifutil;
2394 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2395 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2396 out + pos, outsize + pos, restart);
2398 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2399 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2400 out + pos + 1, outsize + pos + 1, restart);
2402 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2404 out + pos + 2, outsize + pos + 2, restart);
2406 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2408 out + pos + 3, outsize + pos + 3, restart);
2410 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2411 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2412 out + pos + 4, outsize + pos + 4, restart);
2414 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2415 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2416 out + pos + 5, outsize + pos + 5, restart);
2418 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2419 S_VALUE(sndp->multicast, sndc->multicast, itv),
2420 out + pos + 6, outsize + pos + 6, restart);
2422 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2424 out + pos + 7, outsize + pos + 7, svg_p->dt);
2427 /* Mark interfaces not seen here as now unregistered */
2428 for (k = 0; k < svg_p->nr_max; k++) {
2429 unregistered = outsize + k * 9 + 8;
2430 if (*unregistered != FALSE) {
2431 *unregistered = TRUE;
2436 if (action & F_END) {
2437 for (i = 0; i < svg_p->nr_max; i++) {
2439 * Check if there is something to display.
2440 * Don't test sndc->interface because maybe the network
2441 * interface has been registered later.
2447 /* Recalculate min and max values in kB, not in B */
2448 *(spmin + pos + 2) /= 1024;
2449 *(spmax + pos + 2) /= 1024;
2450 *(spmin + pos + 3) /= 1024;
2451 *(spmax + pos + 3) /= 1024;
2453 item_name = *(out + pos + 8);
2454 draw_activity_graphs(a->g_nr, g_type,
2455 title, g_title, item_name, group,
2456 spmin + pos, spmax + pos, out + pos, outsize + pos,
2460 /* Free remaining structures */
2461 free_graphs(out, outsize, spmin, spmax);
2466 ***************************************************************************
2467 * Display network interface errors statistics in SVG.
2470 * @a Activity structure with statistics.
2471 * @curr Index in array for current sample statistics.
2472 * @action Action expected from current function.
2473 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2474 * flag indicating that a restart record has been previously
2475 * found (.@restart) and time used for the X axis origin
2477 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2478 * @record_hdr Pointer on record header of current stats sample.
2479 ***************************************************************************
2481 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2482 unsigned long long itv, struct record_header *record_hdr)
2484 struct stats_net_edev *snedc, *snedp, snedzero;
2485 int group[] = {2, 2, 2, 3};
2486 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2488 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2489 "Network errors statistics (3)", "Network errors statistics (4)"};
2490 char *g_title[] = {"rxerr/s", "txerr/s",
2491 "rxdrop/s", "txdrop/s",
2492 "rxfifo/s", "txfifo/s",
2493 "coll/s", "txcarr/s", "rxfram/s"};
2494 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2495 static double *spmin, *spmax;
2497 static int *outsize;
2499 int i, j, k, pos, restart, *unregistered;
2501 if (action & F_BEGIN) {
2503 * Allocate arrays (#0..8) that will contain the graphs data
2504 * and the min/max values.
2505 * Also allocate one additional array (#9) for each interface:
2506 * out + 9 will contain the interface name,
2507 * outsize + 9 will contain a positive value (TRUE) if the interface
2508 * has either still not been registered, or has been unregistered.
2510 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
2513 if (action & F_MAIN) {
2514 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2515 restart = svg_p->restart;
2517 * Mark previously registered interfaces as now
2518 * possibly unregistered for all graphs.
2520 for (k = 0; k < svg_p->nr_max; k++) {
2521 unregistered = outsize + k * 10 + 9;
2522 if (*unregistered == FALSE) {
2523 *unregistered = MAYBE;
2527 /* For each network interfaces structure */
2528 for (i = 0; i < a->nr[curr]; i++) {
2529 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2530 if (!strcmp(snedc->interface, ""))
2531 /* Empty structure: This is the end of the list */
2534 /* Look for corresponding graph */
2535 for (k = 0; k < svg_p->nr_max; k++) {
2536 item_name = *(out + k * 10 + 9);
2537 if (!strcmp(snedc->interface, item_name))
2541 if (k == svg_p->nr_max) {
2542 /* Graph not found: Look for first free entry */
2543 for (k = 0; k < svg_p->nr_max; k++) {
2544 item_name = *(out + k * 10 + 9);
2545 if (!strcmp(item_name, ""))
2548 if (k == svg_p->nr_max) {
2549 /* No free graph entry: Extend all buffers */
2550 reallocate_all_graph_lines(svg_p->nr_max,
2551 &out, &outsize, &spmin, &spmax);
2557 unregistered = outsize + pos + 9;
2559 j = check_net_edev_reg(a, curr, !curr, i);
2561 /* This is a newly registered interface. Previous stats are zero */
2565 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2569 * If current interface was marked as previously unregistered,
2570 * then set restart variable to TRUE so that the graph will be
2571 * discontinuous, and mark it as now registered.
2573 if (*unregistered == TRUE) {
2576 *unregistered = FALSE;
2578 if (!item_name[0]) {
2579 /* Save network interface name (if not already done) */
2580 strncpy(item_name, snedc->interface, CHUNKSIZE);
2581 item_name[CHUNKSIZE - 1] = '\0';
2584 /* Check for min/max values */
2585 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2586 itv, spmin + pos, spmax + pos, g_fields);
2589 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2590 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2591 out + pos, outsize + pos, restart);
2593 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2594 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2595 out + pos + 1, outsize + pos + 1, restart);
2597 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2598 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2599 out + pos + 2, outsize + pos + 2, restart);
2601 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2602 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2603 out + pos + 3, outsize + pos + 3, restart);
2605 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2606 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2607 out + pos + 4, outsize + pos + 4, restart);
2609 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2610 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2611 out + pos + 5, outsize + pos + 5, restart);
2613 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2614 S_VALUE(snedp->collisions, snedc->collisions, itv),
2615 out + pos + 6, outsize + pos + 6, restart);
2617 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2618 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2619 out + pos + 7, outsize + pos + 7, restart);
2621 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2622 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2623 out + pos + 8, outsize + pos + 8, restart);
2626 /* Mark interfaces not seen here as now unregistered */
2627 for (k = 0; k < svg_p->nr_max; k++) {
2628 unregistered = outsize + k * 10 + 9;
2629 if (*unregistered != FALSE) {
2630 *unregistered = TRUE;
2635 if (action & F_END) {
2636 for (i = 0; i < svg_p->nr_max; i++) {
2638 * Check if there is something to display.
2639 * Don't test snedc->interface because maybe the network
2640 * interface has been registered later.
2646 item_name = *(out + pos + 9);
2647 draw_activity_graphs(a->g_nr, g_type,
2648 title, g_title, item_name, group,
2649 spmin + pos, spmax + pos, out + pos, outsize + pos,
2653 /* Free remaining structures */
2654 free_graphs(out, outsize, spmin, spmax);
2659 ***************************************************************************
2660 * Display NFS client statistics in SVG.
2663 * @a Activity structure with statistics.
2664 * @curr Index in array for current sample statistics.
2665 * @action Action expected from current function.
2666 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2667 * flag indicating that a restart record has been previously
2668 * found (.@restart) and time used for the X axis origin
2670 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2671 * @record_hdr Pointer on record header of current stats sample.
2672 ***************************************************************************
2674 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2675 unsigned long long itv, struct record_header *record_hdr)
2677 struct stats_net_nfs
2678 *snnc = (struct stats_net_nfs *) a->buf[curr],
2679 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2680 int group[] = {2, 2, 2};
2681 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2682 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2683 "NFS client statistics (3)"};
2684 char *g_title[] = {"call/s", "retrans/s",
2685 "read/s", "write/s",
2686 "access/s", "getatt/s"};
2687 int g_fields[] = {0, 1, 2, 3, 4, 5};
2688 static double *spmin, *spmax;
2690 static int *outsize;
2692 if (action & F_BEGIN) {
2694 * Allocate arrays that will contain the graphs data
2695 * and the min/max values.
2697 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2700 if (action & F_MAIN) {
2701 /* Check for min/max values */
2702 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2703 itv, spmin, spmax, g_fields);
2706 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2707 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2708 out, outsize, svg_p->restart);
2710 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2711 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2712 out + 1, outsize + 1, svg_p->restart);
2714 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2715 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2716 out + 2, outsize + 2, svg_p->restart);
2718 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2719 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2720 out + 3, outsize + 3, svg_p->restart);
2722 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2723 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2724 out + 4, outsize + 4, svg_p->restart);
2726 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2727 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2728 out + 5, outsize + 5, svg_p->restart);
2731 if (action & F_END) {
2732 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2733 spmin, spmax, out, outsize, svg_p, record_hdr);
2735 /* Free remaining structures */
2736 free_graphs(out, outsize, spmin, spmax);
2741 ***************************************************************************
2742 * Display NFS server statistics in SVG.
2745 * @a Activity structure with statistics.
2746 * @curr Index in array for current sample statistics.
2747 * @action Action expected from current function.
2748 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2749 * flag indicating that a restart record has been previously
2750 * found (.@restart) and time used for the X axis origin
2752 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2753 * @record_hdr Pointer on record header of current stats sample.
2754 ***************************************************************************
2756 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2757 unsigned long long itv, struct record_header *record_hdr)
2759 struct stats_net_nfsd
2760 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2761 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2762 int group[] = {2, 3, 2, 2, 2};
2763 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2764 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2765 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2766 "NFS server statistics (3)", "NFS server statistics (4)",
2767 "NFS server statistics (5)"};
2768 char *g_title[] = {"scall/s", "badcall/s",
2769 "packet/s", "udp/s", "tcp/s",
2771 "sread/s", "swrite/s",
2772 "saccess/s", "sgetatt/s"};
2773 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2774 static double *spmin, *spmax;
2776 static int *outsize;
2778 if (action & F_BEGIN) {
2780 * Allocate arrays that will contain the graphs data
2781 * and the min/max values.
2783 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2786 if (action & F_MAIN) {
2787 /* Check for min/max values */
2788 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2789 itv, spmin, spmax, g_fields);
2792 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2793 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2794 out, outsize, svg_p->restart);
2796 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2797 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2798 out + 1, outsize + 1, svg_p->restart);
2800 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2801 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2802 out + 2, outsize + 2, svg_p->restart);
2804 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2805 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2806 out + 3, outsize + 3, svg_p->restart);
2808 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2809 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2810 out + 4, outsize + 4, svg_p->restart);
2812 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2813 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2814 out + 5, outsize + 5, svg_p->restart);
2816 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2817 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2818 out + 6, outsize + 6, svg_p->restart);
2820 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2821 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2822 out + 7, outsize + 7, svg_p->restart);
2824 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2825 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2826 out + 8, outsize + 8, svg_p->restart);
2828 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2829 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2830 out + 9, outsize + 9, svg_p->restart);
2832 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2833 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2834 out + 10, outsize + 10, svg_p->restart);
2837 if (action & F_END) {
2838 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2839 spmin, spmax, out, outsize, svg_p, record_hdr);
2841 /* Free remaining structures */
2842 free_graphs(out, outsize, spmin, spmax);
2847 ***************************************************************************
2848 * Display network socket statistics in SVG.
2851 * @a Activity structure with statistics.
2852 * @curr Index in array for current sample statistics.
2853 * @action Action expected from current function.
2854 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2855 * flag indicating that a restart record has been previously
2856 * found (.@restart) and time used for the X axis origin
2858 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2859 * @record_hdr Pointer on record header of current stats sample.
2860 ***************************************************************************
2862 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2863 unsigned long long itv, struct record_header *record_hdr)
2865 struct stats_net_sock
2866 *snsc = (struct stats_net_sock *) a->buf[curr];
2867 int group[] = {1, 5};
2868 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2869 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2870 char *g_title[] = {"~totsck",
2871 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2872 int g_fields[] = {0, 1, 5, 2, 3, 4};
2873 static double *spmin, *spmax;
2875 static int *outsize;
2877 if (action & F_BEGIN) {
2879 * Allocate arrays that will contain the graphs data
2880 * and the min/max values.
2882 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2885 if (action & F_MAIN) {
2886 /* Check for min/max values */
2887 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2888 itv, spmin, spmax, g_fields);
2890 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2891 (unsigned long long) snsc->sock_inuse,
2892 out, outsize, svg_p->restart);
2894 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2895 (unsigned long long) snsc->tcp_inuse,
2896 out + 1, outsize + 1, svg_p->restart);
2898 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2899 (unsigned long long) snsc->udp_inuse,
2900 out + 2, outsize + 2, svg_p->restart);
2902 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2903 (unsigned long long) snsc->raw_inuse,
2904 out + 3, outsize + 3, svg_p->restart);
2906 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2907 (unsigned long long) snsc->frag_inuse,
2908 out + 4, outsize + 4, svg_p->restart);
2910 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2911 (unsigned long long) snsc->tcp_tw,
2912 out + 5, outsize + 5, svg_p->restart);
2915 if (action & F_END) {
2916 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2917 spmin, spmax, out, outsize, svg_p, record_hdr);
2919 /* Free remaining structures */
2920 free_graphs(out, outsize, spmin, spmax);
2925 ***************************************************************************
2926 * Display IPv4 network statistics in SVG.
2929 * @a Activity structure with statistics.
2930 * @curr Index in array for current sample statistics.
2931 * @action Action expected from current function.
2932 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2933 * flag indicating that a restart record has been previously
2934 * found (.@restart) and time used for the X axis origin
2936 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2937 * @record_hdr Pointer on record header of current stats sample.
2938 ***************************************************************************
2940 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2941 unsigned long long itv, struct record_header *record_hdr)
2944 *snic = (struct stats_net_ip *) a->buf[curr],
2945 *snip = (struct stats_net_ip *) a->buf[!curr];
2946 int group[] = {4, 2, 2};
2947 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2948 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2949 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2950 "asmrq/s", "asmok/s",
2951 "fragok/s", "fragcrt/s"};
2952 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2953 static double *spmin, *spmax;
2955 static int *outsize;
2957 if (action & F_BEGIN) {
2959 * Allocate arrays that will contain the graphs data
2960 * and the min/max values.
2962 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2965 if (action & F_MAIN) {
2966 /* Check for min/max values */
2967 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2968 itv, spmin, spmax, g_fields);
2971 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2972 S_VALUE(snip->InReceives, snic->InReceives, itv),
2973 out, outsize, svg_p->restart);
2975 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2976 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2977 out + 1, outsize + 1, svg_p->restart);
2979 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2980 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2981 out + 2, outsize + 2, svg_p->restart);
2983 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2984 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2985 out + 3, outsize + 3, svg_p->restart);
2987 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2988 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2989 out + 4, outsize + 4, svg_p->restart);
2991 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2992 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2993 out + 5, outsize + 5, svg_p->restart);
2995 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2996 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2997 out + 6, outsize + 6, svg_p->restart);
2999 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3000 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3001 out + 7, outsize + 7, svg_p->restart);
3004 if (action & F_END) {
3005 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3006 spmin, spmax, out, outsize, svg_p, record_hdr);
3008 /* Free remaining structures */
3009 free_graphs(out, outsize, spmin, spmax);
3014 ***************************************************************************
3015 * Display IPv4 network errors statistics in SVG.
3018 * @a Activity structure with statistics.
3019 * @curr Index in array for current sample statistics.
3020 * @action Action expected from current function.
3021 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3022 * flag indicating that a restart record has been previously
3023 * found (.@restart) and time used for the X axis origin
3025 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3026 * @record_hdr Pointer on record header of current stats sample.
3027 ***************************************************************************
3029 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3030 unsigned long long itv, struct record_header *record_hdr)
3032 struct stats_net_eip
3033 *sneic = (struct stats_net_eip *) a->buf[curr],
3034 *sneip = (struct stats_net_eip *) a->buf[!curr];
3035 int group[] = {3, 2, 3};
3036 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3037 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
3038 "IPv4 network errors statistics (3)"};
3039 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3040 "idisc/s", "odisc/s",
3041 "onort/s", "asmf/s", "fragf/s"};
3042 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3043 static double *spmin, *spmax;
3045 static int *outsize;
3047 if (action & F_BEGIN) {
3049 * Allocate arrays that will contain the graphs data
3050 * and the min/max values.
3052 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3055 if (action & F_MAIN) {
3056 /* Check for min/max values */
3057 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3058 itv, spmin, spmax, g_fields);
3061 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3062 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3063 out, outsize, svg_p->restart);
3065 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3066 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3067 out + 1, outsize + 1, svg_p->restart);
3069 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3070 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3071 out + 2, outsize + 2, svg_p->restart);
3073 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3074 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3075 out + 3, outsize + 3, svg_p->restart);
3077 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3078 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3079 out + 4, outsize + 4, svg_p->restart);
3081 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3082 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3083 out + 5, outsize + 5, svg_p->restart);
3085 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3086 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3087 out + 6, outsize + 6, svg_p->restart);
3089 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3090 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3091 out + 7, outsize + 7, svg_p->restart);
3094 if (action & F_END) {
3095 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3096 spmin, spmax, out, outsize, svg_p, record_hdr);
3098 /* Free remaining structures */
3099 free_graphs(out, outsize, spmin, spmax);
3104 ***************************************************************************
3105 * Display ICMPv4 network statistics in SVG.
3108 * @a Activity structure with statistics.
3109 * @curr Index in array for current sample statistics.
3110 * @action Action expected from current function.
3111 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3112 * flag indicating that a restart record has been previously
3113 * found (.@restart) and time used for the X axis origin
3115 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3116 * @record_hdr Pointer on record header of current stats sample.
3117 ***************************************************************************
3119 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3120 unsigned long long itv, struct record_header *record_hdr)
3122 struct stats_net_icmp
3123 *snic = (struct stats_net_icmp *) a->buf[curr],
3124 *snip = (struct stats_net_icmp *) a->buf[!curr];
3125 int group[] = {2, 4, 4, 4};
3126 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3128 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3129 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3130 char *g_title[] = {"imsg/s", "omsg/s",
3131 "iech/s", "iechr/s", "oech/s", "oechr/s",
3132 "itm/s", "itmr/s", "otm/s", "otmr/s",
3133 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3134 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3135 static double *spmin, *spmax;
3137 static int *outsize;
3139 if (action & F_BEGIN) {
3141 * Allocate arrays that will contain the graphs data
3142 * and the min/max values.
3144 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3147 if (action & F_MAIN) {
3148 /* Check for min/max values */
3149 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3150 itv, spmin, spmax, g_fields);
3153 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3154 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3155 out, outsize, svg_p->restart);
3157 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3158 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3159 out + 1, outsize + 1, svg_p->restart);
3161 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3162 S_VALUE(snip->InEchos, snic->InEchos, itv),
3163 out + 2, outsize + 2, svg_p->restart);
3165 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3166 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3167 out + 3, outsize + 3, svg_p->restart);
3169 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3170 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3171 out + 4, outsize + 4, svg_p->restart);
3173 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3174 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3175 out + 5, outsize + 5, svg_p->restart);
3177 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3178 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3179 out + 6, outsize + 6, svg_p->restart);
3181 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3182 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3183 out + 7, outsize + 7, svg_p->restart);
3185 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3186 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3187 out + 8, outsize + 8, svg_p->restart);
3189 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3190 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3191 out + 9, outsize + 9, svg_p->restart);
3193 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3194 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3195 out + 10, outsize + 10, svg_p->restart);
3197 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3198 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3199 out + 11, outsize + 11, svg_p->restart);
3201 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3202 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3203 out + 12, outsize + 12, svg_p->restart);
3205 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3206 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3207 out + 13, outsize + 13, svg_p->restart);
3210 if (action & F_END) {
3211 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3212 spmin, spmax, out, outsize, svg_p, record_hdr);
3214 /* Free remaining structures */
3215 free_graphs(out, outsize, spmin, spmax);
3220 ***************************************************************************
3221 * Display ICMPv4 network errors statistics in SVG.
3224 * @a Activity structure with statistics.
3225 * @curr Index in array for current sample statistics.
3226 * @action Action expected from current function.
3227 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3228 * flag indicating that a restart record has been previously
3229 * found (.@restart) and time used for the X axis origin
3231 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3232 * @record_hdr Pointer on record header of current stats sample.
3233 ***************************************************************************
3235 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3236 unsigned long long itv, struct record_header *record_hdr)
3238 struct stats_net_eicmp
3239 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3240 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3241 int group[] = {2, 2, 2, 2, 2, 2};
3242 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3243 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3244 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3245 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3246 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3247 char *g_title[] = {"ierr/s", "oerr/s",
3248 "idstunr/s", "odstunr/s",
3249 "itmex/s", "otmex/s",
3250 "iparmpb/s", "oparmpb/s",
3251 "isrcq/s", "osrcq/s",
3252 "iredir/s", "oredir/s"};
3253 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3254 static double *spmin, *spmax;
3256 static int *outsize;
3258 if (action & F_BEGIN) {
3260 * Allocate arrays that will contain the graphs data
3261 * and the min/max values.
3263 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3266 if (action & F_MAIN) {
3267 /* Check for min/max values */
3268 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3269 itv, spmin, spmax, g_fields);
3272 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3273 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3274 out, outsize, svg_p->restart);
3276 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3277 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3278 out + 1, outsize + 1, svg_p->restart);
3280 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3281 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3282 out + 2, outsize + 2, svg_p->restart);
3284 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3285 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3286 out + 3, outsize + 3, svg_p->restart);
3288 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3289 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3290 out + 4, outsize + 4, svg_p->restart);
3292 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3293 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3294 out + 5, outsize + 5, svg_p->restart);
3296 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3297 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3298 out + 6, outsize + 6, svg_p->restart);
3300 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3301 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3302 out + 7, outsize + 7, svg_p->restart);
3304 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3305 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3306 out + 8, outsize + 8, svg_p->restart);
3308 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3309 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3310 out + 9, outsize + 9, svg_p->restart);
3312 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3313 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3314 out + 10, outsize + 10, svg_p->restart);
3316 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3317 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3318 out + 11, outsize + 11, svg_p->restart);
3321 if (action & F_END) {
3322 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3323 spmin, spmax, out, outsize, svg_p, record_hdr);
3325 /* Free remaining structures */
3326 free_graphs(out, outsize, spmin, spmax);
3331 ***************************************************************************
3332 * Display TCPv4 network statistics in SVG.
3335 * @a Activity structure with statistics.
3336 * @curr Index in array for current sample statistics.
3337 * @action Action expected from current function.
3338 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3339 * flag indicating that a restart record has been previously
3340 * found (.@restart) and time used for the X axis origin
3342 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3343 * @record_hdr Pointer on record header of current stats sample.
3344 ***************************************************************************
3346 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3347 unsigned long long itv, struct record_header *record_hdr)
3349 struct stats_net_tcp
3350 *sntc = (struct stats_net_tcp *) a->buf[curr],
3351 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3352 int group[] = {2, 2};
3353 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3354 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3355 char *g_title[] = {"active/s", "passive/s",
3356 "iseg/s", "oseg/s"};
3357 int g_fields[] = {0, 1, 2, 3};
3358 static double *spmin, *spmax;
3360 static int *outsize;
3362 if (action & F_BEGIN) {
3364 * Allocate arrays that will contain the graphs data
3365 * and the min/max values.
3367 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3370 if (action & F_MAIN) {
3371 /* Check for min/max values */
3372 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3373 itv, spmin, spmax, g_fields);
3376 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3377 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3378 out, outsize, svg_p->restart);
3380 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3381 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3382 out + 1, outsize + 1, svg_p->restart);
3384 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3385 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3386 out + 2, outsize + 2, svg_p->restart);
3388 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3389 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3390 out + 3, outsize + 3, svg_p->restart);
3393 if (action & F_END) {
3394 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3395 spmin, spmax, out, outsize, svg_p, record_hdr);
3397 /* Free remaining structures */
3398 free_graphs(out, outsize, spmin, spmax);
3403 ***************************************************************************
3404 * Display TCPv4 network errors statistics in SVG.
3407 * @a Activity structure with statistics.
3408 * @curr Index in array for current sample statistics.
3409 * @action Action expected from current function.
3410 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3411 * flag indicating that a restart record has been previously
3412 * found (.@restart) and time used for the X axis origin
3414 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3415 * @record_hdr Pointer on record header of current stats sample.
3416 ***************************************************************************
3418 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3419 unsigned long long itv, struct record_header *record_hdr)
3421 struct stats_net_etcp
3422 *snetc = (struct stats_net_etcp *) a->buf[curr],
3423 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3424 int group[] = {2, 3};
3425 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3426 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3427 char *g_title[] = {"atmptf/s", "estres/s",
3428 "retrans/s", "isegerr/s", "orsts/s"};
3429 int g_fields[] = {0, 1, 2, 3, 4};
3430 static double *spmin, *spmax;
3432 static int *outsize;
3434 if (action & F_BEGIN) {
3436 * Allocate arrays that will contain the graphs data
3437 * and the min/max values.
3439 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3442 if (action & F_MAIN) {
3443 /* Check for min/max values */
3444 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3445 itv, spmin, spmax, g_fields);
3448 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3449 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3450 out, outsize, svg_p->restart);
3452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3453 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3454 out + 1, outsize + 1, svg_p->restart);
3456 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3457 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3458 out + 2, outsize + 2, svg_p->restart);
3460 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3461 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3462 out + 3, outsize + 3, svg_p->restart);
3464 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3465 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3466 out + 4, outsize + 4, svg_p->restart);
3469 if (action & F_END) {
3470 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3471 spmin, spmax, out, outsize, svg_p, record_hdr);
3473 /* Free remaining structures */
3474 free_graphs(out, outsize, spmin, spmax);
3479 ***************************************************************************
3480 * Display UDPv4 network statistics in SVG.
3483 * @a Activity structure with statistics.
3484 * @curr Index in array for current sample statistics.
3485 * @action Action expected from current function.
3486 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3487 * flag indicating that a restart record has been previously
3488 * found (.@restart) and time used for the X axis origin
3490 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3491 * @record_hdr Pointer on record header of current stats sample.
3492 ***************************************************************************
3494 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3495 unsigned long long itv, struct record_header *record_hdr)
3497 struct stats_net_udp
3498 *snuc = (struct stats_net_udp *) a->buf[curr],
3499 *snup = (struct stats_net_udp *) a->buf[!curr];
3500 int group[] = {2, 2};
3501 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3502 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3503 char *g_title[] = {"idgm/s", "odgm/s",
3504 "noport/s", "idgmerr/s"};
3505 int g_fields[] = {0, 1, 2, 3};
3506 static double *spmin, *spmax;
3508 static int *outsize;
3510 if (action & F_BEGIN) {
3512 * Allocate arrays that will contain the graphs data
3513 * and the min/max values.
3515 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3518 if (action & F_MAIN) {
3519 /* Check for min/max values */
3520 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3521 itv, spmin, spmax, g_fields);
3524 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3525 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3526 out, outsize, svg_p->restart);
3528 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3529 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3530 out + 1, outsize + 1, svg_p->restart);
3532 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3533 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3534 out + 2, outsize + 2, svg_p->restart);
3536 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3537 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3538 out + 3, outsize + 3, svg_p->restart);
3541 if (action & F_END) {
3542 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3543 spmin, spmax, out, outsize, svg_p, record_hdr);
3545 /* Free remaining structures */
3546 free_graphs(out, outsize, spmin, spmax);
3551 ***************************************************************************
3552 * Display IPV6 network socket statistics in SVG.
3555 * @a Activity structure with statistics.
3556 * @curr Index in array for current sample statistics.
3557 * @action Action expected from current function.
3558 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3559 * flag indicating that a restart record has been previously
3560 * found (.@restart) and time used for the X axis origin
3562 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3563 * @record_hdr Pointer on record header of current stats sample.
3564 ***************************************************************************
3566 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3567 unsigned long long itv, struct record_header *record_hdr)
3569 struct stats_net_sock6
3570 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3572 int g_type[] = {SVG_LINE_GRAPH};
3573 char *title[] = {"IPv6 network sockets"};
3574 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3575 int g_fields[] = {0, 1, 2, 3};
3576 static double *spmin, *spmax;
3578 static int *outsize;
3580 if (action & F_BEGIN) {
3582 * Allocate arrays that will contain the graphs data
3583 * and the min/max values.
3585 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3588 if (action & F_MAIN) {
3589 /* Check for min/max values */
3590 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3591 itv, spmin, spmax, g_fields);
3593 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3594 (unsigned long long) snsc->tcp6_inuse,
3595 out, outsize, svg_p->restart);
3597 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3598 (unsigned long long) snsc->udp6_inuse,
3599 out + 1, outsize + 1, svg_p->restart);
3601 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3602 (unsigned long long) snsc->raw6_inuse,
3603 out + 2, outsize + 2, svg_p->restart);
3605 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3606 (unsigned long long) snsc->frag6_inuse,
3607 out + 3, outsize + 3, svg_p->restart);
3610 if (action & F_END) {
3611 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3612 spmin, spmax, out, outsize, svg_p, record_hdr);
3614 /* Free remaining structures */
3615 free_graphs(out, outsize, spmin, spmax);
3620 ***************************************************************************
3621 * Display IPv6 network statistics in SVG.
3624 * @a Activity structure with statistics.
3625 * @curr Index in array for current sample statistics.
3626 * @action Action expected from current function.
3627 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3628 * flag indicating that a restart record has been previously
3629 * found (.@restart) and time used for the X axis origin
3631 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3632 * @record_hdr Pointer on record header of current stats sample.
3633 ***************************************************************************
3635 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3636 unsigned long long itv, struct record_header *record_hdr)
3638 struct stats_net_ip6
3639 *snic = (struct stats_net_ip6 *) a->buf[curr],
3640 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3641 int group[] = {4, 2, 2, 2};
3642 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3644 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3645 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3646 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3647 "asmrq6/s", "asmok6/s",
3648 "imcpck6/s", "omcpck6/s",
3649 "fragok6/s", "fragcr6/s"};
3650 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3651 static double *spmin, *spmax;
3653 static int *outsize;
3655 if (action & F_BEGIN) {
3657 * Allocate arrays that will contain the graphs data
3658 * and the min/max values.
3660 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3663 if (action & F_MAIN) {
3664 /* Check for min/max values */
3665 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3666 itv, spmin, spmax, g_fields);
3669 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3670 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3671 out, outsize, svg_p->restart);
3673 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3674 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3675 out + 1, outsize + 1, svg_p->restart);
3677 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3678 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3679 out + 2, outsize + 2, svg_p->restart);
3681 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3682 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3683 out + 3, outsize + 3, svg_p->restart);
3685 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3686 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3687 out + 4, outsize + 4, svg_p->restart);
3689 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3690 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3691 out + 5, outsize + 5, svg_p->restart);
3693 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3694 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3695 out + 6, outsize + 6, svg_p->restart);
3697 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3698 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3699 out + 7, outsize + 7, svg_p->restart);
3701 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3702 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3703 out + 8, outsize + 8, svg_p->restart);
3705 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3706 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3707 out + 9, outsize + 9, svg_p->restart);
3710 if (action & F_END) {
3711 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3712 spmin, spmax, out, outsize, svg_p, record_hdr);
3714 /* Free remaining structures */
3715 free_graphs(out, outsize, spmin, spmax);
3720 ***************************************************************************
3721 * Display IPv6 network errors statistics in SVG.
3724 * @a Activity structure with statistics.
3725 * @curr Index in array for current sample statistics.
3726 * @action Action expected from current function.
3727 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3728 * flag indicating that a restart record has been previously
3729 * found (.@restart) and time used for the X axis origin
3731 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3732 * @record_hdr Pointer on record header of current stats sample.
3733 ***************************************************************************
3735 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3736 unsigned long long itv, struct record_header *record_hdr)
3738 struct stats_net_eip6
3739 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3740 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3741 int group[] = {4, 2, 2, 3};
3742 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3744 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3745 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3746 "IPv6 network errors statistics (5)"};
3747 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3748 "idisc6/s", "odisc6/s",
3749 "inort6/s", "onort6/s",
3750 "asmf6/s", "fragf6/s", "itrpck6/s"};
3751 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3752 static double *spmin, *spmax;
3754 static int *outsize;
3756 if (action & F_BEGIN) {
3758 * Allocate arrays that will contain the graphs data
3759 * and the min/max values.
3761 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3764 if (action & F_MAIN) {
3765 /* Check for min/max values */
3766 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3767 itv, spmin, spmax, g_fields);
3770 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3771 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3772 out, outsize, svg_p->restart);
3774 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3775 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3776 out + 1, outsize + 1, svg_p->restart);
3778 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3779 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3780 out + 2, outsize + 2, svg_p->restart);
3782 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3783 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3784 out + 3, outsize + 3, svg_p->restart);
3786 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3787 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3788 out + 4, outsize + 4, svg_p->restart);
3790 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3791 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3792 out + 5, outsize + 5, svg_p->restart);
3794 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3795 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3796 out + 6, outsize + 6, svg_p->restart);
3798 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3799 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3800 out + 7, outsize + 7, svg_p->restart);
3802 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3803 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3804 out + 8, outsize + 8, svg_p->restart);
3806 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3807 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3808 out + 9, outsize + 9, svg_p->restart);
3810 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3811 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3812 out + 10, outsize + 10, svg_p->restart);
3815 if (action & F_END) {
3816 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3817 spmin, spmax, out, outsize, svg_p, record_hdr);
3819 /* Free remaining structures */
3820 free_graphs(out, outsize, spmin, spmax);
3825 ***************************************************************************
3826 * Display ICMPv6 network statistics in SVG.
3829 * @a Activity structure with statistics.
3830 * @curr Index in array for current sample statistics.
3831 * @action Action expected from current function.
3832 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3833 * flag indicating that a restart record has been previously
3834 * found (.@restart) and time used for the X axis origin
3836 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3837 * @record_hdr Pointer on record header of current stats sample.
3838 ***************************************************************************
3840 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3841 unsigned long long itv, struct record_header *record_hdr)
3843 struct stats_net_icmp6
3844 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3845 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3846 int group[] = {2, 3, 5, 3, 4};
3847 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3848 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3849 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3850 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3851 "ICMPv6 network statistics (5)"};
3852 char *g_title[] = {"imsg6/s", "omsg6/s",
3853 "iech6/s", "iechr6/s", "oechr6/s",
3854 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3855 "irtsol6/s", "ortsol6/s", "irtad6/s",
3856 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3857 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3858 static double *spmin, *spmax;
3860 static int *outsize;
3862 if (action & F_BEGIN) {
3864 * Allocate arrays that will contain the graphs data
3865 * and the min/max values.
3867 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3870 if (action & F_MAIN) {
3871 /* Check for min/max values */
3872 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3873 itv, spmin, spmax, g_fields);
3876 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3877 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3878 out, outsize, svg_p->restart);
3880 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3881 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3882 out + 1, outsize + 1, svg_p->restart);
3884 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3885 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3886 out + 2, outsize + 2, svg_p->restart);
3888 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3889 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3890 out + 3, outsize + 3, svg_p->restart);
3892 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3893 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3894 out + 4, outsize + 4, svg_p->restart);
3896 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3897 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3898 out + 5, outsize + 5, svg_p->restart);
3900 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3901 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3902 out + 6, outsize + 6, svg_p->restart);
3904 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3905 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3906 out + 7, outsize + 7, svg_p->restart);
3908 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3909 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3910 out + 8, outsize + 8, svg_p->restart);
3912 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3913 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3914 out + 9, outsize + 9, svg_p->restart);
3916 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3917 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3918 out + 10, outsize + 10, svg_p->restart);
3920 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3921 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3922 out + 11, outsize + 11, svg_p->restart);
3924 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3925 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3926 out + 12, outsize + 12, svg_p->restart);
3928 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3929 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3930 out + 13, outsize + 13, svg_p->restart);
3932 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3933 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3934 out + 14, outsize + 14, svg_p->restart);
3936 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3937 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3938 out + 15, outsize + 15, svg_p->restart);
3940 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3941 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3942 out + 16, outsize + 16, svg_p->restart);
3945 if (action & F_END) {
3946 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3947 spmin, spmax, out, outsize, svg_p, record_hdr);
3949 /* Free remaining structures */
3950 free_graphs(out, outsize, spmin, spmax);
3955 ***************************************************************************
3956 * Display ICMPv6 network errors statistics in SVG.
3959 * @a Activity structure with statistics.
3960 * @curr Index in array for current sample statistics.
3961 * @action Action expected from current function.
3962 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3963 * flag indicating that a restart record has been previously
3964 * found (.@restart) and time used for the X axis origin
3966 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3967 * @record_hdr Pointer on record header of current stats sample.
3968 ***************************************************************************
3970 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3971 unsigned long long itv, struct record_header *record_hdr)
3973 struct stats_net_eicmp6
3974 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3975 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3976 int group[] = {1, 2, 2, 2, 2, 2};
3977 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3978 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3979 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3980 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3981 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3982 char *g_title[] = {"ierr6/s",
3983 "idtunr6/s", "odtunr6/s",
3984 "itmex6/s", "otmex6/s",
3985 "iprmpb6/s", "oprmpb6/s",
3986 "iredir6/s", "oredir6/s",
3987 "ipck2b6/s", "opck2b6/s"};
3988 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3989 static double *spmin, *spmax;
3991 static int *outsize;
3993 if (action & F_BEGIN) {
3995 * Allocate arrays that will contain the graphs data
3996 * and the min/max values.
3998 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4001 if (action & F_MAIN) {
4002 /* Check for min/max values */
4003 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4004 itv, spmin, spmax, g_fields);
4007 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4008 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4009 out, outsize, svg_p->restart);
4011 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4012 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4013 out + 1, outsize + 1, svg_p->restart);
4015 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4016 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4017 out + 2, outsize + 2, svg_p->restart);
4019 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4020 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4021 out + 3, outsize + 3, svg_p->restart);
4023 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4024 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4025 out + 4, outsize + 4, svg_p->restart);
4027 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4028 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4029 out + 5, outsize + 5, svg_p->restart);
4031 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4032 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4033 out + 6, outsize + 6, svg_p->restart);
4035 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4036 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4037 out + 7, outsize + 7, svg_p->restart);
4039 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4040 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4041 out + 8, outsize + 8, svg_p->restart);
4043 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4044 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4045 out + 9, outsize + 9, svg_p->restart);
4047 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4048 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4049 out + 10, outsize + 10, svg_p->restart);
4052 if (action & F_END) {
4053 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4054 spmin, spmax, out, outsize, svg_p, record_hdr);
4056 /* Free remaining structures */
4057 free_graphs(out, outsize, spmin, spmax);
4062 ***************************************************************************
4063 * Display UDPv6 network statistics in SVG.
4066 * @a Activity structure with statistics.
4067 * @curr Index in array for current sample statistics.
4068 * @action Action expected from current function.
4069 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4070 * flag indicating that a restart record has been previously
4071 * found (.@restart) and time used for the X axis origin
4073 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4074 * @record_hdr Pointer on record header of current stats sample.
4075 ***************************************************************************
4077 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4078 unsigned long long itv, struct record_header *record_hdr)
4080 struct stats_net_udp6
4081 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4082 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4083 int group[] = {2, 2};
4084 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4085 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
4086 char *g_title[] = {"idgm6/s", "odgm6/s",
4087 "noport6/s", "idgmer6/s"};
4088 int g_fields[] = {0, 1, 2, 3};
4089 static double *spmin, *spmax;
4091 static int *outsize;
4093 if (action & F_BEGIN) {
4095 * Allocate arrays that will contain the graphs data
4096 * and the min/max values.
4098 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4101 if (action & F_MAIN) {
4102 /* Check for min/max values */
4103 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4104 itv, spmin, spmax, g_fields);
4107 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4108 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4109 out, outsize, svg_p->restart);
4111 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4112 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4113 out + 1, outsize + 1, svg_p->restart);
4115 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4116 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4117 out + 2, outsize + 2, svg_p->restart);
4119 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4120 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4121 out + 3, outsize + 3, svg_p->restart);
4124 if (action & F_END) {
4125 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4126 spmin, spmax, out, outsize, svg_p, record_hdr);
4128 /* Free remaining structures */
4129 free_graphs(out, outsize, spmin, spmax);
4134 ***************************************************************************
4135 * Display CPU frequency statistics in SVG.
4138 * @a Activity structure with statistics.
4139 * @curr Index in array for current sample statistics.
4140 * @action Action expected from current function.
4141 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4142 * flag indicating that a restart record has been previously
4143 * found (.@restart) and time used for the X axis origin
4145 * @itv Interval of time in 1/100th of a second (unused here).
4146 * @record_hdr Pointer on record header of current stats sample.
4147 ***************************************************************************
4149 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4150 unsigned long long itv, struct record_header *record_hdr)
4152 struct stats_pwr_cpufreq *spc, *spp;
4154 int g_type[] = {SVG_LINE_GRAPH};
4155 char *title[] = {"CPU frequency"};
4156 char *g_title[] = {"MHz"};
4157 static double *spmin, *spmax;
4159 static int *outsize;
4163 if (action & F_BEGIN) {
4165 * Allocate arrays that will contain the graphs data
4166 * and the min/max values.
4168 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4171 if (action & F_MAIN) {
4173 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4175 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4176 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4178 /* Should current CPU (including CPU "all") be displayed? */
4179 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4184 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4185 ((double) spp->cpufreq) / 100,
4186 ((double) spc->cpufreq) / 100,
4187 out + i, outsize + i, svg_p->restart, svg_p->dt,
4188 spmin + i, spmax + i);
4192 if (action & F_END) {
4193 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
4195 /* Should current CPU (including CPU "all") be displayed? */
4196 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4201 /* This is CPU "all" */
4202 strcpy(item_name, "all");
4205 sprintf(item_name, "%d", i - 1);
4208 draw_activity_graphs(a->g_nr, g_type,
4209 title, g_title, item_name, group,
4210 spmin + i, spmax + i, out + i, outsize + i,
4214 /* Free remaining structures */
4215 free_graphs(out, outsize, spmin, spmax);
4220 ***************************************************************************
4221 * Display fan statistics in SVG.
4224 * @a Activity structure with statistics.
4225 * @curr Index in array for current sample statistics.
4226 * @action Action expected from current function.
4227 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4228 * flag indicating that a restart record has been previously
4229 * found (.@restart) and time used for the X axis origin
4231 * @itv Interval of time in 1/100th of a second (unused here).
4232 * @record_hdr Pointer on record header of current stats sample.
4233 ***************************************************************************
4235 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4236 unsigned long long itv, struct record_header *record_hdr)
4238 struct stats_pwr_fan *spc, *spp;
4240 int g_type[] = {SVG_LINE_GRAPH};
4241 char *title[] = {"Fan speed"};
4242 char *g_title[] = {"~rpm"};
4243 static double *spmin, *spmax;
4245 static int *outsize;
4246 char item_name[MAX_SENSORS_DEV_LEN + 8];
4249 if (action & F_BEGIN) {
4251 * Allocate arrays that will contain the graphs data
4252 * and the min/max values.
4254 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4257 if (action & F_MAIN) {
4259 for (i = 0; i < a->nr[curr]; i++) {
4261 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4262 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4265 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4268 out + i, outsize + i, svg_p->restart, svg_p->dt,
4269 spmin + i, spmax + i);
4273 if (action & F_END) {
4274 for (i = 0; i < svg_p->nr_max; i++) {
4276 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4278 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4279 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4281 draw_activity_graphs(a->g_nr, g_type,
4282 title, g_title, item_name, group,
4283 spmin + i, spmax + i, out + i, outsize + i,
4287 /* Free remaining structures */
4288 free_graphs(out, outsize, spmin, spmax);
4293 ***************************************************************************
4294 * Display temperature statistics in SVG.
4297 * @a Activity structure with statistics.
4298 * @curr Index in array for current sample statistics.
4299 * @action Action expected from current function.
4300 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4301 * flag indicating that a restart record has been previously
4302 * found (.@restart) and time used for the X axis origin
4304 * @itv Interval of time in 1/100th of a second (unused here).
4305 * @record_hdr Pointer on record header of current stats sample.
4306 ***************************************************************************
4308 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4309 unsigned long long itv, struct record_header *record_hdr)
4311 struct stats_pwr_temp *spc;
4312 int group[] = {1, 1};
4313 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4314 char *title[] = {"Device temperature (1)",
4315 "Device temperature (2)"};
4316 char *g_title[] = {"~degC",
4318 static double *spmin, *spmax;
4320 static int *outsize;
4321 char item_name[MAX_SENSORS_DEV_LEN + 8];
4325 if (action & F_BEGIN) {
4327 * Allocate arrays that will contain the graphs data
4328 * and the min/max values.
4330 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4333 if (action & F_MAIN) {
4334 /* For each temperature sensor */
4335 for (i = 0; i < a->nr[curr]; i++) {
4337 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4339 /* Look for min/max values */
4340 if (spc->temp < *(spmin + 2 * i)) {
4341 *(spmin + 2 * i) = spc->temp;
4343 if (spc->temp > *(spmax + 2 * i)) {
4344 *(spmax + 2 * i) = spc->temp;
4346 tval = (spc->temp_max - spc->temp_min) ?
4347 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4349 if (tval < *(spmin + 2 * i + 1)) {
4350 *(spmin + 2 * i + 1) = tval;
4352 if (tval > *(spmax + 2 * i + 1)) {
4353 *(spmax + 2 * i + 1) = tval;
4357 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4359 out + 2 * i, outsize + 2 * i, svg_p->restart);
4361 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4363 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4367 if (action & F_END) {
4368 for (i = 0; i < svg_p->nr_max; i++) {
4370 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4372 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4373 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4375 draw_activity_graphs(a->g_nr, g_type,
4376 title, g_title, item_name, group,
4377 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4381 /* Free remaining structures */
4382 free_graphs(out, outsize, spmin, spmax);
4387 ***************************************************************************
4388 * Display voltage inputs statistics in SVG.
4391 * @a Activity structure with statistics.
4392 * @curr Index in array for current sample statistics.
4393 * @action Action expected from current function.
4394 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4395 * flag indicating that a restart record has been previously
4396 * found (.@restart) and time used for the X axis origin
4398 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4399 * @record_hdr Pointer on record header of current stats sample.
4400 ***************************************************************************
4402 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4403 unsigned long long itv, struct record_header *record_hdr)
4405 struct stats_pwr_in *spc;
4406 int group[] = {1, 1};
4407 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4408 char *title[] = {"Voltage inputs (1)",
4409 "Voltage inputs (2)"};
4410 char *g_title[] = {"inV",
4412 static double *spmin, *spmax;
4414 static int *outsize;
4415 char item_name[MAX_SENSORS_DEV_LEN + 8];
4419 if (action & F_BEGIN) {
4421 * Allocate arrays that will contain the graphs data
4422 * and the min/max values.
4424 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4427 if (action & F_MAIN) {
4428 /* For each voltage input sensor */
4429 for (i = 0; i < a->nr[curr]; i++) {
4431 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4433 /* Look for min/max values */
4434 if (spc->in < *(spmin + 2 * i)) {
4435 *(spmin + 2 * i) = spc->in;
4437 if (spc->in > *(spmax + 2 * i)) {
4438 *(spmax + 2 * i) = spc->in;
4440 tval = (spc->in_max - spc->in_min) ?
4441 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4443 if (tval < *(spmin + 2 * i + 1)) {
4444 *(spmin + 2 * i + 1) = tval;
4446 if (tval > *(spmax + 2 * i + 1)) {
4447 *(spmax + 2 * i + 1) = tval;
4451 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4453 out + 2 * i, outsize + 2 * i, svg_p->restart);
4455 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4457 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4461 if (action & F_END) {
4462 for (i = 0; i < svg_p->nr_max; i++) {
4464 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4466 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4467 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4469 draw_activity_graphs(a->g_nr, g_type,
4470 title, g_title, item_name, group,
4471 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4475 /* Free remaining structures */
4476 free_graphs(out, outsize, spmin, spmax);
4481 ***************************************************************************
4482 * Display huge pages statistics in SVG.
4485 * @a Activity structure with statistics.
4486 * @curr Index in array for current sample statistics.
4487 * @action Action expected from current function.
4488 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4489 * flag indicating that a restart record has been previously
4490 * found (.@restart) and time used for the X axis origin
4492 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4493 * @record_hdr Pointer on record header of current stats sample.
4494 ***************************************************************************
4496 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4497 unsigned long long itv, struct record_header *record_hdr)
4500 *smc = (struct stats_huge *) a->buf[curr];
4501 int group[] = {2, 1};
4502 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4503 char *title[] = {"Huge pages utilization (1)",
4504 "Huge pages utilization (2)"};
4505 char *g_title[] = {"~kbhugfree", "~kbhugused",
4507 int g_fields[] = {0};
4508 unsigned int local_types_nr[] = {0, 1, 0};
4509 static double *spmin, *spmax;
4511 static int *outsize;
4514 if (action & F_BEGIN) {
4516 * Allocate arrays that will contain the graphs data
4517 * and the min/max values.
4519 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4522 if (action & F_MAIN) {
4523 /* Check for min/max values */
4524 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4525 itv, spmin, spmax, g_fields);
4527 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4528 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4530 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4531 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4533 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4534 if (tval < *(spmin + 2)) {
4535 *(spmin + 2) = tval;
4537 if (tval > *(spmax + 2)) {
4538 *(spmax + 2) = tval;
4542 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4543 (unsigned long long) smc->frhkb,
4544 out, outsize, svg_p->restart);
4546 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4547 (unsigned long long) smc->tlhkb - smc->frhkb,
4548 out + 1, outsize + 1, svg_p->restart);
4550 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4552 out + 2, outsize + 2, svg_p->dt);
4555 if (action & F_END) {
4556 draw_activity_graphs(a->g_nr, g_type,
4557 title, g_title, NULL, group,
4558 spmin, spmax, out, outsize, svg_p, record_hdr);
4560 /* Free remaining structures */
4561 free_graphs(out, outsize, spmin, spmax);
4566 ***************************************************************************
4567 * Display filesystem statistics in SVG.
4570 * @a Activity structure with statistics.
4571 * @curr Index in array for current sample statistics.
4572 * @action Action expected from current function.
4573 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4574 * flag indicating that a restart record has been previously
4575 * found (.@restart) and time used for the X axis origin
4577 * @itv Interval of time in 1/100th of a second (unused here).
4578 * @record_hdr Pointer on record header of current stats sample.
4579 ***************************************************************************
4581 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4582 unsigned long long itv, struct record_header *record_hdr)
4584 struct stats_filesystem *sfc, *sfp;
4585 int group[] = {2, 2, 2, 1};
4586 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4587 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4588 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4589 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4590 char *g_title[] = {"~MBfsfree", "~MBfsused",
4591 "%ufsused", "%fsused",
4592 "Ifree/1000", "Iused/1000",
4594 static double *spmin, *spmax;
4596 static int *outsize;
4597 char *item_name = NULL;
4599 int i, k, pos, restart;
4601 if (action & F_BEGIN) {
4603 * Allocate arrays (#0..6) that will contain the graphs data
4604 * and the min/max values.
4605 * Also allocate two additional arrays (#7..8) for each filesystem:
4606 * out + 7 will contain the filesystem name,
4607 * out + 8 will contain the mount point.
4609 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
4612 if (action & F_MAIN) {
4613 /* For each filesystem structure */
4614 for (i = 0; i < a->nr[curr]; i++) {
4615 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4617 /* Look for corresponding graph */
4618 for (k = 0; k < svg_p->nr_max; k++) {
4619 item_name = *(out + k * 9 + 7);
4620 if (!strcmp(sfc->fs_name, item_name))
4625 if (k == svg_p->nr_max) {
4626 /* Graph not found: Look for first free entry */
4627 for (k = 0; k < svg_p->nr_max; k++) {
4628 item_name = *(out + k * 9 + 7);
4629 if (!strcmp(item_name, ""))
4632 if (k == svg_p->nr_max) {
4633 /* No free graph entry: Extend all buffers */
4634 reallocate_all_graph_lines(svg_p->nr_max,
4635 &out, &outsize, &spmin, &spmax);
4642 if (!item_name[0]) {
4643 /* Save filesystem name and mount point (if not already done) */
4644 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4645 item_name[CHUNKSIZE - 1] = '\0';
4646 item_name = *(out + pos + 8);
4647 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4648 item_name[CHUNKSIZE - 1] = '\0';
4652 for (k = 0; k < a->nr[!curr]; k++) {
4653 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4654 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4655 /* Filesystem found in previous sample */
4656 restart = svg_p->restart;
4660 /* Check for min/max values */
4662 /* Compute fsfree min/max values */
4663 tval = (double) sfc->f_bfree;
4664 if (tval > *(spmax + pos)) {
4665 *(spmax + pos) = tval;
4667 if (tval < *(spmin + pos)) {
4668 *(spmin + pos) = tval;
4670 /* Compute fsused min/max values */
4671 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4672 if (tval > *(spmax + pos + 1)) {
4673 *(spmax + pos + 1) = tval;
4675 if (tval < *(spmin + pos + 1)) {
4676 *(spmin + pos + 1) = tval;
4678 /* Compute %ufsused min/max values */
4679 tval = sfc->f_blocks ?
4680 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4681 if (tval > *(spmax + pos + 2)) {
4682 *(spmax + pos + 2) = tval;
4684 if (tval < *(spmin + pos + 2)) {
4685 *(spmin + pos + 2) = tval;
4687 /* Compute %fsused min/max values */
4688 tval = sfc->f_blocks ?
4689 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4690 if (tval > *(spmax + pos + 3)) {
4691 *(spmax + pos + 3) = tval;
4693 if (tval < *(spmin + pos + 3)) {
4694 *(spmin + pos + 3) = tval;
4696 /* Compute Ifree min/max values */
4697 tval = (double) sfc->f_ffree;
4698 if (tval > *(spmax + pos + 4)) {
4699 *(spmax + pos + 4) = tval;
4701 if (tval < *(spmin + pos + 4)) {
4702 *(spmin + pos + 4) = tval;
4704 /* Compute Iused min/max values */
4705 tval = (double) (sfc->f_files - sfc->f_ffree);
4706 if (tval > *(spmax + pos + 5)) {
4707 *(spmax + pos + 5) = tval;
4709 if (tval < *(spmin + pos + 5)) {
4710 *(spmin + pos + 5) = tval;
4712 /* Compute %Iused min/max values */
4713 tval = sfc->f_files ?
4714 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4715 if (tval > *(spmax + pos + 6)) {
4716 *(spmax + pos + 6) = tval;
4718 if (tval < *(spmin + pos + 6)) {
4719 *(spmin + pos + 6) = tval;
4723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4724 (double) sfc->f_bfree / 1024 / 1024,
4725 out + pos, outsize + pos, restart);
4727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4728 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4729 out + pos + 1, outsize + pos + 1, restart);
4731 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4734 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4735 out + pos + 2, outsize + pos + 2, svg_p->dt);
4737 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4740 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4741 out + pos + 3, outsize + pos + 3, svg_p->dt);
4743 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4744 ((double) sfc->f_ffree) / 1000,
4745 out + pos + 4, outsize + pos + 4, restart);
4747 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4748 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4749 out + pos + 5, outsize + pos + 5, restart);
4751 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4754 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4755 out + pos + 6, outsize + pos + 6, svg_p->dt);
4759 if (action & F_END) {
4761 for (i = 0; i < svg_p->nr_max; i++) {
4763 /* Check if there is something to display */
4768 /* Conversion B -> MB and inodes/1000 */
4769 for (k = 0; k < 2; k++) {
4770 *(spmin + pos + k) /= (1024 * 1024);
4771 *(spmax + pos + k) /= (1024 * 1024);
4772 *(spmin + pos + 4 + k) /= 1000;
4773 *(spmax + pos + 4 + k) /= 1000;
4776 if (DISPLAY_MOUNT(a->opt_flags)) {
4777 item_name = *(out + pos + 8);
4780 item_name = *(out + pos + 7);
4783 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4784 spmin + pos, spmax + pos, out + pos, outsize + pos,
4788 /* Free remaining structures */
4789 free_graphs(out, outsize, spmin, spmax);
4794 ***************************************************************************
4795 * Display Fibre Channel HBA statistics in SVG.
4798 * @a Activity structure with statistics.
4799 * @curr Index in array for current sample statistics.
4800 * @action Action expected from current function.
4801 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4802 * flag indicating that a restart record has been previously
4803 * found (.@restart) and time used for the X axis origin
4805 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4806 * @record_hdr Pointer on record header of current stats sample.
4807 ***************************************************************************
4809 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4810 unsigned long long itv, struct record_header *record_hdr)
4812 struct stats_fchost *sfcc, *sfcp;
4813 int group[] = {2, 2};
4814 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4815 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4816 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4817 "fch_rxw/s", "fch_txw/s"};
4818 int g_fields[] = {0, 1, 2, 3};
4819 static double *spmin, *spmax;
4821 static int *outsize;
4823 int i, j, j0, k, found, pos, restart, *unregistered;
4825 if (action & F_BEGIN) {
4827 * Allocate arrays (#0..3) that will contain the graphs data
4828 * and the min/max values.
4829 * Also allocate one additional array (#4) that will contain
4830 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4831 * has either still not been registered, or has been unregistered
4834 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
4837 if (action & F_MAIN) {
4838 restart = svg_p->restart;
4840 * Mark previously registered interfaces as now
4841 * possibly unregistered for all graphs.
4843 for (k = 0; k < svg_p->nr_max; k++) {
4844 unregistered = outsize + k * 5 + 4;
4845 if (*unregistered == FALSE) {
4846 *unregistered = MAYBE;
4850 /* For each FC HBA */
4851 for (i = 0; i < a->nr[curr]; i++) {
4855 if (a->nr[!curr] > 0) {
4856 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4858 /* Look for corresponding graph */
4859 for (k = 0; k < svg_p->nr_max; k++) {
4860 item_name = *(out + k * 5 + 4);
4861 if (!strcmp(sfcc->fchost_name, item_name))
4865 if (k == svg_p->nr_max) {
4866 /* Graph not found: Look for first free entry */
4867 for (k = 0; k < svg_p->nr_max; k++) {
4868 item_name = *(out + k * 5 + 4);
4869 if (!strcmp(item_name, ""))
4872 if (k == svg_p->nr_max) {
4873 /* No free graph entry: Extend all buffers */
4874 reallocate_all_graph_lines(svg_p->nr_max,
4875 &out, &outsize, &spmin, &spmax);
4881 unregistered = outsize + pos + 4;
4883 /* Look for corresponding structure in previous iteration */
4886 if (j >= a->nr[!curr]) {
4887 j = a->nr[!curr] - 1;
4893 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4894 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4898 if (++j >= a->nr[!curr]) {
4909 * If current interface was marked as previously unregistered,
4910 * then set restart variable to TRUE so that the graph will be
4911 * discontinuous, and mark it as now registered.
4913 if (*unregistered == TRUE) {
4916 *unregistered = FALSE;
4918 item_name = *(out + pos + 4);
4919 if (!item_name[0]) {
4920 /* Save FC HBA name */
4921 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4922 item_name[CHUNKSIZE - 1] = '\0';
4925 /* Look for min/max values */
4926 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4927 itv, spmin + pos, spmax + pos, g_fields);
4930 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4931 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4932 out + pos, outsize + pos, restart);
4934 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4935 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4936 out + pos + 1, outsize + pos + 1, restart);
4938 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4939 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4940 out + pos + 2, outsize + pos + 2, restart);
4942 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4943 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4944 out + pos + 3, outsize + pos + 3, restart);
4947 /* Mark interfaces not seen here as now unregistered */
4948 for (k = 0; k < svg_p->nr_max; k++) {
4949 unregistered = outsize + k * 5 + 4;
4950 if (*unregistered != FALSE) {
4951 *unregistered = TRUE;
4956 if (action & F_END) {
4957 for (i = 0; i < svg_p->nr_max; i++) {
4959 /* Check if there is something to display */
4964 item_name = *(out + pos + 4);
4965 draw_activity_graphs(a->g_nr, g_type,
4966 title, g_title, item_name, group,
4967 spmin + pos, spmax + pos, out + pos, outsize + pos,
4971 /* Free remaining structures */
4972 free_graphs(out, outsize, spmin, spmax);
4977 ***************************************************************************
4978 * Display softnet statistics in SVG.
4981 * @a Activity structure with statistics.
4982 * @curr Index in array for current sample statistics.
4983 * @action Action expected from current function.
4984 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4985 * flag indicating that a restart record has been previously
4986 * found (.@restart) and time used for the X axis origin
4988 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4989 * @record_hdr Pointer on record header of current stats sample.
4990 ***************************************************************************
4992 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4993 unsigned long long itv, struct record_header *record_hdr)
4995 struct stats_softnet *ssnc, *ssnp;
4996 int group[] = {2, 3};
4997 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4998 char *title[] = {"Software-based network processing statistics (1)",
4999 "Software-based network processing statistics (2)"};
5000 char *g_title[] = {"total/s", "dropd/s",
5001 "squeezd/s", "rx_rps/s", "flw_lim/s"};
5002 int g_fields[] = {0, 1, 2, 3, 4};
5003 static double *spmin, *spmax;
5005 static int *outsize;
5009 if (action & F_BEGIN) {
5011 * Allocate arrays that will contain the graphs data
5012 * and the min/max values.
5014 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
5017 if (action & F_MAIN) {
5019 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
5021 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5022 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5024 /* Should current CPU (including CPU "all") be displayed? */
5025 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5031 /* Check for min/max values */
5032 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5033 itv, spmin + pos, spmax + pos, g_fields);
5036 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5037 S_VALUE(ssnp->processed, ssnc->processed, itv),
5038 out + pos, outsize + pos, svg_p->restart);
5040 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5041 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5042 out + pos + 1, outsize + pos + 1, svg_p->restart);
5044 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5045 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5046 out + pos + 2, outsize + pos + 2, svg_p->restart);
5048 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5049 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5050 out + pos + 3, outsize + pos + 3, svg_p->restart);
5052 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5053 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5054 out + pos + 4, outsize + pos + 4, svg_p->restart);
5058 if (action & F_END) {
5059 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
5061 /* Should current CPU (including CPU "all") be displayed? */
5062 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5069 /* This is CPU "all" */
5070 strcpy(item_name, "all");
5073 sprintf(item_name, "%d", i - 1);
5076 draw_activity_graphs(a->g_nr, g_type,
5077 title, g_title, item_name, group,
5078 spmin + pos, spmax + pos, out + pos, outsize + pos,
5082 /* Free remaining structures */
5083 free_graphs(out, outsize, spmin, spmax);