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 ***************************************************************************
31 #include "svg_stats.h"
36 #define _(string) gettext(string)
38 #define _(string) (string)
41 extern unsigned int flags;
42 extern unsigned int dm_major;
44 unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
45 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
46 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
47 0xcc3300, 0x50040f, 0xffffbf, 0x193d55};
48 #define SVG_COLORS_IDX_MASK 0x0f
51 ***************************************************************************
52 * Compare the values of a statistics sample with the max and min values
53 * already found in previous samples for this same activity. If some new
54 * min or max values are found, then save them.
55 * Assume values cannot be negative.
56 * The structure containing the statistics sample is composed of @llu_nr
57 * unsigned long long fields, followed by @lu_nr unsigned long fields, then
58 * followed by @u_nr unsigned int fields.
61 * @types_nr Number of fields whose type is "long long", "long" and "int"
62 * composing the structure.
63 * @cs Pointer on current sample statistics structure.
64 * @ps Pointer on previous sample statistics structure (may be NULL).
65 * @itv Interval of time in 1/100th of a second.
66 * @spmin Array containing min values already found for this activity.
67 * @spmax Array containing max values already found for this activity.
68 * @g_fields Index in spmin/spmax arrays where extrema values for each
69 * activity metric will be saved. As a consequence spmin/spmax
70 * arrays may contain values in a different order than that of
71 * the fields in the statistics structure.
74 * @spmin Array containg the possible new min values for current activity.
75 * @spmax Array containg the possible new max values for current activity.
76 ***************************************************************************
78 void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
79 double *spmin, double *spmax, int g_fields[])
81 unsigned long long *lluc, *llup;
82 unsigned long *luc, *lup;
83 unsigned int *uc, *up;
87 /* Compare unsigned long long fields */
88 lluc = (unsigned long long *) cs;
89 llup = (unsigned long long *) ps;
90 for (i = 0; i < types_nr[0]; i++, m++) {
92 val = *lluc < *llup ? 0.0 : S_VALUE(*llup, *lluc, itv);
96 * If no pointer on previous sample has been given
97 * then the value is not a per-second one.
101 if (val < *(spmin + g_fields[m])) {
102 *(spmin + g_fields[m]) = val;
104 if (val > *(spmax + g_fields[m])) {
105 *(spmax + g_fields[m]) = val;
107 lluc = (unsigned long long *) ((char *) lluc + ULL_ALIGNMENT_WIDTH);
109 llup = (unsigned long long *) ((char *) llup + ULL_ALIGNMENT_WIDTH);
113 /* Compare unsigned long fields */
114 luc = (unsigned long *) lluc;
115 lup = (unsigned long *) llup;
116 for (i = 0; i < types_nr[1]; i++, m++) {
118 val = *luc < *lup ? 0.0 : S_VALUE(*lup, *luc, itv);
123 if (val < *(spmin + g_fields[m])) {
124 *(spmin + g_fields[m]) = val;
126 if (val > *(spmax + g_fields[m])) {
127 *(spmax + g_fields[m]) = val;
129 luc = (unsigned long *) ((char *) luc + UL_ALIGNMENT_WIDTH);
131 lup = (unsigned long *) ((char *) lup + UL_ALIGNMENT_WIDTH);
135 /* Compare unsigned int fields */
136 uc = (unsigned int *) luc;
137 up = (unsigned int *) lup;
138 for (i = 0; i < types_nr[2]; i++, m++) {
140 val = *uc < *up ? 0.0 : S_VALUE(*up, *uc, itv);
145 if (val < *(spmin + g_fields[m])) {
146 *(spmin + g_fields[m]) = val;
148 if (val > *(spmax + g_fields[m])) {
149 *(spmax + g_fields[m]) = val;
151 uc = (unsigned int *) ((char *) uc + U_ALIGNMENT_WIDTH);
153 up = (unsigned int *) ((char *) up + U_ALIGNMENT_WIDTH);
159 ***************************************************************************
160 * Find the min and max values of all the graphs that will be drawn in the
161 * same view. The graphs have their own min and max values in
162 * spmin[pos...pos+n-1] and spmax[pos...pos+n-1].
165 * @pos Position in array for the first graph extrema value.
166 * @n Number of graphs to scan.
167 * @spmin Array containing min values for graphs.
168 * @spmax Array containing max values for graphs.
171 * @gmin Global min value found.
172 * @gmax Global max value found.
173 ***************************************************************************
175 void get_global_extrema(int pos, int n, double *spmin, double *spmax,
176 double *gmin, double *gmax)
180 *gmin = *(spmin + pos);
181 *gmax = *(spmax + pos);
183 for (i = 1; i < n; i++) {
184 if (*(spmin + pos + i) < *gmin) {
185 *gmin = *(spmin + pos + i);
187 if (*(spmax + pos + i) > *gmax) {
188 *gmax = *(spmax + pos + i);
194 ***************************************************************************
195 * Allocate arrays used to save graphs data, min and max values.
196 * @n arrays of chars are allocated for @n graphs to draw. A pointer on this
197 * array is returned. This is equivalent to "char data[][n]" where each
198 * element is of indeterminate size and will contain the graph data (eg.
199 * << path d="M12,14 L13,16..." ... >>.
200 * The size of element data[i] is given by outsize[i].
201 * Also allocate an array to save min values (equivalent to "double spmin[n]")
202 * and an array for max values (equivalent to "double spmax[n]").
205 * @n Number of graphs to draw for current activity.
208 * @outsize Array that will contain the sizes of each element in array
209 * of chars. Equivalent to "int outsize[n]" with
210 * outsize[n] = sizeof(data[][n]).
211 * @spmin Array that will contain min values for current activity.
212 * @spmax Array that will contain max values for current activity.
215 * Pointer on array of arrays of chars that will contain the graphs data.
217 * NB: @min and @max arrays contain values in the same order as the fields
218 * in the statistics structure.
219 ***************************************************************************
221 char **allocate_graph_lines(int n, int **outsize, double **spmin, double **spmax)
228 * Allocate an array of pointers. Each of these pointers will
229 * be an array of chars.
231 if ((out = (char **) malloc(n * sizeof(char *))) == NULL) {
235 /* Allocate array that will contain the size of each array of chars */
236 if ((*outsize = (int *) malloc(n * sizeof(int))) == NULL) {
240 /* Allocate array that will contain the min value of each graph */
241 if ((*spmin = (double *) malloc(n * sizeof(double))) == NULL) {
245 /* Allocate array that will contain the max value of each graph */
246 if ((*spmax = (double *) malloc(n * sizeof(double))) == NULL) {
250 /* Allocate arrays of chars that will contain graphs data */
251 for (i = 0; i < n; i++) {
252 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
257 *out_p = '\0'; /* Reset string so that it can be safely strncat()'d later */
258 *(*outsize + i) = CHUNKSIZE; /* Each array of chars has a default size of CHUNKSIZE */
259 *(*spmin + i) = DBL_MAX; /* Init min and max values */
260 *(*spmax + i) = -DBL_MAX;
267 ***************************************************************************
268 * Reallocate all the arrays used to save graphs data, min and max values.
269 * The new size is the double of the original one.
272 * @n Number of slots currently allocated.
273 * @out Current pointer on arrays containing the graphs data.
274 * @outsize Current pointer on array containing the size of each element
276 * @spmin Current pointer on array containing min values.
277 * @spmax Current pointer on array containing max values.
280 * @out New pointer on arrays containing the graphs data.
281 * @outsize New pointer on array containing the size of each element
283 * @spmin New pointer on array containing min values.
284 * @spmax New pointer on array containing max values.
285 ***************************************************************************
287 void reallocate_all_graph_lines(int n, char ***out, int **outsize,
288 double **spmin, double **spmax)
293 /* Reallocate all the arrays */
294 SREALLOC(*out, char *, n * sizeof(char *) * 2);
295 SREALLOC(*outsize, int, n * sizeof(int) * 2);
296 SREALLOC(*spmin, double, n * sizeof(double) * 2);
297 SREALLOC(*spmax, double, n * sizeof(double) * 2);
299 /* Allocate arrays of chars that will contain graphs data for the newly allocated slots */
300 for (i = 0; i < n; i++) {
301 if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
305 *(*out + n + i) = out_p;
307 *(*outsize + n + i) = CHUNKSIZE;
308 *(*spmin + n + i) = DBL_MAX;
309 *(*spmax + n + i) = -DBL_MAX;
314 ***************************************************************************
315 * Save SVG code for current graph.
318 * @data SVG code to append to current graph definition.
319 * @out Pointer on array of chars for current graph definition.
320 * @outsize Size of array of chars for current graph definition.
323 * @out Pointer on array of chars for current graph definition that
324 * has been updated with the addition of current sample data.
325 * @outsize Array that containing the (possibly new) sizes of each
326 * element in array of chars.
327 ***************************************************************************
329 void save_svg_data(char *data, char **out, int *outsize)
335 /* Determine space left in array */
336 len = *outsize - strlen(out_p) - 1;
337 if (strlen(data) >= len) {
339 * If current array of chars doesn't have enough space left
340 * then reallocate it with CHUNKSIZE more bytes.
342 SREALLOC(out_p, char, *outsize + CHUNKSIZE);
344 *outsize += CHUNKSIZE;
347 strncat(out_p, data, len);
351 ***************************************************************************
352 * Update line graph definition by appending current X,Y coordinates.
355 * @timetag Timestamp in seconds since the epoch for current sample
356 * stats. Will be used as X coordinate.
357 * @value Value of current sample metric. Will be used as Y coordinate.
358 * @out Pointer on array of chars for current graph definition.
359 * @outsize Size of array of chars for current graph definition.
360 * @restart Set to TRUE if a RESTART record has been read since the last
364 * @out Pointer on array of chars for current graph definition that
365 * has been updated with the addition of current sample data.
366 * @outsize Array that containing the (possibly new) sizes of each
367 * element in array of chars.
368 ***************************************************************************
370 void lnappend(unsigned long long timetag, double value, char **out, int *outsize,
375 /* Prepare additional graph definition data */
376 snprintf(data, 128, " %c%llu,%.2f", restart ? 'M' : 'L', timetag, value);
379 save_svg_data(data, out, outsize);
383 ***************************************************************************
384 * Update line graph definition by appending current X,Y coordinates. Use
385 * (unsigned long) integer values here.
388 * @timetag Timestamp in seconds since the epoch for current sample
389 * stats. Will be used as X coordinate.
390 * @value Value of current sample metric. Will be used as Y coordinate.
391 * @out Pointer on array of chars for current graph definition.
392 * @outsize Size of array of chars for current graph definition.
393 * @restart Set to TRUE if a RESTART record has been read since the last
397 * @out Pointer on array of chars for current graph definition that
398 * has been updated with the addition of current sample data.
399 * @outsize Array that containing the (possibly new) sizes of each
400 * element in array of chars.
401 ***************************************************************************
403 void lniappend(unsigned long long timetag, unsigned long value, char **out,
404 int *outsize, int restart)
408 /* Prepare additional graph definition data */
409 snprintf(data, 128, " %c%llu,%lu", restart ? 'M' : 'L', timetag, value);
412 save_svg_data(data, out, outsize);
416 ***************************************************************************
417 * Update bar graph definition by adding a new rectangle.
420 * @timetag Timestamp in seconds since the epoch for current sample
421 * stats. Will be used as X coordinate.
422 * @value Value of current sample metric. Will be used as rectangle
424 * @offset Offset for Y coordinate.
425 * @out Pointer on array of chars for current graph definition.
426 * @outsize Size of array of chars for current graph definition.
427 * @dt Interval of time in seconds between current and previous
431 * @out Pointer on array of chars for current graph definition that
432 * has been updated with the addition of current sample data.
433 * @outsize Array that containing the (possibly new) sizes of each
434 * element in array of chars.
435 ***************************************************************************
437 void brappend(unsigned long long timetag, double offset, double value, char **out,
438 int *outsize, unsigned long long dt)
442 /* Prepare additional graph definition data */
443 if ((value == 0.0) || (dt == 0))
444 /* Dont draw a flat rectangle! */
447 snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
448 timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
451 save_svg_data(data, out, outsize);
456 ***************************************************************************
457 * Update CPU graph and min/max values for each metric.
460 * @timetag Timestamp in seconds since the epoch for current sample
461 * stats. Will be used as X coordinate.
462 * @offset Offset for Y coordinate.
463 * @value Value of current CPU metric. Will be used as rectangle
465 * @out Pointer on array of chars for current graph definition.
466 * @outsize Size of array of chars for current graph definition.
467 * @dt Interval of time in seconds between current and previous
469 * @spmin Min value already found for this CPU metric.
470 * @spmax Max value already found for this CPU metric.
473 * @offset New offset value, to use to draw next rectangle
474 * @out Pointer on array of chars for current graph definition that
475 * has been updated with the addition of current sample data.
476 * @outsize Array that containing the (possibly new) sizes of each
477 * element in array of chars.
478 ***************************************************************************
480 void cpuappend(unsigned long long timetag, double *offset, double value, char **out,
481 int *outsize, unsigned long long dt, double *spmin, double *spmax)
483 /* Save min and max values */
484 if (value < *spmin) {
487 if (value > *spmax) {
490 /* Prepare additional graph definition data */
491 brappend(timetag, *offset, value, out, outsize, dt);
497 ***************************************************************************
498 * Update rectangular graph and min/max values.
501 * @timetag Timestamp in seconds since the epoch for current sample
502 * stats. Will be used as X coordinate.
503 * @p_value Metric value for previous sample
504 * @value Metric value for current sample.
505 * @out Pointer on array of chars for current graph definition.
506 * @outsize Size of array of chars for current graph definition.
507 * @restart Set to TRUE if a RESTART record has been read since the last
509 * @dt Interval of time in seconds between current and previous
511 * @spmin Min value already found for this metric.
512 * @spmax Max value already found for this metric.
515 * @out Pointer on array of chars for current graph definition that
516 * has been updated with the addition of current sample data.
517 * @outsize Array that containing the (possibly new) sizes of each
518 * element in array of chars.
519 * @spmin Min value for this metric.
520 * @spmax Max value for this metric.
521 ***************************************************************************
523 void recappend(unsigned long long timetag, double p_value, double value, char **out,
524 int *outsize, int restart, unsigned long long dt,
525 double *spmin, double *spmax)
527 char data[128], data1[128], data2[128];
529 /* Save min and max values */
530 if (value < *spmin) {
533 if (value > *spmax) {
536 /* Prepare additional graph definition data */
538 snprintf(data1, 128, " M%llu,%.2f", timetag - dt, p_value);
541 if (p_value != value) {
542 snprintf(data2, 128, " L%llu,%.2f", timetag, value);
545 snprintf(data, 128, "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
546 p_value != value ? data2 : "");
549 save_svg_data(data, out, outsize);
553 ***************************************************************************
554 * Calculate 10 raised to the power of n.
557 * @n Power number to use.
560 * 10 raised to the power of n.
561 ***************************************************************************
563 unsigned int pwr10(int n)
568 for (i = 0; i < n; i++) {
576 ***************************************************************************
577 * Autoscale graphs of a given view.
580 * @asf_nr (Maximum) number of autoscale factors.
581 * @group Number of graphs in current view.
582 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH).
583 * @pos Position in array for the first graph in view.
584 * @gmax Global max value for all graphs in view.
585 * @spmax Array containing max values for graphs.
588 * @asfactor Autoscale factors (one for each graph).
589 ***************************************************************************
591 void gr_autoscaling(unsigned int asfactor[], int asf_nr, int group, int g_type, int pos,
592 double gmax, double *spmax)
597 for (j = 0; j < asf_nr; j++) {
598 /* Init autoscale factors */
602 if (AUTOSCALE_ON(flags) && (group > 1) && gmax && (g_type == SVG_LINE_GRAPH)) {
604 for (j = 0; (j < group) && (j < asf_nr); j++) {
605 if (!*(spmax + pos + j) || (*(spmax + pos + j) == gmax))
608 snprintf(val, 32, "%u", (unsigned int) (gmax / *(spmax + pos + j)));
609 if (strlen(val) > 0) {
610 asfactor[j] = pwr10(strlen(val) - 1);
617 ***************************************************************************
618 * Display background grid (horizontal lines) and corresponding graduations.
621 * @ypos Gap between two horizontal lines.
622 * @yfactor Scaling factor on Y axis.
623 * @lmax Max value for current view.
624 * @dp Number of decimal places for graduations.
625 ***************************************************************************
627 void display_hgrid(double ypos, double yfactor, double lmax, int dp)
633 /* Display horizontal lines (except on X axis) */
635 printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
636 "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
637 ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
641 * Display graduations.
642 * Use same rounded value for graduation numbers as for grid lines
643 * to make sure they are properly aligned.
645 sprintf(stmp, "%.2f", ypos * j);
646 printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
647 "text-anchor: end\">%.*f.</text>\n",
648 (long) (atof(stmp) * yfactor), dp, ypos * j);
651 while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
655 ***************************************************************************
656 * Display background grid (vertical lines) and corresponding graduations.
659 * @xpos Gap between two vertical lines.
660 * @xfactor Scaling factor on X axis.
661 * @v_gridnr Number of vertical lines to display.
662 * @svg_p SVG specific parameters (see draw_activity_graphs() function).
663 ***************************************************************************
665 void display_vgrid(long int xpos, double xfactor, int v_gridnr, struct svg_parm *svg_p)
667 struct record_header stamp;
669 char cur_time[TIMESTAMP_LEN];
672 stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
674 for (j = 0; (j <= v_gridnr) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
676 /* Display vertical lines */
677 sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
678 set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
679 printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
680 "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
681 xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
683 * Display graduations.
684 * NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
685 * In this case, we should rather display the exact time instead of only the hour.
687 if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
688 printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
689 "text-anchor: start\">%2dH</text>\n",
690 (long) (xpos * j * xfactor) - 8, rectime.tm_hour);
693 printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
694 "text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
695 (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
697 stamp.ust_time += xpos;
700 if (!PRINT_LOCAL_TIME(flags)) {
701 printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
702 "text-anchor: end\">UTC</text>\n");
707 ***************************************************************************
708 * Calculate the value on the Y axis between two horizontal lines that will
709 * make the graph background grid.
712 * @lmax Max value reached for this graph.
715 * @dp Number of decimal places for Y graduations.
718 * Value between two horizontal lines.
719 ***************************************************************************
721 double ygrid(double lmax, int *dp)
732 n = (long) (lmax / SVG_H_GRIDNR);
735 return (lmax / SVG_H_GRIDNR);
737 snprintf(val, 32, "%ld", n);
744 return ((double) (((long) (n / e)) * e));
748 ***************************************************************************
749 * Calculate the value on the X axis between two vertical lines that will
750 * make the graph background grid.
753 * @timestart First data timestamp (X coordinate of the first data point).
754 * @timeend Last data timestamp (X coordinate of the last data point).
755 * @v_gridnr Number of vertical lines to display. Its value is normally
756 * SVG_V_GRIDNR, except when option "oneday" is used, in which
757 * case it is set to 12.
760 * Value between two vertical lines.
761 ***************************************************************************
763 long int xgrid(unsigned long timestart, unsigned long timeend, int v_gridnr)
765 if ((timeend - timestart) <= v_gridnr)
768 return ((timeend - timestart) / v_gridnr);
772 ***************************************************************************
773 * Free global graphs structures.
776 * @out Pointer on array of chars for each graph definition.
777 * @outsize Size of array of chars for each graph definition.
778 * @spmin Array containing min values for graphs.
779 * @spmax Array containing max values for graphs.
780 ***************************************************************************
782 void free_graphs(char **out, int *outsize, double *spmin, double *spmax)
799 ***************************************************************************
800 * Skip current view where all graphs have only zero values. This function
801 * is called when option "skipempty" has been used, or when "No data" have
802 * been found for current view.
805 * @out Pointer on array of chars for each graph definition.
806 * @pos Position of current view in the array of graphs definitions.
807 * @group Number of graphs in current view.
810 * @pos Position of next view in the array of graphs definitions.
811 ***************************************************************************
813 void skip_current_view(char **out, int *pos, int group)
818 for (j = 0; j < group; j++) {
819 out_p = *(out + *pos + j);
821 /* Even if not displayed, current graph data have to be freed */
829 ***************************************************************************
830 * Display all graphs for current activity.
833 * @g_nr Number of views to display.
834 * @g_type Type of graph (SVG_LINE_GRAPH, SVG_BAR_GRAPH) for each view.
835 * @title Titles for each set of graphs.
836 * @g_title Titles for each graph.
837 * @item_name Item (network interface, etc.) name.
838 * @group Indicate how graphs are grouped together to make sets.
839 * @spmin Array containing min values for graphs.
840 * @spmax Array containing max values for graphs.
841 * @out Pointer on array of chars for each graph definition.
842 * @outsize Size of array of chars for each graph definition.
843 * @svg_p SVG specific parameters: Current views row number (.@graph_no),
844 * time for the first sample of stats (.@ust_time_first), and
845 * times used as start and end values on the X axis
846 * (.@ust_time_ref and .@ust_time_end).
847 * @record_hdr Pointer on record header of current stats sample.
848 ***************************************************************************
850 void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
851 int group[], double *spmin, double *spmax, char **out, int *outsize,
852 struct svg_parm *svg_p, struct record_header *record_hdr)
855 int i, j, dp, pos = 0, views_nr = 0;
856 int v_gridnr, xv, yv;
857 unsigned int asfactor[16];
859 double lmax, xfactor, yfactor, ypos, gmin, gmax;
860 char val[32], cur_date[TIMESTAMP_LEN];
862 /* Translate to proper position for current activity */
863 printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
865 SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
867 /* For each view which is part of current activity */
868 for (i = 0; i < g_nr; i++) {
870 /* Get global min and max value for current view */
871 get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
873 /* Don't display empty views if requested */
874 if (SKIP_EMPTY_VIEWS(flags) && (gmax < 0.005)) {
875 skip_current_view(out, &pos, group[i]);
878 /* Increment number of views actually displayed */
881 /* Compute top left position of view */
882 if (PACK_VIEWS(flags)) {
883 xv = (views_nr - 1) * SVG_T_XSIZE;
888 yv = (views_nr - 1) * SVG_T_YSIZE;
891 /* Graph background */
892 printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
893 xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
896 printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
897 xv, 20 + yv, title[i]);
899 printf(" [%s]", item_name);
902 printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
903 "(Min, Max values)</tspan>\n</text>\n",
904 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
907 * At least two samples are needed.
908 * And a min and max value should have been found.
910 if ((record_hdr->ust_time == svg_p->ust_time_first) ||
911 (*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
913 printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
914 xv, yv + SVG_M_YSIZE);
915 skip_current_view(out, &pos, group[i]);
920 printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
921 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
922 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
923 xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
925 /* Autoscaling graphs if needed */
926 gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
929 for (j = 0; j < group[i]; j++) {
930 /* Set dp to TRUE (1) if current metric is based on integer values */
931 dp = (g_title[pos + j][0] == '~');
932 snprintf(val, 32, "x%u ", asfactor[j]);
933 printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
934 "%s %s(%.*f, %.*f)</text>\n",
935 xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
936 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
937 asfactor[j] == 1 ? "" : val,
938 !dp * 2, *(spmin + pos + j) * asfactor[j],
939 !dp * 2, *(spmax + pos + j) * asfactor[j]);
942 if (DISPLAY_INFO(flags)) {
943 /* Display additional info (hostname, date) */
944 printf("<text x=\"%d\" y=\"%d\" "
945 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
947 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
948 svg_p->file_hdr->sa_nodename);
950 /* Get report date */
951 set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
952 cur_date, sizeof(cur_date));
953 printf("<tspan x=\"%d\" y=\"%d\" "
954 "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
955 "%s</tspan>\n</text>\n",
956 xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
960 /* Translate to proper position for current graph within current activity */
961 printf("<g transform=\"translate(%d,%d)\">\n",
962 xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
965 if (g_type[i] == SVG_LINE_GRAPH) {
966 /* For line graphs */
968 /* If all values are zero then set current max value to 1 */
974 /* Max value cannot be too small, else Y graduations will be meaningless */
975 if (lmax < SVG_H_GRIDNR * 0.01) {
976 lmax = SVG_H_GRIDNR * 0.01;
978 ypos = ygrid(lmax, &dp);
981 /* For bar graphs (used for %values) */
982 ypos = 25.0; /* Draw lines at 25%, 50%, 75% and 100% */
983 dp = 0; /* No decimals */
985 /* Max should be always 100% except for percentage values greater than 100% */
993 yfactor = (double) -SVG_G_YSIZE / lmax;
995 /* Display horizontal lines and graduations */
996 display_hgrid(ypos, yfactor, lmax, dp);
998 /* Set number of vertical lines to 12 when option "oneday" is used */
999 v_gridnr = DISPLAY_ONE_DAY(flags) ? 12 : SVG_V_GRIDNR;
1001 xpos = xgrid(svg_p->ust_time_ref, svg_p->ust_time_end, v_gridnr);
1002 xfactor = (double) SVG_G_XSIZE / (svg_p->ust_time_end - svg_p->ust_time_ref);
1004 /* Display vertical lines and graduations */
1005 display_vgrid(xpos, xfactor, v_gridnr, svg_p);
1007 /* Draw current graphs set */
1008 for (j = 0; j < group[i]; j++) {
1009 out_p = *(out + pos + j);
1010 if (g_type[i] == SVG_LINE_GRAPH) {
1012 printf("<path id=\"g%dp%d\" d=\"%s\" "
1013 "style=\"vector-effect: non-scaling-stroke; "
1014 "stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
1015 "transform=\"scale(%f,%f)\"/>\n",
1016 svg_p->graph_no, pos + j, out_p,
1017 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
1019 yfactor * asfactor[j]);
1021 else if (*out_p) { /* Ignore flat bars */
1023 printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
1024 svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
1025 printf("%s\n", out_p);
1035 /* For next row of views */
1036 (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
1040 ***************************************************************************
1041 * Display CPU statistics in SVG.
1044 * @a Activity structure with statistics.
1045 * @curr Index in array for current sample statistics.
1046 * @action Action expected from current function.
1047 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1048 * flag indicating that a restart record has been previously
1049 * found (.@restart), and time used for the X axis origin
1051 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1053 * @record_hdr Pointer on record header of current stats sample.
1054 ***************************************************************************
1056 __print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1057 unsigned long long itv, struct record_header *record_hdr)
1059 struct stats_cpu *scc, *scp;
1060 unsigned long long tot_jiffies_c, tot_jiffies_p;
1061 unsigned long long deltot_jiffies;
1064 int g_type[] = {SVG_BAR_GRAPH};
1065 char *title[] = {"CPU load"};
1066 char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
1067 char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
1068 static double *spmin, *spmax;
1070 static int *outsize;
1075 if (action & F_BEGIN) {
1077 * Allocate arrays that will contain the graphs data
1078 * and the min/max values.
1080 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
1083 if (action & F_MAIN) {
1085 /* @nr[curr] cannot normally be greater than @nr_ini */
1086 if (a->nr[curr] > a->nr_ini) {
1087 a->nr_ini = a->nr[curr];
1091 for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
1093 scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
1094 scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
1096 /* Should current CPU (including CPU "all") be displayed? */
1097 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1102 * Yes: Compute the total number of jiffies spent by current processor.
1103 * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
1104 * already include them.
1106 tot_jiffies_c = scc->cpu_user + scc->cpu_nice +
1107 scc->cpu_sys + scc->cpu_idle +
1108 scc->cpu_iowait + scc->cpu_hardirq +
1109 scc->cpu_steal + scc->cpu_softirq;
1110 tot_jiffies_p = scp->cpu_user + scp->cpu_nice +
1111 scp->cpu_sys + scp->cpu_idle +
1112 scp->cpu_iowait + scp->cpu_hardirq +
1113 scp->cpu_steal + scp->cpu_softirq;
1115 /* Total number of jiffies spent on the interval */
1116 deltot_jiffies = get_interval(tot_jiffies_p, tot_jiffies_c);
1121 if (i) { /* Don't test CPU "all" here */
1123 * If the CPU is offline then it is omited from /proc/stat:
1124 * All the fields couldn't have been read and the sum of them is zero.
1125 * (Remember that guest/guest_nice times are already included in
1128 if (tot_jiffies_c == 0) {
1130 * Set current struct fields (which have been set to zero)
1131 * to values from previous iteration. Hence their values won't
1132 * jump from zero when the CPU comes back online.
1136 /* An offline CPU is not displayed */
1139 if (tot_jiffies_p == 0)
1140 /* CPU has just come back online */
1144 * Recalculate interval for current proc.
1145 * If result is 0 then current CPU is a tickless one.
1147 deltot_jiffies = get_per_cpu_interval(scc, scp);
1149 if (!deltot_jiffies) { /* Current CPU is tickless */
1151 val = 100.0; /* Tickless CPU: %idle = 100% */
1153 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1156 else { /* DISPLAY_CPU_ALL(a->opt_flags) */
1160 /* Check min/max values for %user, etc. */
1161 for (k = 0; k < j; k++) {
1162 if (0.0 < *(spmin + pos + k)) {
1163 *(spmin + pos + k) = 0.0;
1165 if (0.0 > *(spmax + pos + k)) {
1166 *(spmax + pos + k) = 0.0;
1171 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1173 out + pos + j, outsize + pos + j, svg_p->dt,
1174 spmin + pos + j, spmax + pos + j);
1179 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1181 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1182 &offset, ll_sp_value(scp->cpu_user, scc->cpu_user, deltot_jiffies),
1183 out + pos, outsize + pos, svg_p->dt,
1184 spmin + pos, spmax + pos);
1188 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1190 (scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest) ?
1192 ll_sp_value(scp->cpu_user - scp->cpu_guest,
1193 scc->cpu_user - scc->cpu_guest, deltot_jiffies),
1194 out + pos, outsize + pos, svg_p->dt,
1195 spmin + pos, spmax + pos);
1198 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1200 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1201 &offset, ll_sp_value(scp->cpu_nice, scc->cpu_nice, deltot_jiffies),
1202 out + pos + 1, outsize + pos + 1, svg_p->dt,
1203 spmin + pos + 1, spmax + pos + 1);
1207 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1209 (scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice) ?
1211 ll_sp_value(scp->cpu_nice - scp->cpu_guest_nice,
1212 scc->cpu_nice - scc->cpu_guest_nice, deltot_jiffies),
1213 out + pos + 1, outsize + pos + 1, svg_p->dt,
1214 spmin + pos + 1, spmax + pos + 1);
1217 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1219 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1221 ll_sp_value(scp->cpu_sys + scp->cpu_hardirq + scp->cpu_softirq,
1222 scc->cpu_sys + scc->cpu_hardirq + scc->cpu_softirq,
1224 out + pos + 2, outsize + pos + 2, svg_p->dt,
1225 spmin + pos + 2, spmax + pos + 2);
1229 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1230 &offset, ll_sp_value(scp->cpu_sys, scc->cpu_sys, deltot_jiffies),
1231 out + pos + 2, outsize + pos + 2, svg_p->dt,
1232 spmin + pos + 2, spmax + pos + 2);
1236 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1237 &offset, ll_sp_value(scp->cpu_iowait, scc->cpu_iowait, deltot_jiffies),
1238 out + pos + 3, outsize + pos + 3, svg_p->dt,
1239 spmin + pos + 3, spmax + pos + 3);
1241 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1242 &offset, ll_sp_value(scp->cpu_steal, scc->cpu_steal, deltot_jiffies),
1243 out + pos + 4, outsize + pos + 4, svg_p->dt,
1244 spmin + pos + 4, spmax + pos + 4);
1246 if (DISPLAY_CPU_ALL(a->opt_flags)) {
1248 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1249 &offset, ll_sp_value(scp->cpu_hardirq, scc->cpu_hardirq, deltot_jiffies),
1250 out + pos + 5, outsize + pos + 5, svg_p->dt,
1251 spmin + pos + 5, spmax + pos + 5);
1253 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1254 &offset, ll_sp_value(scp->cpu_softirq, scc->cpu_softirq, deltot_jiffies),
1255 out + pos + 6, outsize + pos + 6, svg_p->dt,
1256 spmin + pos + 6, spmax + pos + 6);
1258 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1259 &offset, ll_sp_value(scp->cpu_guest, scc->cpu_guest, deltot_jiffies),
1260 out + pos + 7, outsize + pos + 7, svg_p->dt,
1261 spmin + pos + 7, spmax + pos + 7);
1263 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1264 &offset, ll_sp_value(scp->cpu_guest_nice, scc->cpu_guest_nice, deltot_jiffies),
1265 out + pos + 8, outsize + pos + 8, svg_p->dt,
1266 spmin + pos + 8, spmax + pos + 8);
1275 cpuappend(record_hdr->ust_time - svg_p->ust_time_ref,
1277 (scc->cpu_idle < scp->cpu_idle ? 0.0 :
1278 ll_sp_value(scp->cpu_idle, scc->cpu_idle, deltot_jiffies)),
1279 out + pos + j, outsize + pos + j, svg_p->dt,
1280 spmin + pos + j, spmax + pos + j);
1284 if (action & F_END) {
1285 if (DISPLAY_IDLE(flags)) {
1286 /* Include additional %idle field */
1291 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
1293 /* Should current CPU (including CPU "all") be displayed? */
1294 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
1300 /* This is CPU "all" */
1301 strcpy(item_name, "all");
1304 sprintf(item_name, "%d", i - 1);
1307 if (DISPLAY_CPU_DEF(a->opt_flags)) {
1308 draw_activity_graphs(a->g_nr, g_type,
1309 title, g_title1, item_name, group1,
1310 spmin + pos, spmax + pos, out + pos, outsize + pos,
1314 draw_activity_graphs(a->g_nr, g_type,
1315 title, g_title2, item_name, group2,
1316 spmin + pos, spmax + pos, out + pos, outsize + pos,
1321 /* Free remaining structures */
1322 free_graphs(out, outsize, spmin, spmax);
1327 ***************************************************************************
1328 * Display task creation and context switch statistics in SVG.
1331 * @a Activity structure with statistics.
1332 * @curr Index in array for current sample statistics.
1333 * @action Action expected from current function.
1334 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1335 * flag indicating that a restart record has been previously
1336 * found (.@restart) and time used for the X axis origin
1338 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1339 * @record_hdr Pointer on record header of current stats sample.
1340 ***************************************************************************
1342 __print_funct_t svg_print_pcsw_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1343 unsigned long long itv, struct record_header *record_hdr)
1346 *spc = (struct stats_pcsw *) a->buf[curr],
1347 *spp = (struct stats_pcsw *) a->buf[!curr];
1348 int group[] = {1, 1};
1349 int g_fields[] = {1, 0};
1350 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1351 char *title[] = {"Task creation", "Switching activity"};
1352 char *g_title[] = {"proc/s",
1354 static double *spmin, *spmax;
1356 static int *outsize;
1358 if (action & F_BEGIN) {
1360 * Allocate arrays that will contain the graphs data
1361 * and the min/max values.
1363 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1366 if (action & F_MAIN) {
1367 /* Check for min/max values */
1368 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1369 itv, spmin, spmax, g_fields);
1371 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1372 S_VALUE(spp->processes, spc->processes, itv),
1373 out, outsize, svg_p->restart);
1375 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1376 S_VALUE(spp->context_switch, spc->context_switch, itv),
1377 out + 1, outsize + 1, svg_p->restart);
1380 if (action & F_END) {
1381 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1382 spmin, spmax, out, outsize, svg_p, record_hdr);
1384 /* Free remaining structures */
1385 free_graphs(out, outsize, spmin, spmax);
1390 ***************************************************************************
1391 * Display swap statistics in SVG.
1394 * @a Activity structure with statistics.
1395 * @curr Index in array for current sample statistics.
1396 * @action Action expected from current function.
1397 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1398 * flag indicating that a restart record has been previously
1399 * found (.@restart) and time used for the X axis origin
1401 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1402 * @record_hdr Pointer on record header of current stats sample.
1403 ***************************************************************************
1405 __print_funct_t svg_print_swap_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1406 unsigned long long itv, struct record_header *record_hdr)
1409 *ssc = (struct stats_swap *) a->buf[curr],
1410 *ssp = (struct stats_swap *) a->buf[!curr];
1412 int g_type[] = {SVG_LINE_GRAPH};
1413 char *title[] = {"Swap activity"};
1414 char *g_title[] = {"pswpin/s", "pswpout/s" };
1415 int g_fields[] = {0, 1};
1416 static double *spmin, *spmax;
1418 static int *outsize;
1420 if (action & F_BEGIN) {
1422 * Allocate arrays that will contain the graphs data
1423 * and the min/max values.
1425 out = allocate_graph_lines(2, &outsize, &spmin, &spmax);
1428 if (action & F_MAIN) {
1429 /* Check for min/max values */
1430 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1431 itv, spmin, spmax, g_fields);
1433 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1434 S_VALUE(ssp->pswpin, ssc->pswpin, itv),
1435 out, outsize, svg_p->restart);
1437 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1438 S_VALUE(ssp->pswpout, ssc->pswpout, itv),
1439 out + 1, outsize + 1, svg_p->restart);
1442 if (action & F_END) {
1443 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1444 spmin, spmax, out, outsize, svg_p, record_hdr);
1446 /* Free remaining structures */
1447 free_graphs(out, outsize, spmin, spmax);
1452 ***************************************************************************
1453 * Display paging statistics in SVG.
1456 * @a Activity structure with statistics.
1457 * @curr Index in array for current sample statistics.
1458 * @action Action expected from current function.
1459 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1460 * flag indicating that a restart record has been previously
1461 * found (.@restart) and time used for the X axis origin
1463 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1464 * @record_hdr Pointer on record header of current stats sample.
1465 ***************************************************************************
1467 __print_funct_t svg_print_paging_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1468 unsigned long long itv, struct record_header *record_hdr)
1471 *spc = (struct stats_paging *) a->buf[curr],
1472 *spp = (struct stats_paging *) a->buf[!curr];
1473 int group[] = {2, 2, 4};
1474 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1475 char *title[] = {"Paging activity (1)", "Paging activity (2)", "Paging activity (3)"};
1476 char *g_title[] = {"pgpgin/s", "pgpgout/s",
1477 "fault/s", "majflt/s",
1478 "pgfree/s", "pgscank/s", "pgscand/s", "pgsteal/s"};
1479 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
1480 static double *spmin, *spmax;
1482 static int *outsize;
1484 if (action & F_BEGIN) {
1486 * Allocate arrays that will contain the graphs data
1487 * and the min/max values.
1489 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
1492 if (action & F_MAIN) {
1493 /* Check for min/max values */
1494 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1495 itv, spmin, spmax, g_fields);
1497 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1498 S_VALUE(spp->pgpgin, spc->pgpgin, itv),
1499 out, outsize, svg_p->restart);
1501 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1502 S_VALUE(spp->pgpgout, spc->pgpgout, itv),
1503 out + 1, outsize + 1, svg_p->restart);
1505 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1506 S_VALUE(spp->pgfault, spc->pgfault, itv),
1507 out + 2, outsize + 2, svg_p->restart);
1509 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1510 S_VALUE(spp->pgmajfault, spc->pgmajfault, itv),
1511 out + 3, outsize + 3, svg_p->restart);
1513 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1514 S_VALUE(spp->pgfree, spc->pgfree, itv),
1515 out + 4, outsize + 4, svg_p->restart);
1517 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1518 S_VALUE(spp->pgscan_kswapd, spc->pgscan_kswapd, itv),
1519 out + 5, outsize + 5, svg_p->restart);
1521 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1522 S_VALUE(spp->pgscan_direct, spc->pgscan_direct, itv),
1523 out + 6, outsize + 6, svg_p->restart);
1525 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1526 S_VALUE(spp->pgsteal, spc->pgsteal, itv),
1527 out + 7, outsize + 7, svg_p->restart);
1530 if (action & F_END) {
1531 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1532 spmin, spmax, out, outsize, svg_p, record_hdr);
1534 /* Free remaining structures */
1535 free_graphs(out, outsize, spmin, spmax);
1540 ***************************************************************************
1541 * Display I/O and transfer rate statistics in SVG.
1544 * @a Activity structure with statistics.
1545 * @curr Index in array for current sample statistics.
1546 * @action Action expected from current function.
1547 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1548 * flag indicating that a restart record has been previously
1549 * found (.@restart) and time used for the X axis origin
1551 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1552 * @record_hdr Pointer on record header of current stats sample.
1553 ***************************************************************************
1555 __print_funct_t svg_print_io_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1556 unsigned long long itv, struct record_header *record_hdr)
1559 *sic = (struct stats_io *) a->buf[curr],
1560 *sip = (struct stats_io *) a->buf[!curr];
1561 int group[] = {3, 2};
1562 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1563 char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
1564 char *g_title[] = {"tps", "rtps", "wtps",
1565 "bread/s", "bwrtn/s"};
1566 int g_fields[] = {0, 1, 2, 3, 4};
1567 static double *spmin, *spmax;
1569 static int *outsize;
1571 if (action & F_BEGIN) {
1573 * Allocate arrays that will contain the graphs data
1574 * and the min/max values.
1576 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
1579 if (action & F_MAIN) {
1580 /* Check for min/max values */
1581 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
1582 itv, spmin, spmax, g_fields);
1585 * If we get negative values, this is probably because
1586 * one or more devices/filesystems have been unmounted.
1587 * We display 0.0 in this case though we should rather tell
1588 * the user that the value cannot be calculated here.
1591 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1592 sic->dk_drive < sip->dk_drive ? 0.0 :
1593 S_VALUE(sip->dk_drive, sic->dk_drive, itv),
1594 out, outsize, svg_p->restart);
1596 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1597 sic->dk_drive_rio < sip->dk_drive_rio ? 0.0 :
1598 S_VALUE(sip->dk_drive_rio, sic->dk_drive_rio, itv),
1599 out + 1, outsize + 1, svg_p->restart);
1601 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1602 sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
1603 S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
1604 out + 2, outsize + 2, svg_p->restart);
1606 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1607 sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
1608 S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
1609 out + 3, outsize + 3, svg_p->restart);
1611 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1612 sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
1613 S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
1614 out + 4, outsize + 4, svg_p->restart);
1617 if (action & F_END) {
1618 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1619 spmin, spmax, out, outsize, svg_p, record_hdr);
1621 /* Free remaining structures */
1622 free_graphs(out, outsize, spmin, spmax);
1627 ***************************************************************************
1628 * Display memory statistics in SVG.
1631 * @a Activity structure with statistics.
1632 * @curr Index in array for current sample statistics.
1633 * @action Action expected from current function.
1634 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1635 * flag indicating that a restart record has been previously
1636 * found (.@restart) and time used for the X axis origin
1638 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1639 * @record_hdr Pointer on record header of current stats sample.
1640 ***************************************************************************
1642 __print_funct_t svg_print_memory_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1643 unsigned long long itv, struct record_header *record_hdr)
1646 *smc = (struct stats_memory *) a->buf[curr];
1647 int group1[] = {3, 1, 3, 1, 3, 5};
1648 int g_type1[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH,
1649 SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1650 int group2[] = {3, 1, 1};
1651 int g_type2[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_BAR_GRAPH};
1652 char *title1[] = {"Memory utilization (1)", "Memory utilization (2)",
1653 "Memory utilization (3)", "Memory utilization (4)",
1654 "Memory utilization (5)", "Memory utilization (6)"};
1655 char *title2[] = {"Swap utilization (1)", "Swap utilization (2)",
1656 "Swap utilization (3)"};
1657 char *g_title1[] = {"MBmemfree", "MBavail", "MBmemused", "%memused", "MBbuffers",
1658 "MBcached", "MBcommit", "%commit", "MBactive", "MBinact",
1659 "MBdirty", "MBanonpg", "MBslab", "MBkstack", "MBpgtbl",
1661 char *g_title2[] = {"MBswpfree", "MBswpused", "MBswpcad", "%swpused",
1663 int g_fields[] = {0, 4, 5, 21, 16, 22, 18, 6, 8, 9, 10, 11, 12, 13, 14, 15, 1};
1664 static double *spmin, *spmax;
1666 static int *outsize;
1670 if (action & F_BEGIN) {
1672 * Allocate arrays that will contain the graphs data
1673 * and the min/max values.
1675 out = allocate_graph_lines(23, &outsize, &spmin, &spmax);
1678 if (action & F_MAIN) {
1679 /* Check for min/max values */
1680 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1681 itv, spmin, spmax, g_fields);
1682 /* Compute %memused min/max values */
1683 tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
1684 if (tval > *(spmax + 3)) {
1685 *(spmax + 3) = tval;
1687 if (tval < *(spmin + 3)) {
1688 *(spmin + 3) = tval;
1690 /* Compute %commit min/max values */
1691 tval = (smc->tlmkb + smc->tlskb) ?
1692 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0;
1693 if (tval > *(spmax + 7)) {
1694 *(spmax + 7) = tval;
1696 if (tval < *(spmin + 7)) {
1697 *(spmin + 7) = tval;
1699 /* Compute %swpused min/max values */
1701 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0;
1702 if (tval > *(spmax + 19)) {
1703 *(spmax + 19) = tval;
1705 if (tval < *(spmin + 19)) {
1706 *(spmin + 19) = tval;
1708 /* Compute %swpcad min/max values */
1709 tval = (smc->tlskb - smc->frskb) ?
1710 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0;
1711 if (tval > *(spmax + 20)) {
1712 *(spmax + 20) = tval;
1714 if (tval < *(spmin + 20)) {
1715 *(spmin + 20) = tval;
1717 /* Compute memused min/max values in MB */
1718 tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
1719 if (tval > *(spmax + 2)) {
1720 *(spmax + 2) = tval;
1722 if (tval < *(spmin + 2)) {
1723 *(spmin + 2) = tval;
1725 /* Compute swpused min/max values in MB */
1726 tval = ((double) (smc->tlskb - smc->frskb)) / 1024;
1727 if (tval > *(spmax + 17)) {
1728 *(spmax + 17) = tval;
1730 if (tval < *(spmin + 17)) {
1731 *(spmin + 17) = tval;
1735 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1736 ((double) smc->frmkb) / 1024,
1737 out, outsize, svg_p->restart);
1739 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1740 ((double) (smc->tlmkb - smc->frmkb)) / 1024,
1741 out + 2, outsize + 2, svg_p->restart);
1743 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1744 ((double) smc->availablekb) / 1024,
1745 out + 1, outsize + 1, svg_p->restart);
1747 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1748 ((double) smc->bufkb) / 1024,
1749 out + 4, outsize + 4, svg_p->restart);
1751 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1752 ((double) smc->camkb) / 1024,
1753 out + 5, outsize + 5, svg_p->restart);
1755 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1756 ((double) smc->frskb) / 1024,
1757 out + 16, outsize + 16, svg_p->restart);
1759 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1760 ((double) (smc->tlskb - smc->frskb)) / 1024,
1761 out + 17, outsize + 17, svg_p->restart);
1763 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1764 ((double) smc->caskb) / 1024,
1765 out + 18, outsize + 18, svg_p->restart);
1767 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1768 ((double) smc->comkb) / 1024,
1769 out + 6, outsize + 6, svg_p->restart);
1771 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1772 ((double) smc->activekb) / 1024,
1773 out + 8, outsize + 8, svg_p->restart);
1775 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1776 ((double) smc->inactkb) / 1024,
1777 out + 9, outsize + 9, svg_p->restart);
1779 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1780 ((double) smc->dirtykb) / 1024,
1781 out + 10, outsize + 10, svg_p->restart);
1783 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1784 ((double) smc->anonpgkb) / 1024,
1785 out + 11, outsize + 11, svg_p->restart);
1787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1788 ((double) smc->slabkb) / 1024,
1789 out + 12, outsize + 12, svg_p->restart);
1791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1792 ((double) smc->kstackkb) / 1024,
1793 out + 13, outsize + 13, svg_p->restart);
1795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1796 ((double) smc->pgtblkb) / 1024,
1797 out + 14, outsize + 14, svg_p->restart);
1799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1800 ((double) smc->vmusedkb) / 1024,
1801 out + 15, outsize + 15, svg_p->restart);
1803 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1806 SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
1807 out + 3, outsize + 3, svg_p->dt);
1809 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1811 (smc->tlmkb + smc->tlskb) ?
1812 SP_VALUE(0, smc->comkb, smc->tlmkb + smc->tlskb) : 0.0,
1813 out + 7, outsize + 7, svg_p->dt);
1815 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1818 SP_VALUE(smc->frskb, smc->tlskb, smc->tlskb) : 0.0,
1819 out + 19, outsize + 19, svg_p->dt);
1821 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
1823 (smc->tlskb - smc->frskb) ?
1824 SP_VALUE(0, smc->caskb, smc->tlskb - smc->frskb) : 0.0,
1825 out + 20, outsize + 20, svg_p->dt);
1828 if (action & F_END) {
1830 /* Conversion kB -> MB */
1831 for (i = 0; i < 17; i++) {
1832 *(spmin + g_fields[i]) /= 1024;
1833 *(spmax + g_fields[i]) /= 1024;
1836 if (DISPLAY_MEMORY(a->opt_flags)) {
1837 draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
1838 g_type1, title1, g_title1, NULL, group1,
1839 spmin, spmax, out, outsize, svg_p, record_hdr);
1842 if (DISPLAY_SWAP(a->opt_flags)) {
1843 draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
1844 spmin + 16, spmax + 16, out + 16, outsize + 16,
1848 /* Free remaining structures */
1849 free_graphs(out, outsize, spmin, spmax);
1854 ***************************************************************************
1855 * Display kernel tables statistics in SVG.
1858 * @a Activity structure with statistics.
1859 * @curr Index in array for current sample statistics.
1860 * @action Action expected from current function.
1861 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1862 * flag indicating that a restart record has been previously
1863 * found (.@restart) and time used for the X axis origin
1865 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1866 * @record_hdr Pointer on record header of current stats sample.
1867 ***************************************************************************
1869 __print_funct_t svg_print_ktables_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1870 unsigned long long itv, struct record_header *record_hdr)
1872 struct stats_ktables
1873 *skc = (struct stats_ktables *) a->buf[curr];
1874 int group[] = {3, 1};
1875 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1876 char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
1877 char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
1879 int g_fields[] = {1, 2, 0, 3};
1880 static double *spmin, *spmax;
1882 static int *outsize;
1884 if (action & F_BEGIN) {
1886 * Allocate arrays that will contain the graphs data
1887 * and the min/max values.
1889 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
1892 if (action & F_MAIN) {
1893 /* Check for min/max values */
1894 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1895 itv, spmin, spmax, g_fields);
1897 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1898 (unsigned long) skc->dentry_stat,
1899 out, outsize, svg_p->restart);
1901 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1902 (unsigned long) skc->file_used,
1903 out + 1, outsize + 1, svg_p->restart);
1905 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1906 (unsigned long) skc->inode_used,
1907 out + 2, outsize + 2, svg_p->restart);
1909 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1910 (unsigned long) skc->pty_nr,
1911 out + 3, outsize + 3, svg_p->restart);
1914 if (action & F_END) {
1915 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
1916 spmin, spmax, out, outsize, svg_p, record_hdr);
1918 /* Free remaining structures */
1919 free_graphs(out, outsize, spmin, spmax);
1924 ***************************************************************************
1925 * Display queue and load statistics in SVG.
1928 * @a Activity structure with statistics.
1929 * @curr Index in array for current sample statistics.
1930 * @action Action expected from current function.
1931 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
1932 * flag indicating that a restart record has been previously
1933 * found (.@restart) and time used for the X axis origin
1935 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
1936 * @record_hdr Pointer on record header of current stats sample.
1937 ***************************************************************************
1939 __print_funct_t svg_print_queue_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
1940 unsigned long long itv, struct record_header *record_hdr)
1943 *sqc = (struct stats_queue *) a->buf[curr];
1944 int group[] = {2, 1, 3};
1945 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
1946 char *title[] = {"Queue length", "Task list", "Load average"};
1947 char *g_title[] = {"~runq-sz", "~blocked",
1949 "ldavg-1", "ldavg-5", "ldavg-15"};
1950 int g_fields[] = {0, 1, 3, 4, 5, 2};
1951 static double *spmin, *spmax;
1953 static int *outsize;
1955 if (action & F_BEGIN) {
1957 * Allocate arrays that will contain the graphs data
1958 * and the min/max values.
1960 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
1963 if (action & F_MAIN) {
1964 /* Check for min/max values */
1965 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
1966 itv, spmin, spmax, g_fields);
1968 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1969 (unsigned long) sqc->nr_running,
1970 out, outsize, svg_p->restart);
1972 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1973 (unsigned long) sqc->procs_blocked,
1974 out + 1, outsize + 1, svg_p->restart);
1976 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
1977 (unsigned long) sqc->nr_threads,
1978 out + 2, outsize + 2, svg_p->restart);
1980 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1981 (double) sqc->load_avg_1 / 100,
1982 out + 3, outsize + 3, svg_p->restart);
1984 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1985 (double) sqc->load_avg_5 / 100,
1986 out + 4, outsize + 4, svg_p->restart);
1988 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
1989 (double) sqc->load_avg_15 / 100,
1990 out + 5, outsize + 5, svg_p->restart);
1993 if (action & F_END) {
1994 /* Fix min/max values for load average */
1995 *(spmin + 3) /= 100; *(spmax + 3) /= 100;
1996 *(spmin + 4) /= 100; *(spmax + 4) /= 100;
1997 *(spmin + 5) /= 100; *(spmax + 5) /= 100;
1999 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2000 spmin, spmax, out, outsize, svg_p, record_hdr);
2002 /* Free remaining structures */
2003 free_graphs(out, outsize, spmin, spmax);
2008 ***************************************************************************
2009 * Display disk statistics in SVG.
2012 * @a Activity structure with statistics.
2013 * @curr Index in array for current sample statistics.
2014 * @action Action expected from current function.
2015 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2016 * flag indicating that a restart record has been previously
2017 * found (.@restart) and time used for the X axis origin
2019 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2020 * @record_hdr Pointer on record header of current stats sample.
2021 ***************************************************************************
2023 __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2024 unsigned long long itv, struct record_header *record_hdr)
2026 struct stats_disk *sdc, *sdp, sdpzero;
2027 struct ext_disk_stats xds;
2028 int group[] = {1, 2, 2, 2, 1};
2029 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2030 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
2031 char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
2032 "Disk statistics (3)", "Disk statistics (4)",
2033 "Disk statistics (5)"};
2034 char *g_title[] = {"tps",
2036 "areq-sz", "aqu-sz",
2039 int g_fields[] = {0, 1, 2};
2040 unsigned int local_types_nr[] = {1, 0, 0};
2041 static double *spmin, *spmax;
2043 static int *outsize;
2044 char *item_name, *persist_dev_name;
2045 double rkB, wkB, aqusz;
2046 int i, j, k, pos, restart, *unregistered;
2048 if (action & F_BEGIN) {
2050 * Allocate arrays (#0..7) that will contain the graphs data
2051 * and the min/max values.
2052 * Also allocate one additional array (#8) for each disk device:
2053 * spmax + 8 will contain the device major number,
2054 * spmin + 8 will contain the device minor number,
2055 * outsize + 8 will contain a positive value (TRUE) if the device
2056 * has either still not been registered, or has been unregistered.
2058 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2061 if (action & F_MAIN) {
2062 memset(&sdpzero, 0, STATS_DISK_SIZE);
2063 restart = svg_p->restart;
2065 * Mark previously registered devices as now
2066 * possibly unregistered for all graphs.
2068 for (k = 0; k < svg_p->nr_max; k++) {
2069 unregistered = outsize + k * 9 + 8;
2070 if (*unregistered == FALSE) {
2071 *unregistered = MAYBE;
2075 /* For each device structure */
2076 for (i = 0; i < a->nr[curr]; i++) {
2077 sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
2079 /* Look for corresponding graph */
2080 for (k = 0; k < svg_p->nr_max; k++) {
2081 if ((sdc->major == *(spmax + k * 9 + 8)) &&
2082 (sdc->minor == *(spmin + k * 9 + 8)))
2086 if (k == svg_p->nr_max) {
2087 /* Graph not found: Look for first free entry */
2088 for (k = 0; k < svg_p->nr_max; k++) {
2089 if (*(spmax + k * 9 + 8) == -DBL_MAX)
2092 if (k == svg_p->nr_max) {
2093 /* No free graph entry: Extend all buffers */
2094 reallocate_all_graph_lines(svg_p->nr_max,
2095 &out, &outsize, &spmin, &spmax);
2100 unregistered = outsize + pos + 8;
2102 j = check_disk_reg(a, curr, !curr, i);
2104 /* This is a newly registered interface. Previous stats are zero */
2108 sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
2112 * If current device was marked as previously unregistered,
2113 * then set restart variable to TRUE so that the graph will be
2114 * discontinuous, and mark it as now registered.
2116 if (*unregistered == TRUE) {
2119 *unregistered = FALSE;
2121 if (*(spmax + pos + 8) == -DBL_MAX) {
2122 /* Save device major and minor numbers (if not already done) */
2123 *(spmax + pos + 8) = sdc->major;
2124 *(spmin + pos + 8) = sdc->minor;
2127 /* Check for min/max values */
2128 save_extrema(local_types_nr, (void *) sdc, (void *) sdp,
2129 itv, spmin + pos, spmax + pos, g_fields);
2131 rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
2132 wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
2133 if (rkB < *(spmin + pos + 1)) {
2134 *(spmin + pos + 1) = rkB;
2136 if (rkB > *(spmax + pos + 1)) {
2137 *(spmax + pos + 1) = rkB;
2139 if (wkB < *(spmin + pos + 2)) {
2140 *(spmin + pos + 2) = wkB;
2142 if (wkB > *(spmax + pos + 2)) {
2143 *(spmax + pos + 2) = wkB;
2146 compute_ext_disk_stats(sdc, sdp, itv, &xds);
2147 if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
2148 *(spmin + pos + 3) = xds.arqsz / 2;
2150 if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
2151 *(spmax + pos + 3) = xds.arqsz / 2;
2153 aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
2154 if (aqusz < *(spmin + pos + 4)) {
2155 *(spmin + pos + 4) = aqusz;
2157 if (aqusz > *(spmax + pos + 4)) {
2158 *(spmax + pos + 4) = aqusz;
2160 if (xds.await < *(spmin + pos + 5)) {
2161 *(spmin + pos + 5) = xds.await;
2163 if (xds.await > *(spmax + pos + 5)) {
2164 *(spmax + pos + 5) = xds.await;
2166 if (xds.svctm < *(spmin + pos + 6)) {
2167 *(spmin + pos + 6) = xds.svctm;
2169 if (xds.svctm > *(spmax + pos + 6)) {
2170 *(spmax + pos + 6) = xds.svctm;
2172 if ((xds.util / 10.0) < *(spmin + pos + 7)) {
2173 *(spmin + pos + 7) = xds.util / 10.0;
2175 if ((xds.util / 10.0) > *(spmax + pos + 7)) {
2176 *(spmax + pos + 7) = xds.util / 10.0;
2180 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2181 S_VALUE(sdp->nr_ios, sdc->nr_ios, itv),
2182 out + pos, outsize + pos, restart);
2184 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2185 S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2,
2186 out + pos + 1, outsize + pos + 1, restart);
2188 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2189 S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
2190 out + pos + 2, outsize + pos + 2, restart);
2192 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2194 out + pos + 3, outsize + pos + 3, restart);
2196 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2198 out + pos + 4, outsize + pos + 4, restart);
2200 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2202 out + pos + 5, outsize + pos + 5, restart);
2204 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2206 out + pos + 6, outsize + pos + 6, restart);
2208 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2209 0.0, xds.util / 10.0,
2210 out + pos + 7, outsize + pos + 7, svg_p->dt);
2213 /* Mark devices not seen here as now unregistered */
2214 for (k = 0; k < svg_p->nr_max; k++) {
2215 unregistered = outsize + k * 9 + 8;
2216 if (*unregistered != FALSE) {
2217 *unregistered = TRUE;
2222 if (action & F_END) {
2223 for (i = 0; i < svg_p->nr_max; i++) {
2224 /* Check if there is something to display */
2230 persist_dev_name = NULL;
2232 if (DISPLAY_PERSIST_NAME_S(flags)) {
2233 persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
2237 if (persist_dev_name) {
2238 item_name = persist_dev_name;
2241 if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
2242 item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
2246 item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
2247 USE_PRETTY_OPTION(flags));
2251 draw_activity_graphs(a->g_nr, g_type,
2252 title, g_title, item_name, group,
2253 spmin + pos, spmax + pos, out + pos, outsize + pos,
2257 /* Free remaining structures */
2258 free_graphs(out, outsize, spmin, spmax);
2263 ***************************************************************************
2264 * Display network interfaces statistics in SVG.
2267 * @a Activity structure with statistics.
2268 * @curr Index in array for current sample statistics.
2269 * @action Action expected from current function.
2270 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2271 * flag indicating that a restart record has been previously
2272 * found (.@restart) and time used for the X axis origin
2274 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2275 * @record_hdr Pointer on record header of current stats sample.
2276 ***************************************************************************
2278 __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2279 unsigned long long itv, struct record_header *record_hdr)
2281 struct stats_net_dev *sndc, *sndp, sndzero;
2282 int group[] = {2, 2, 3, 1};
2283 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2285 char *title[] = {"Network statistics (1)", "Network statistics (2)",
2286 "Network statistics (3)", "Network statistics (4)"};
2287 char *g_title[] = {"rxpck/s", "txpck/s",
2289 "rxcmp/s", "txcmp/s", "rxmcst/s",
2291 int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
2292 unsigned int local_types_nr[] = {7, 0, 0};
2293 static double *spmin, *spmax;
2295 static int *outsize;
2297 double rxkb, txkb, ifutil;
2298 int i, j, k, pos, restart, *unregistered;
2300 if (action & F_BEGIN) {
2302 * Allocate arrays (#0..7) that will contain the graphs data
2303 * and the min/max values.
2304 * Also allocate one additional array (#8) for each interface:
2305 * out + 8 will contain the interface name,
2306 * outsize + 8 will contain a positive value (TRUE) if the interface
2307 * has either still not been registered, or has been unregistered.
2309 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
2312 if (action & F_MAIN) {
2313 memset(&sndzero, 0, STATS_NET_DEV_SIZE);
2314 restart = svg_p->restart;
2316 * Mark previously registered interfaces as now
2317 * possibly unregistered for all graphs.
2319 for (k = 0; k < svg_p->nr_max; k++) {
2320 unregistered = outsize + k * 9 + 8;
2321 if (*unregistered == FALSE) {
2322 *unregistered = MAYBE;
2326 /* For each network interfaces structure */
2327 for (i = 0; i < a->nr[curr]; i++) {
2328 sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
2330 /* Look for corresponding graph */
2331 for (k = 0; k < svg_p->nr_max; k++) {
2332 item_name = *(out + k * 9 + 8);
2333 if (!strcmp(sndc->interface, item_name))
2337 if (k == svg_p->nr_max) {
2338 /* Graph not found: Look for first free entry */
2339 for (k = 0; k < svg_p->nr_max; k++) {
2340 item_name = *(out + k * 9 + 8);
2341 if (!strcmp(item_name, ""))
2344 if (k == svg_p->nr_max) {
2345 /* No free graph entry: Extend all buffers */
2346 reallocate_all_graph_lines(svg_p->nr_max,
2347 &out, &outsize, &spmin, &spmax);
2353 unregistered = outsize + pos + 8;
2355 j = check_net_dev_reg(a, curr, !curr, i);
2357 /* This is a newly registered interface. Previous stats are zero */
2361 sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
2365 * If current interface was marked as previously unregistered,
2366 * then set restart variable to TRUE so that the graph will be
2367 * discontinuous, and mark it as now registered.
2369 if (*unregistered == TRUE) {
2372 *unregistered = FALSE;
2374 if (!item_name[0]) {
2375 /* Save network interface name (if not already done) */
2376 strncpy(item_name, sndc->interface, CHUNKSIZE);
2377 item_name[CHUNKSIZE - 1] = '\0';
2380 /* Check for min/max values */
2381 save_extrema(local_types_nr, (void *) sndc, (void *) sndp,
2382 itv, spmin + pos, spmax + pos, g_fields);
2384 rxkb = S_VALUE(sndp->rx_bytes, sndc->rx_bytes, itv);
2385 txkb = S_VALUE(sndp->tx_bytes, sndc->tx_bytes, itv);
2386 ifutil = compute_ifutil(sndc, rxkb, txkb);
2387 if (ifutil < *(spmin + pos + 7)) {
2388 *(spmin + pos + 7) = ifutil;
2390 if (ifutil > *(spmax + pos + 7)) {
2391 *(spmax + pos + 7) = ifutil;
2395 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2396 S_VALUE(sndp->rx_packets, sndc->rx_packets, itv),
2397 out + pos, outsize + pos, restart);
2399 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2400 S_VALUE(sndp->tx_packets, sndc->tx_packets, itv),
2401 out + pos + 1, outsize + pos + 1, restart);
2403 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2405 out + pos + 2, outsize + pos + 2, restart);
2407 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2409 out + pos + 3, outsize + pos + 3, restart);
2411 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2412 S_VALUE(sndp->rx_compressed, sndc->rx_compressed, itv),
2413 out + pos + 4, outsize + pos + 4, restart);
2415 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2416 S_VALUE(sndp->tx_compressed, sndc->tx_compressed, itv),
2417 out + pos + 5, outsize + pos + 5, restart);
2419 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2420 S_VALUE(sndp->multicast, sndc->multicast, itv),
2421 out + pos + 6, outsize + pos + 6, restart);
2423 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
2425 out + pos + 7, outsize + pos + 7, svg_p->dt);
2428 /* Mark interfaces not seen here as now unregistered */
2429 for (k = 0; k < svg_p->nr_max; k++) {
2430 unregistered = outsize + k * 9 + 8;
2431 if (*unregistered != FALSE) {
2432 *unregistered = TRUE;
2437 if (action & F_END) {
2438 for (i = 0; i < svg_p->nr_max; i++) {
2440 * Check if there is something to display.
2441 * Don't test sndc->interface because maybe the network
2442 * interface has been registered later.
2448 /* Recalculate min and max values in kB, not in B */
2449 *(spmin + pos + 2) /= 1024;
2450 *(spmax + pos + 2) /= 1024;
2451 *(spmin + pos + 3) /= 1024;
2452 *(spmax + pos + 3) /= 1024;
2454 item_name = *(out + pos + 8);
2455 draw_activity_graphs(a->g_nr, g_type,
2456 title, g_title, item_name, group,
2457 spmin + pos, spmax + pos, out + pos, outsize + pos,
2461 /* Free remaining structures */
2462 free_graphs(out, outsize, spmin, spmax);
2467 ***************************************************************************
2468 * Display network interface errors statistics in SVG.
2471 * @a Activity structure with statistics.
2472 * @curr Index in array for current sample statistics.
2473 * @action Action expected from current function.
2474 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2475 * flag indicating that a restart record has been previously
2476 * found (.@restart) and time used for the X axis origin
2478 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2479 * @record_hdr Pointer on record header of current stats sample.
2480 ***************************************************************************
2482 __print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2483 unsigned long long itv, struct record_header *record_hdr)
2485 struct stats_net_edev *snedc, *snedp, snedzero;
2486 int group[] = {2, 2, 2, 3};
2487 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2489 char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
2490 "Network errors statistics (3)", "Network errors statistics (4)"};
2491 char *g_title[] = {"rxerr/s", "txerr/s",
2492 "rxdrop/s", "txdrop/s",
2493 "rxfifo/s", "txfifo/s",
2494 "coll/s", "txcarr/s", "rxfram/s"};
2495 int g_fields[] = {6, 0, 1, 2, 3, 4, 5, 8, 7};
2496 static double *spmin, *spmax;
2498 static int *outsize;
2500 int i, j, k, pos, restart, *unregistered;
2502 if (action & F_BEGIN) {
2504 * Allocate arrays (#0..8) that will contain the graphs data
2505 * and the min/max values.
2506 * Also allocate one additional array (#9) for each interface:
2507 * out + 9 will contain the interface name,
2508 * outsize + 9 will contain a positive value (TRUE) if the interface
2509 * has either still not been registered, or has been unregistered.
2511 out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
2514 if (action & F_MAIN) {
2515 memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
2516 restart = svg_p->restart;
2518 * Mark previously registered interfaces as now
2519 * possibly unregistered for all graphs.
2521 for (k = 0; k < svg_p->nr_max; k++) {
2522 unregistered = outsize + k * 10 + 9;
2523 if (*unregistered == FALSE) {
2524 *unregistered = MAYBE;
2528 /* For each network interfaces structure */
2529 for (i = 0; i < a->nr[curr]; i++) {
2530 snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
2531 if (!strcmp(snedc->interface, ""))
2532 /* Empty structure: This is the end of the list */
2535 /* Look for corresponding graph */
2536 for (k = 0; k < svg_p->nr_max; k++) {
2537 item_name = *(out + k * 10 + 9);
2538 if (!strcmp(snedc->interface, item_name))
2542 if (k == svg_p->nr_max) {
2543 /* Graph not found: Look for first free entry */
2544 for (k = 0; k < svg_p->nr_max; k++) {
2545 item_name = *(out + k * 10 + 9);
2546 if (!strcmp(item_name, ""))
2549 if (k == svg_p->nr_max) {
2550 /* No free graph entry: Extend all buffers */
2551 reallocate_all_graph_lines(svg_p->nr_max,
2552 &out, &outsize, &spmin, &spmax);
2558 unregistered = outsize + pos + 9;
2560 j = check_net_edev_reg(a, curr, !curr, i);
2562 /* This is a newly registered interface. Previous stats are zero */
2566 snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
2570 * If current interface was marked as previously unregistered,
2571 * then set restart variable to TRUE so that the graph will be
2572 * discontinuous, and mark it as now registered.
2574 if (*unregistered == TRUE) {
2577 *unregistered = FALSE;
2579 if (!item_name[0]) {
2580 /* Save network interface name (if not already done) */
2581 strncpy(item_name, snedc->interface, CHUNKSIZE);
2582 item_name[CHUNKSIZE - 1] = '\0';
2585 /* Check for min/max values */
2586 save_extrema(a->gtypes_nr, (void *) snedc, (void *) snedp,
2587 itv, spmin + pos, spmax + pos, g_fields);
2590 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2591 S_VALUE(snedp->rx_errors, snedc->rx_errors, itv),
2592 out + pos, outsize + pos, restart);
2594 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2595 S_VALUE(snedp->tx_errors, snedc->tx_errors, itv),
2596 out + pos + 1, outsize + pos + 1, restart);
2598 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2599 S_VALUE(snedp->rx_dropped, snedc->rx_dropped, itv),
2600 out + pos + 2, outsize + pos + 2, restart);
2602 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2603 S_VALUE(snedp->tx_dropped, snedc->tx_dropped, itv),
2604 out + pos + 3, outsize + pos + 3, restart);
2606 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2607 S_VALUE(snedp->rx_fifo_errors, snedc->rx_fifo_errors, itv),
2608 out + pos + 4, outsize + pos + 4, restart);
2610 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2611 S_VALUE(snedp->tx_fifo_errors, snedc->tx_fifo_errors, itv),
2612 out + pos + 5, outsize + pos + 5, restart);
2614 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2615 S_VALUE(snedp->collisions, snedc->collisions, itv),
2616 out + pos + 6, outsize + pos + 6, restart);
2618 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2619 S_VALUE(snedp->tx_carrier_errors, snedc->tx_carrier_errors, itv),
2620 out + pos + 7, outsize + pos + 7, restart);
2622 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2623 S_VALUE(snedp->rx_frame_errors, snedc->rx_frame_errors, itv),
2624 out + pos + 8, outsize + pos + 8, restart);
2627 /* Mark interfaces not seen here as now unregistered */
2628 for (k = 0; k < svg_p->nr_max; k++) {
2629 unregistered = outsize + k * 10 + 9;
2630 if (*unregistered != FALSE) {
2631 *unregistered = TRUE;
2636 if (action & F_END) {
2637 for (i = 0; i < svg_p->nr_max; i++) {
2639 * Check if there is something to display.
2640 * Don't test snedc->interface because maybe the network
2641 * interface has been registered later.
2647 item_name = *(out + pos + 9);
2648 draw_activity_graphs(a->g_nr, g_type,
2649 title, g_title, item_name, group,
2650 spmin + pos, spmax + pos, out + pos, outsize + pos,
2654 /* Free remaining structures */
2655 free_graphs(out, outsize, spmin, spmax);
2660 ***************************************************************************
2661 * Display NFS client statistics in SVG.
2664 * @a Activity structure with statistics.
2665 * @curr Index in array for current sample statistics.
2666 * @action Action expected from current function.
2667 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2668 * flag indicating that a restart record has been previously
2669 * found (.@restart) and time used for the X axis origin
2671 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2672 * @record_hdr Pointer on record header of current stats sample.
2673 ***************************************************************************
2675 __print_funct_t svg_print_net_nfs_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2676 unsigned long long itv, struct record_header *record_hdr)
2678 struct stats_net_nfs
2679 *snnc = (struct stats_net_nfs *) a->buf[curr],
2680 *snnp = (struct stats_net_nfs *) a->buf[!curr];
2681 int group[] = {2, 2, 2};
2682 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2683 char *title[] = {"NFS client statistics (1)", "NFS client statistics (2)",
2684 "NFS client statistics (3)"};
2685 char *g_title[] = {"call/s", "retrans/s",
2686 "read/s", "write/s",
2687 "access/s", "getatt/s"};
2688 int g_fields[] = {0, 1, 2, 3, 4, 5};
2689 static double *spmin, *spmax;
2691 static int *outsize;
2693 if (action & F_BEGIN) {
2695 * Allocate arrays that will contain the graphs data
2696 * and the min/max values.
2698 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2701 if (action & F_MAIN) {
2702 /* Check for min/max values */
2703 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2704 itv, spmin, spmax, g_fields);
2707 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2708 S_VALUE(snnp->nfs_rpccnt, snnc->nfs_rpccnt, itv),
2709 out, outsize, svg_p->restart);
2711 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2712 S_VALUE(snnp->nfs_rpcretrans, snnc->nfs_rpcretrans, itv),
2713 out + 1, outsize + 1, svg_p->restart);
2715 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2716 S_VALUE(snnp->nfs_readcnt, snnc->nfs_readcnt, itv),
2717 out + 2, outsize + 2, svg_p->restart);
2719 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2720 S_VALUE(snnp->nfs_writecnt, snnc->nfs_writecnt, itv),
2721 out + 3, outsize + 3, svg_p->restart);
2723 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2724 S_VALUE(snnp->nfs_accesscnt, snnc->nfs_accesscnt, itv),
2725 out + 4, outsize + 4, svg_p->restart);
2727 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2728 S_VALUE(snnp->nfs_getattcnt, snnc->nfs_getattcnt, itv),
2729 out + 5, outsize + 5, svg_p->restart);
2732 if (action & F_END) {
2733 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2734 spmin, spmax, out, outsize, svg_p, record_hdr);
2736 /* Free remaining structures */
2737 free_graphs(out, outsize, spmin, spmax);
2742 ***************************************************************************
2743 * Display NFS server statistics in SVG.
2746 * @a Activity structure with statistics.
2747 * @curr Index in array for current sample statistics.
2748 * @action Action expected from current function.
2749 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2750 * flag indicating that a restart record has been previously
2751 * found (.@restart) and time used for the X axis origin
2753 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2754 * @record_hdr Pointer on record header of current stats sample.
2755 ***************************************************************************
2757 __print_funct_t svg_print_net_nfsd_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2758 unsigned long long itv, struct record_header *record_hdr)
2760 struct stats_net_nfsd
2761 *snndc = (struct stats_net_nfsd *) a->buf[curr],
2762 *snndp = (struct stats_net_nfsd *) a->buf[!curr];
2763 int group[] = {2, 3, 2, 2, 2};
2764 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
2765 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2766 char *title[] = {"NFS server statistics (1)", "NFS server statistics (2)",
2767 "NFS server statistics (3)", "NFS server statistics (4)",
2768 "NFS server statistics (5)"};
2769 char *g_title[] = {"scall/s", "badcall/s",
2770 "packet/s", "udp/s", "tcp/s",
2772 "sread/s", "swrite/s",
2773 "saccess/s", "sgetatt/s"};
2774 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
2775 static double *spmin, *spmax;
2777 static int *outsize;
2779 if (action & F_BEGIN) {
2781 * Allocate arrays that will contain the graphs data
2782 * and the min/max values.
2784 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
2787 if (action & F_MAIN) {
2788 /* Check for min/max values */
2789 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2790 itv, spmin, spmax, g_fields);
2793 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2794 S_VALUE(snndp->nfsd_rpccnt, snndc->nfsd_rpccnt, itv),
2795 out, outsize, svg_p->restart);
2797 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2798 S_VALUE(snndp->nfsd_rpcbad, snndc->nfsd_rpcbad, itv),
2799 out + 1, outsize + 1, svg_p->restart);
2801 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2802 S_VALUE(snndp->nfsd_netcnt, snndc->nfsd_netcnt, itv),
2803 out + 2, outsize + 2, svg_p->restart);
2805 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2806 S_VALUE(snndp->nfsd_netudpcnt, snndc->nfsd_netudpcnt, itv),
2807 out + 3, outsize + 3, svg_p->restart);
2809 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2810 S_VALUE(snndp->nfsd_nettcpcnt, snndc->nfsd_nettcpcnt, itv),
2811 out + 4, outsize + 4, svg_p->restart);
2813 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2814 S_VALUE(snndp->nfsd_rchits, snndc->nfsd_rchits, itv),
2815 out + 5, outsize + 5, svg_p->restart);
2817 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2818 S_VALUE(snndp->nfsd_rcmisses, snndc->nfsd_rcmisses, itv),
2819 out + 6, outsize + 6, svg_p->restart);
2821 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2822 S_VALUE(snndp->nfsd_readcnt, snndc->nfsd_readcnt, itv),
2823 out + 7, outsize + 7, svg_p->restart);
2825 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2826 S_VALUE(snndp->nfsd_writecnt, snndc->nfsd_writecnt, itv),
2827 out + 8, outsize + 8, svg_p->restart);
2829 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2830 S_VALUE(snndp->nfsd_accesscnt, snndc->nfsd_accesscnt, itv),
2831 out + 9, outsize + 9, svg_p->restart);
2833 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2834 S_VALUE(snndp->nfsd_getattcnt, snndc->nfsd_getattcnt, itv),
2835 out + 10, outsize + 10, svg_p->restart);
2838 if (action & F_END) {
2839 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2840 spmin, spmax, out, outsize, svg_p, record_hdr);
2842 /* Free remaining structures */
2843 free_graphs(out, outsize, spmin, spmax);
2848 ***************************************************************************
2849 * Display network socket statistics in SVG.
2852 * @a Activity structure with statistics.
2853 * @curr Index in array for current sample statistics.
2854 * @action Action expected from current function.
2855 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2856 * flag indicating that a restart record has been previously
2857 * found (.@restart) and time used for the X axis origin
2859 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2860 * @record_hdr Pointer on record header of current stats sample.
2861 ***************************************************************************
2863 __print_funct_t svg_print_net_sock_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2864 unsigned long long itv, struct record_header *record_hdr)
2866 struct stats_net_sock
2867 *snsc = (struct stats_net_sock *) a->buf[curr];
2868 int group[] = {1, 5};
2869 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2870 char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
2871 char *g_title[] = {"~totsck",
2872 "~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
2873 int g_fields[] = {0, 1, 5, 2, 3, 4};
2874 static double *spmin, *spmax;
2876 static int *outsize;
2878 if (action & F_BEGIN) {
2880 * Allocate arrays that will contain the graphs data
2881 * and the min/max values.
2883 out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
2886 if (action & F_MAIN) {
2887 /* Check for min/max values */
2888 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
2889 itv, spmin, spmax, g_fields);
2891 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2892 (unsigned long) snsc->sock_inuse,
2893 out, outsize, svg_p->restart);
2895 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2896 (unsigned long) snsc->tcp_inuse,
2897 out + 1, outsize + 1, svg_p->restart);
2899 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2900 (unsigned long) snsc->udp_inuse,
2901 out + 2, outsize + 2, svg_p->restart);
2903 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2904 (unsigned long) snsc->raw_inuse,
2905 out + 3, outsize + 3, svg_p->restart);
2907 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2908 (unsigned long) snsc->frag_inuse,
2909 out + 4, outsize + 4, svg_p->restart);
2911 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
2912 (unsigned long) snsc->tcp_tw,
2913 out + 5, outsize + 5, svg_p->restart);
2916 if (action & F_END) {
2917 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
2918 spmin, spmax, out, outsize, svg_p, record_hdr);
2920 /* Free remaining structures */
2921 free_graphs(out, outsize, spmin, spmax);
2926 ***************************************************************************
2927 * Display IPv4 network statistics in SVG.
2930 * @a Activity structure with statistics.
2931 * @curr Index in array for current sample statistics.
2932 * @action Action expected from current function.
2933 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
2934 * flag indicating that a restart record has been previously
2935 * found (.@restart) and time used for the X axis origin
2937 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
2938 * @record_hdr Pointer on record header of current stats sample.
2939 ***************************************************************************
2941 __print_funct_t svg_print_net_ip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
2942 unsigned long long itv, struct record_header *record_hdr)
2945 *snic = (struct stats_net_ip *) a->buf[curr],
2946 *snip = (struct stats_net_ip *) a->buf[!curr];
2947 int group[] = {4, 2, 2};
2948 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
2949 char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
2950 char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
2951 "asmrq/s", "asmok/s",
2952 "fragok/s", "fragcrt/s"};
2953 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
2954 static double *spmin, *spmax;
2956 static int *outsize;
2958 if (action & F_BEGIN) {
2960 * Allocate arrays that will contain the graphs data
2961 * and the min/max values.
2963 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
2966 if (action & F_MAIN) {
2967 /* Check for min/max values */
2968 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
2969 itv, spmin, spmax, g_fields);
2972 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2973 S_VALUE(snip->InReceives, snic->InReceives, itv),
2974 out, outsize, svg_p->restart);
2976 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2977 S_VALUE(snip->ForwDatagrams, snic->ForwDatagrams, itv),
2978 out + 1, outsize + 1, svg_p->restart);
2980 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2981 S_VALUE(snip->InDelivers, snic->InDelivers, itv),
2982 out + 2, outsize + 2, svg_p->restart);
2984 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2985 S_VALUE(snip->OutRequests, snic->OutRequests, itv),
2986 out + 3, outsize + 3, svg_p->restart);
2988 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2989 S_VALUE(snip->ReasmReqds, snic->ReasmReqds, itv),
2990 out + 4, outsize + 4, svg_p->restart);
2992 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2993 S_VALUE(snip->ReasmOKs, snic->ReasmOKs, itv),
2994 out + 5, outsize + 5, svg_p->restart);
2996 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
2997 S_VALUE(snip->FragOKs, snic->FragOKs, itv),
2998 out + 6, outsize + 6, svg_p->restart);
3000 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3001 S_VALUE(snip->FragCreates, snic->FragCreates, itv),
3002 out + 7, outsize + 7, svg_p->restart);
3005 if (action & F_END) {
3006 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3007 spmin, spmax, out, outsize, svg_p, record_hdr);
3009 /* Free remaining structures */
3010 free_graphs(out, outsize, spmin, spmax);
3015 ***************************************************************************
3016 * Display IPv4 network errors statistics in SVG.
3019 * @a Activity structure with statistics.
3020 * @curr Index in array for current sample statistics.
3021 * @action Action expected from current function.
3022 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3023 * flag indicating that a restart record has been previously
3024 * found (.@restart) and time used for the X axis origin
3026 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3027 * @record_hdr Pointer on record header of current stats sample.
3028 ***************************************************************************
3030 __print_funct_t svg_print_net_eip_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3031 unsigned long long itv, struct record_header *record_hdr)
3033 struct stats_net_eip
3034 *sneic = (struct stats_net_eip *) a->buf[curr],
3035 *sneip = (struct stats_net_eip *) a->buf[!curr];
3036 int group[] = {3, 2, 3};
3037 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3038 char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
3039 "IPv4 network errors statistics (3)"};
3040 char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
3041 "idisc/s", "odisc/s",
3042 "onort/s", "asmf/s", "fragf/s"};
3043 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7};
3044 static double *spmin, *spmax;
3046 static int *outsize;
3048 if (action & F_BEGIN) {
3050 * Allocate arrays that will contain the graphs data
3051 * and the min/max values.
3053 out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
3056 if (action & F_MAIN) {
3057 /* Check for min/max values */
3058 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3059 itv, spmin, spmax, g_fields);
3062 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3063 S_VALUE(sneip->InHdrErrors, sneic->InHdrErrors, itv),
3064 out, outsize, svg_p->restart);
3066 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3067 S_VALUE(sneip->InAddrErrors, sneic->InAddrErrors, itv),
3068 out + 1, outsize + 1, svg_p->restart);
3070 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3071 S_VALUE(sneip->InUnknownProtos, sneic->InUnknownProtos, itv),
3072 out + 2, outsize + 2, svg_p->restart);
3074 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3075 S_VALUE(sneip->InDiscards, sneic->InDiscards, itv),
3076 out + 3, outsize + 3, svg_p->restart);
3078 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3079 S_VALUE(sneip->OutDiscards, sneic->OutDiscards, itv),
3080 out + 4, outsize + 4, svg_p->restart);
3082 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3083 S_VALUE(sneip->OutNoRoutes, sneic->OutNoRoutes, itv),
3084 out + 5, outsize + 5, svg_p->restart);
3086 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3087 S_VALUE(sneip->ReasmFails, sneic->ReasmFails, itv),
3088 out + 6, outsize + 6, svg_p->restart);
3090 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3091 S_VALUE(sneip->FragFails, sneic->FragFails, itv),
3092 out + 7, outsize + 7, svg_p->restart);
3095 if (action & F_END) {
3096 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3097 spmin, spmax, out, outsize, svg_p, record_hdr);
3099 /* Free remaining structures */
3100 free_graphs(out, outsize, spmin, spmax);
3105 ***************************************************************************
3106 * Display ICMPv4 network statistics in SVG.
3109 * @a Activity structure with statistics.
3110 * @curr Index in array for current sample statistics.
3111 * @action Action expected from current function.
3112 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3113 * flag indicating that a restart record has been previously
3114 * found (.@restart) and time used for the X axis origin
3116 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3117 * @record_hdr Pointer on record header of current stats sample.
3118 ***************************************************************************
3120 __print_funct_t svg_print_net_icmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3121 unsigned long long itv, struct record_header *record_hdr)
3123 struct stats_net_icmp
3124 *snic = (struct stats_net_icmp *) a->buf[curr],
3125 *snip = (struct stats_net_icmp *) a->buf[!curr];
3126 int group[] = {2, 4, 4, 4};
3127 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3129 char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
3130 "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
3131 char *g_title[] = {"imsg/s", "omsg/s",
3132 "iech/s", "iechr/s", "oech/s", "oechr/s",
3133 "itm/s", "itmr/s", "otm/s", "otmr/s",
3134 "iadrmk/s", "iadrmkr/s", "oadrmk/s", "oadrmkr/s"};
3135 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
3136 static double *spmin, *spmax;
3138 static int *outsize;
3140 if (action & F_BEGIN) {
3142 * Allocate arrays that will contain the graphs data
3143 * and the min/max values.
3145 out = allocate_graph_lines(14, &outsize, &spmin, &spmax);
3148 if (action & F_MAIN) {
3149 /* Check for min/max values */
3150 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3151 itv, spmin, spmax, g_fields);
3154 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3155 S_VALUE(snip->InMsgs, snic->InMsgs, itv),
3156 out, outsize, svg_p->restart);
3158 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3159 S_VALUE(snip->OutMsgs, snic->OutMsgs, itv),
3160 out + 1, outsize + 1, svg_p->restart);
3162 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3163 S_VALUE(snip->InEchos, snic->InEchos, itv),
3164 out + 2, outsize + 2, svg_p->restart);
3166 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3167 S_VALUE(snip->InEchoReps, snic->InEchoReps, itv),
3168 out + 3, outsize + 3, svg_p->restart);
3170 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3171 S_VALUE(snip->OutEchos, snic->OutEchos, itv),
3172 out + 4, outsize + 4, svg_p->restart);
3174 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3175 S_VALUE(snip->OutEchoReps, snic->OutEchoReps, itv),
3176 out + 5, outsize + 5, svg_p->restart);
3178 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3179 S_VALUE(snip->InTimestamps, snic->InTimestamps, itv),
3180 out + 6, outsize + 6, svg_p->restart);
3182 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3183 S_VALUE(snip->InTimestampReps, snic->InTimestampReps, itv),
3184 out + 7, outsize + 7, svg_p->restart);
3186 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3187 S_VALUE(snip->OutTimestamps, snic->OutTimestamps, itv),
3188 out + 8, outsize + 8, svg_p->restart);
3190 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3191 S_VALUE(snip->OutTimestampReps, snic->OutTimestampReps, itv),
3192 out + 9, outsize + 9, svg_p->restart);
3194 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3195 S_VALUE(snip->InAddrMasks, snic->InAddrMasks, itv),
3196 out + 10, outsize + 10, svg_p->restart);
3198 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3199 S_VALUE(snip->InAddrMaskReps, snic->InAddrMaskReps, itv),
3200 out + 11, outsize + 11, svg_p->restart);
3202 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3203 S_VALUE(snip->OutAddrMasks, snic->OutAddrMasks, itv),
3204 out + 12, outsize + 12, svg_p->restart);
3206 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3207 S_VALUE(snip->OutAddrMaskReps, snic->OutAddrMaskReps, itv),
3208 out + 13, outsize + 13, svg_p->restart);
3211 if (action & F_END) {
3212 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3213 spmin, spmax, out, outsize, svg_p, record_hdr);
3215 /* Free remaining structures */
3216 free_graphs(out, outsize, spmin, spmax);
3221 ***************************************************************************
3222 * Display ICMPv4 network errors statistics in SVG.
3225 * @a Activity structure with statistics.
3226 * @curr Index in array for current sample statistics.
3227 * @action Action expected from current function.
3228 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3229 * flag indicating that a restart record has been previously
3230 * found (.@restart) and time used for the X axis origin
3232 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3233 * @record_hdr Pointer on record header of current stats sample.
3234 ***************************************************************************
3236 __print_funct_t svg_print_net_eicmp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3237 unsigned long long itv, struct record_header *record_hdr)
3239 struct stats_net_eicmp
3240 *sneic = (struct stats_net_eicmp *) a->buf[curr],
3241 *sneip = (struct stats_net_eicmp *) a->buf[!curr];
3242 int group[] = {2, 2, 2, 2, 2, 2};
3243 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3244 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3245 char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
3246 "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
3247 "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
3248 char *g_title[] = {"ierr/s", "oerr/s",
3249 "idstunr/s", "odstunr/s",
3250 "itmex/s", "otmex/s",
3251 "iparmpb/s", "oparmpb/s",
3252 "isrcq/s", "osrcq/s",
3253 "iredir/s", "oredir/s"};
3254 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
3255 static double *spmin, *spmax;
3257 static int *outsize;
3259 if (action & F_BEGIN) {
3261 * Allocate arrays that will contain the graphs data
3262 * and the min/max values.
3264 out = allocate_graph_lines(12, &outsize, &spmin, &spmax);
3267 if (action & F_MAIN) {
3268 /* Check for min/max values */
3269 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3270 itv, spmin, spmax, g_fields);
3273 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3274 S_VALUE(sneip->InErrors, sneic->InErrors, itv),
3275 out, outsize, svg_p->restart);
3277 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3278 S_VALUE(sneip->OutErrors, sneic->OutErrors, itv),
3279 out + 1, outsize + 1, svg_p->restart);
3281 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3282 S_VALUE(sneip->InDestUnreachs, sneic->InDestUnreachs, itv),
3283 out + 2, outsize + 2, svg_p->restart);
3285 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3286 S_VALUE(sneip->OutDestUnreachs, sneic->OutDestUnreachs, itv),
3287 out + 3, outsize + 3, svg_p->restart);
3289 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3290 S_VALUE(sneip->InTimeExcds, sneic->InTimeExcds, itv),
3291 out + 4, outsize + 4, svg_p->restart);
3293 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3294 S_VALUE(sneip->OutTimeExcds, sneic->OutTimeExcds, itv),
3295 out + 5, outsize + 5, svg_p->restart);
3297 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3298 S_VALUE(sneip->InParmProbs, sneic->InParmProbs, itv),
3299 out + 6, outsize + 6, svg_p->restart);
3301 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3302 S_VALUE(sneip->OutParmProbs, sneic->OutParmProbs, itv),
3303 out + 7, outsize + 7, svg_p->restart);
3305 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3306 S_VALUE(sneip->InSrcQuenchs, sneic->InSrcQuenchs, itv),
3307 out + 8, outsize + 8, svg_p->restart);
3309 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3310 S_VALUE(sneip->OutSrcQuenchs, sneic->OutSrcQuenchs, itv),
3311 out + 9, outsize + 9, svg_p->restart);
3313 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3314 S_VALUE(sneip->InRedirects, sneic->InRedirects, itv),
3315 out + 10, outsize + 10, svg_p->restart);
3317 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3318 S_VALUE(sneip->OutRedirects, sneic->OutRedirects, itv),
3319 out + 11, outsize + 11, svg_p->restart);
3322 if (action & F_END) {
3323 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3324 spmin, spmax, out, outsize, svg_p, record_hdr);
3326 /* Free remaining structures */
3327 free_graphs(out, outsize, spmin, spmax);
3332 ***************************************************************************
3333 * Display TCPv4 network statistics in SVG.
3336 * @a Activity structure with statistics.
3337 * @curr Index in array for current sample statistics.
3338 * @action Action expected from current function.
3339 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3340 * flag indicating that a restart record has been previously
3341 * found (.@restart) and time used for the X axis origin
3343 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3344 * @record_hdr Pointer on record header of current stats sample.
3345 ***************************************************************************
3347 __print_funct_t svg_print_net_tcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3348 unsigned long long itv, struct record_header *record_hdr)
3350 struct stats_net_tcp
3351 *sntc = (struct stats_net_tcp *) a->buf[curr],
3352 *sntp = (struct stats_net_tcp *) a->buf[!curr];
3353 int group[] = {2, 2};
3354 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3355 char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
3356 char *g_title[] = {"active/s", "passive/s",
3357 "iseg/s", "oseg/s"};
3358 int g_fields[] = {0, 1, 2, 3};
3359 static double *spmin, *spmax;
3361 static int *outsize;
3363 if (action & F_BEGIN) {
3365 * Allocate arrays that will contain the graphs data
3366 * and the min/max values.
3368 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3371 if (action & F_MAIN) {
3372 /* Check for min/max values */
3373 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3374 itv, spmin, spmax, g_fields);
3377 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3378 S_VALUE(sntp->ActiveOpens, sntc->ActiveOpens, itv),
3379 out, outsize, svg_p->restart);
3381 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3382 S_VALUE(sntp->PassiveOpens, sntc->PassiveOpens, itv),
3383 out + 1, outsize + 1, svg_p->restart);
3385 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3386 S_VALUE(sntp->InSegs, sntc->InSegs, itv),
3387 out + 2, outsize + 2, svg_p->restart);
3389 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3390 S_VALUE(sntp->OutSegs, sntc->OutSegs, itv),
3391 out + 3, outsize + 3, svg_p->restart);
3394 if (action & F_END) {
3395 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3396 spmin, spmax, out, outsize, svg_p, record_hdr);
3398 /* Free remaining structures */
3399 free_graphs(out, outsize, spmin, spmax);
3404 ***************************************************************************
3405 * Display TCPv4 network errors statistics in SVG.
3408 * @a Activity structure with statistics.
3409 * @curr Index in array for current sample statistics.
3410 * @action Action expected from current function.
3411 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3412 * flag indicating that a restart record has been previously
3413 * found (.@restart) and time used for the X axis origin
3415 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3416 * @record_hdr Pointer on record header of current stats sample.
3417 ***************************************************************************
3419 __print_funct_t svg_print_net_etcp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3420 unsigned long long itv, struct record_header *record_hdr)
3422 struct stats_net_etcp
3423 *snetc = (struct stats_net_etcp *) a->buf[curr],
3424 *snetp = (struct stats_net_etcp *) a->buf[!curr];
3425 int group[] = {2, 3};
3426 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3427 char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
3428 char *g_title[] = {"atmptf/s", "estres/s",
3429 "retrans/s", "isegerr/s", "orsts/s"};
3430 int g_fields[] = {0, 1, 2, 3, 4};
3431 static double *spmin, *spmax;
3433 static int *outsize;
3435 if (action & F_BEGIN) {
3437 * Allocate arrays that will contain the graphs data
3438 * and the min/max values.
3440 out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
3443 if (action & F_MAIN) {
3444 /* Check for min/max values */
3445 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3446 itv, spmin, spmax, g_fields);
3449 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3450 S_VALUE(snetp->AttemptFails, snetc->AttemptFails, itv),
3451 out, outsize, svg_p->restart);
3453 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3454 S_VALUE(snetp->EstabResets, snetc->EstabResets, itv),
3455 out + 1, outsize + 1, svg_p->restart);
3457 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3458 S_VALUE(snetp->RetransSegs, snetc->RetransSegs, itv),
3459 out + 2, outsize + 2, svg_p->restart);
3461 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3462 S_VALUE(snetp->InErrs, snetc->InErrs, itv),
3463 out + 3, outsize + 3, svg_p->restart);
3465 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3466 S_VALUE(snetp->OutRsts, snetc->OutRsts, itv),
3467 out + 4, outsize + 4, svg_p->restart);
3470 if (action & F_END) {
3471 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3472 spmin, spmax, out, outsize, svg_p, record_hdr);
3474 /* Free remaining structures */
3475 free_graphs(out, outsize, spmin, spmax);
3480 ***************************************************************************
3481 * Display UDPv4 network statistics in SVG.
3484 * @a Activity structure with statistics.
3485 * @curr Index in array for current sample statistics.
3486 * @action Action expected from current function.
3487 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3488 * flag indicating that a restart record has been previously
3489 * found (.@restart) and time used for the X axis origin
3491 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3492 * @record_hdr Pointer on record header of current stats sample.
3493 ***************************************************************************
3495 __print_funct_t svg_print_net_udp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3496 unsigned long long itv, struct record_header *record_hdr)
3498 struct stats_net_udp
3499 *snuc = (struct stats_net_udp *) a->buf[curr],
3500 *snup = (struct stats_net_udp *) a->buf[!curr];
3501 int group[] = {2, 2};
3502 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3503 char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
3504 char *g_title[] = {"idgm/s", "odgm/s",
3505 "noport/s", "idgmerr/s"};
3506 int g_fields[] = {0, 1, 2, 3};
3507 static double *spmin, *spmax;
3509 static int *outsize;
3511 if (action & F_BEGIN) {
3513 * Allocate arrays that will contain the graphs data
3514 * and the min/max values.
3516 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3519 if (action & F_MAIN) {
3520 /* Check for min/max values */
3521 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3522 itv, spmin, spmax, g_fields);
3525 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3526 S_VALUE(snup->InDatagrams, snuc->InDatagrams, itv),
3527 out, outsize, svg_p->restart);
3529 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3530 S_VALUE(snup->OutDatagrams, snuc->OutDatagrams, itv),
3531 out + 1, outsize + 1, svg_p->restart);
3533 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3534 S_VALUE(snup->NoPorts, snuc->NoPorts, itv),
3535 out + 2, outsize + 2, svg_p->restart);
3537 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3538 S_VALUE(snup->InErrors, snuc->InErrors, itv),
3539 out + 3, outsize + 3, svg_p->restart);
3542 if (action & F_END) {
3543 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3544 spmin, spmax, out, outsize, svg_p, record_hdr);
3546 /* Free remaining structures */
3547 free_graphs(out, outsize, spmin, spmax);
3552 ***************************************************************************
3553 * Display IPV6 network socket statistics in SVG.
3556 * @a Activity structure with statistics.
3557 * @curr Index in array for current sample statistics.
3558 * @action Action expected from current function.
3559 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3560 * flag indicating that a restart record has been previously
3561 * found (.@restart) and time used for the X axis origin
3563 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3564 * @record_hdr Pointer on record header of current stats sample.
3565 ***************************************************************************
3567 __print_funct_t svg_print_net_sock6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3568 unsigned long long itv, struct record_header *record_hdr)
3570 struct stats_net_sock6
3571 *snsc = (struct stats_net_sock6 *) a->buf[curr];
3573 int g_type[] = {SVG_LINE_GRAPH};
3574 char *title[] = {"IPv6 network sockets"};
3575 char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
3576 int g_fields[] = {0, 1, 2, 3};
3577 static double *spmin, *spmax;
3579 static int *outsize;
3581 if (action & F_BEGIN) {
3583 * Allocate arrays that will contain the graphs data
3584 * and the min/max values.
3586 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
3589 if (action & F_MAIN) {
3590 /* Check for min/max values */
3591 save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
3592 itv, spmin, spmax, g_fields);
3594 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3595 (unsigned long) snsc->tcp6_inuse,
3596 out, outsize, svg_p->restart);
3598 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3599 (unsigned long) snsc->udp6_inuse,
3600 out + 1, outsize + 1, svg_p->restart);
3602 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3603 (unsigned long) snsc->raw6_inuse,
3604 out + 2, outsize + 2, svg_p->restart);
3606 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
3607 (unsigned long) snsc->frag6_inuse,
3608 out + 3, outsize + 3, svg_p->restart);
3611 if (action & F_END) {
3612 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3613 spmin, spmax, out, outsize, svg_p, record_hdr);
3615 /* Free remaining structures */
3616 free_graphs(out, outsize, spmin, spmax);
3621 ***************************************************************************
3622 * Display IPv6 network statistics in SVG.
3625 * @a Activity structure with statistics.
3626 * @curr Index in array for current sample statistics.
3627 * @action Action expected from current function.
3628 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3629 * flag indicating that a restart record has been previously
3630 * found (.@restart) and time used for the X axis origin
3632 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3633 * @record_hdr Pointer on record header of current stats sample.
3634 ***************************************************************************
3636 __print_funct_t svg_print_net_ip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3637 unsigned long long itv, struct record_header *record_hdr)
3639 struct stats_net_ip6
3640 *snic = (struct stats_net_ip6 *) a->buf[curr],
3641 *snip = (struct stats_net_ip6 *) a->buf[!curr];
3642 int group[] = {4, 2, 2, 2};
3643 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3645 char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
3646 "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
3647 char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
3648 "asmrq6/s", "asmok6/s",
3649 "imcpck6/s", "omcpck6/s",
3650 "fragok6/s", "fragcr6/s"};
3651 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
3652 static double *spmin, *spmax;
3654 static int *outsize;
3656 if (action & F_BEGIN) {
3658 * Allocate arrays that will contain the graphs data
3659 * and the min/max values.
3661 out = allocate_graph_lines(10, &outsize, &spmin, &spmax);
3664 if (action & F_MAIN) {
3665 /* Check for min/max values */
3666 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3667 itv, spmin, spmax, g_fields);
3670 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3671 S_VALUE(snip->InReceives6, snic->InReceives6, itv),
3672 out, outsize, svg_p->restart);
3674 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3675 S_VALUE(snip->OutForwDatagrams6, snic->OutForwDatagrams6, itv),
3676 out + 1, outsize + 1, svg_p->restart);
3678 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3679 S_VALUE(snip->InDelivers6, snic->InDelivers6, itv),
3680 out + 2, outsize + 2, svg_p->restart);
3682 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3683 S_VALUE(snip->OutRequests6, snic->OutRequests6, itv),
3684 out + 3, outsize + 3, svg_p->restart);
3686 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3687 S_VALUE(snip->ReasmReqds6, snic->ReasmReqds6, itv),
3688 out + 4, outsize + 4, svg_p->restart);
3690 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3691 S_VALUE(snip->ReasmOKs6, snic->ReasmOKs6, itv),
3692 out + 5, outsize + 5, svg_p->restart);
3694 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3695 S_VALUE(snip->InMcastPkts6, snic->InMcastPkts6, itv),
3696 out + 6, outsize + 6, svg_p->restart);
3698 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3699 S_VALUE(snip->OutMcastPkts6, snic->OutMcastPkts6, itv),
3700 out + 7, outsize + 7, svg_p->restart);
3702 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3703 S_VALUE(snip->FragOKs6, snic->FragOKs6, itv),
3704 out + 8, outsize + 8, svg_p->restart);
3706 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3707 S_VALUE(snip->FragCreates6, snic->FragCreates6, itv),
3708 out + 9, outsize + 9, svg_p->restart);
3711 if (action & F_END) {
3712 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3713 spmin, spmax, out, outsize, svg_p, record_hdr);
3715 /* Free remaining structures */
3716 free_graphs(out, outsize, spmin, spmax);
3721 ***************************************************************************
3722 * Display IPv6 network errors statistics in SVG.
3725 * @a Activity structure with statistics.
3726 * @curr Index in array for current sample statistics.
3727 * @action Action expected from current function.
3728 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3729 * flag indicating that a restart record has been previously
3730 * found (.@restart) and time used for the X axis origin
3732 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3733 * @record_hdr Pointer on record header of current stats sample.
3734 ***************************************************************************
3736 __print_funct_t svg_print_net_eip6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3737 unsigned long long itv, struct record_header *record_hdr)
3739 struct stats_net_eip6
3740 *sneic = (struct stats_net_eip6 *) a->buf[curr],
3741 *sneip = (struct stats_net_eip6 *) a->buf[!curr];
3742 int group[] = {4, 2, 2, 3};
3743 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3745 char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
3746 "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
3747 "IPv6 network errors statistics (5)"};
3748 char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
3749 "idisc6/s", "odisc6/s",
3750 "inort6/s", "onort6/s",
3751 "asmf6/s", "fragf6/s", "itrpck6/s"};
3752 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3753 static double *spmin, *spmax;
3755 static int *outsize;
3757 if (action & F_BEGIN) {
3759 * Allocate arrays that will contain the graphs data
3760 * and the min/max values.
3762 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
3765 if (action & F_MAIN) {
3766 /* Check for min/max values */
3767 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3768 itv, spmin, spmax, g_fields);
3771 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3772 S_VALUE(sneip->InHdrErrors6, sneic->InHdrErrors6, itv),
3773 out, outsize, svg_p->restart);
3775 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3776 S_VALUE(sneip->InAddrErrors6, sneic->InAddrErrors6, itv),
3777 out + 1, outsize + 1, svg_p->restart);
3779 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3780 S_VALUE(sneip->InUnknownProtos6, sneic->InUnknownProtos6, itv),
3781 out + 2, outsize + 2, svg_p->restart);
3783 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3784 S_VALUE(sneip->InTooBigErrors6, sneic->InTooBigErrors6, itv),
3785 out + 3, outsize + 3, svg_p->restart);
3787 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3788 S_VALUE(sneip->InDiscards6, sneic->InDiscards6, itv),
3789 out + 4, outsize + 4, svg_p->restart);
3791 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3792 S_VALUE(sneip->OutDiscards6, sneic->OutDiscards6, itv),
3793 out + 5, outsize + 5, svg_p->restart);
3795 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3796 S_VALUE(sneip->InNoRoutes6, sneic->InNoRoutes6, itv),
3797 out + 6, outsize + 6, svg_p->restart);
3799 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3800 S_VALUE(sneip->OutNoRoutes6, sneic->OutNoRoutes6, itv),
3801 out + 7, outsize + 7, svg_p->restart);
3803 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3804 S_VALUE(sneip->ReasmFails6, sneic->ReasmFails6, itv),
3805 out + 8, outsize + 8, svg_p->restart);
3807 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3808 S_VALUE(sneip->FragFails6, sneic->FragFails6, itv),
3809 out + 9, outsize + 9, svg_p->restart);
3811 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3812 S_VALUE(sneip->InTruncatedPkts6, sneic->InTruncatedPkts6, itv),
3813 out + 10, outsize + 10, svg_p->restart);
3816 if (action & F_END) {
3817 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3818 spmin, spmax, out, outsize, svg_p, record_hdr);
3820 /* Free remaining structures */
3821 free_graphs(out, outsize, spmin, spmax);
3826 ***************************************************************************
3827 * Display ICMPv6 network statistics in SVG.
3830 * @a Activity structure with statistics.
3831 * @curr Index in array for current sample statistics.
3832 * @action Action expected from current function.
3833 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3834 * flag indicating that a restart record has been previously
3835 * found (.@restart) and time used for the X axis origin
3837 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3838 * @record_hdr Pointer on record header of current stats sample.
3839 ***************************************************************************
3841 __print_funct_t svg_print_net_icmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3842 unsigned long long itv, struct record_header *record_hdr)
3844 struct stats_net_icmp6
3845 *snic = (struct stats_net_icmp6 *) a->buf[curr],
3846 *snip = (struct stats_net_icmp6 *) a->buf[!curr];
3847 int group[] = {2, 3, 5, 3, 4};
3848 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3849 SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3850 char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
3851 "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
3852 "ICMPv6 network statistics (5)"};
3853 char *g_title[] = {"imsg6/s", "omsg6/s",
3854 "iech6/s", "iechr6/s", "oechr6/s",
3855 "igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
3856 "irtsol6/s", "ortsol6/s", "irtad6/s",
3857 "inbsol6/s", "onbsol6/s", "inbad6/s", "onbad6/s"};
3858 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3859 static double *spmin, *spmax;
3861 static int *outsize;
3863 if (action & F_BEGIN) {
3865 * Allocate arrays that will contain the graphs data
3866 * and the min/max values.
3868 out = allocate_graph_lines(17, &outsize, &spmin, &spmax);
3871 if (action & F_MAIN) {
3872 /* Check for min/max values */
3873 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
3874 itv, spmin, spmax, g_fields);
3877 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3878 S_VALUE(snip->InMsgs6, snic->InMsgs6, itv),
3879 out, outsize, svg_p->restart);
3881 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3882 S_VALUE(snip->OutMsgs6, snic->OutMsgs6, itv),
3883 out + 1, outsize + 1, svg_p->restart);
3885 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3886 S_VALUE(snip->InEchos6, snic->InEchos6, itv),
3887 out + 2, outsize + 2, svg_p->restart);
3889 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3890 S_VALUE(snip->InEchoReplies6, snic->InEchoReplies6, itv),
3891 out + 3, outsize + 3, svg_p->restart);
3893 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3894 S_VALUE(snip->OutEchoReplies6, snic->OutEchoReplies6, itv),
3895 out + 4, outsize + 4, svg_p->restart);
3897 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3898 S_VALUE(snip->InGroupMembQueries6, snic->InGroupMembQueries6, itv),
3899 out + 5, outsize + 5, svg_p->restart);
3901 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3902 S_VALUE(snip->InGroupMembResponses6, snic->InGroupMembResponses6, itv),
3903 out + 6, outsize + 6, svg_p->restart);
3905 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3906 S_VALUE(snip->OutGroupMembResponses6, snic->OutGroupMembResponses6, itv),
3907 out + 7, outsize + 7, svg_p->restart);
3909 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3910 S_VALUE(snip->InGroupMembReductions6, snic->InGroupMembReductions6, itv),
3911 out + 8, outsize + 8, svg_p->restart);
3913 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3914 S_VALUE(snip->OutGroupMembReductions6, snic->OutGroupMembReductions6, itv),
3915 out + 9, outsize + 9, svg_p->restart);
3917 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3918 S_VALUE(snip->InRouterSolicits6, snic->InRouterSolicits6, itv),
3919 out + 10, outsize + 10, svg_p->restart);
3921 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3922 S_VALUE(snip->OutRouterSolicits6, snic->OutRouterSolicits6, itv),
3923 out + 11, outsize + 11, svg_p->restart);
3925 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3926 S_VALUE(snip->InRouterAdvertisements6, snic->InRouterAdvertisements6, itv),
3927 out + 12, outsize + 12, svg_p->restart);
3929 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3930 S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
3931 out + 13, outsize + 13, svg_p->restart);
3933 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3934 S_VALUE(snip->OutNeighborSolicits6, snic->OutNeighborSolicits6, itv),
3935 out + 14, outsize + 14, svg_p->restart);
3937 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3938 S_VALUE(snip->InNeighborAdvertisements6, snic->InNeighborAdvertisements6, itv),
3939 out + 15, outsize + 15, svg_p->restart);
3941 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
3942 S_VALUE(snip->OutNeighborAdvertisements6, snic->OutNeighborAdvertisements6, itv),
3943 out + 16, outsize + 16, svg_p->restart);
3946 if (action & F_END) {
3947 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
3948 spmin, spmax, out, outsize, svg_p, record_hdr);
3950 /* Free remaining structures */
3951 free_graphs(out, outsize, spmin, spmax);
3956 ***************************************************************************
3957 * Display ICMPv6 network errors statistics in SVG.
3960 * @a Activity structure with statistics.
3961 * @curr Index in array for current sample statistics.
3962 * @action Action expected from current function.
3963 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
3964 * flag indicating that a restart record has been previously
3965 * found (.@restart) and time used for the X axis origin
3967 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
3968 * @record_hdr Pointer on record header of current stats sample.
3969 ***************************************************************************
3971 __print_funct_t svg_print_net_eicmp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
3972 unsigned long long itv, struct record_header *record_hdr)
3974 struct stats_net_eicmp6
3975 *sneic = (struct stats_net_eicmp6 *) a->buf[curr],
3976 *sneip = (struct stats_net_eicmp6 *) a->buf[!curr];
3977 int group[] = {1, 2, 2, 2, 2, 2};
3978 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
3979 SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
3980 char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
3981 "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
3982 "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
3983 char *g_title[] = {"ierr6/s",
3984 "idtunr6/s", "odtunr6/s",
3985 "itmex6/s", "otmex6/s",
3986 "iprmpb6/s", "oprmpb6/s",
3987 "iredir6/s", "oredir6/s",
3988 "ipck2b6/s", "opck2b6/s"};
3989 int g_fields[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
3990 static double *spmin, *spmax;
3992 static int *outsize;
3994 if (action & F_BEGIN) {
3996 * Allocate arrays that will contain the graphs data
3997 * and the min/max values.
3999 out = allocate_graph_lines(11, &outsize, &spmin, &spmax);
4002 if (action & F_MAIN) {
4003 /* Check for min/max values */
4004 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4005 itv, spmin, spmax, g_fields);
4008 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4009 S_VALUE(sneip->InErrors6, sneic->InErrors6, itv),
4010 out, outsize, svg_p->restart);
4012 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4013 S_VALUE(sneip->InDestUnreachs6, sneic->InDestUnreachs6, itv),
4014 out + 1, outsize + 1, svg_p->restart);
4016 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4017 S_VALUE(sneip->OutDestUnreachs6, sneic->OutDestUnreachs6, itv),
4018 out + 2, outsize + 2, svg_p->restart);
4020 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4021 S_VALUE(sneip->InTimeExcds6, sneic->InTimeExcds6, itv),
4022 out + 3, outsize + 3, svg_p->restart);
4024 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4025 S_VALUE(sneip->OutTimeExcds6, sneic->OutTimeExcds6, itv),
4026 out + 4, outsize + 4, svg_p->restart);
4028 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4029 S_VALUE(sneip->InParmProblems6, sneic->InParmProblems6, itv),
4030 out + 5, outsize + 5, svg_p->restart);
4032 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4033 S_VALUE(sneip->OutParmProblems6, sneic->OutParmProblems6, itv),
4034 out + 6, outsize + 6, svg_p->restart);
4036 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4037 S_VALUE(sneip->InRedirects6, sneic->InRedirects6, itv),
4038 out + 7, outsize + 7, svg_p->restart);
4040 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4041 S_VALUE(sneip->OutRedirects6, sneic->OutRedirects6, itv),
4042 out + 8, outsize + 8, svg_p->restart);
4044 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4045 S_VALUE(sneip->InPktTooBigs6, sneic->InPktTooBigs6, itv),
4046 out + 9, outsize + 9, svg_p->restart);
4048 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4049 S_VALUE(sneip->OutPktTooBigs6, sneic->OutPktTooBigs6, itv),
4050 out + 10, outsize + 10, svg_p->restart);
4053 if (action & F_END) {
4054 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4055 spmin, spmax, out, outsize, svg_p, record_hdr);
4057 /* Free remaining structures */
4058 free_graphs(out, outsize, spmin, spmax);
4063 ***************************************************************************
4064 * Display UDPv6 network statistics in SVG.
4067 * @a Activity structure with statistics.
4068 * @curr Index in array for current sample statistics.
4069 * @action Action expected from current function.
4070 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4071 * flag indicating that a restart record has been previously
4072 * found (.@restart) and time used for the X axis origin
4074 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4075 * @record_hdr Pointer on record header of current stats sample.
4076 ***************************************************************************
4078 __print_funct_t svg_print_net_udp6_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4079 unsigned long long itv, struct record_header *record_hdr)
4081 struct stats_net_udp6
4082 *snuc = (struct stats_net_udp6 *) a->buf[curr],
4083 *snup = (struct stats_net_udp6 *) a->buf[!curr];
4084 int group[] = {2, 2};
4085 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4086 char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
4087 char *g_title[] = {"idgm6/s", "odgm6/s",
4088 "noport6/s", "idgmer6/s"};
4089 int g_fields[] = {0, 1, 2, 3};
4090 static double *spmin, *spmax;
4092 static int *outsize;
4094 if (action & F_BEGIN) {
4096 * Allocate arrays that will contain the graphs data
4097 * and the min/max values.
4099 out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
4102 if (action & F_MAIN) {
4103 /* Check for min/max values */
4104 save_extrema(a->gtypes_nr, (void *) a->buf[curr], (void *) a->buf[!curr],
4105 itv, spmin, spmax, g_fields);
4108 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4109 S_VALUE(snup->InDatagrams6, snuc->InDatagrams6, itv),
4110 out, outsize, svg_p->restart);
4112 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4113 S_VALUE(snup->OutDatagrams6, snuc->OutDatagrams6, itv),
4114 out + 1, outsize + 1, svg_p->restart);
4116 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4117 S_VALUE(snup->NoPorts6, snuc->NoPorts6, itv),
4118 out + 2, outsize + 2, svg_p->restart);
4120 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4121 S_VALUE(snup->InErrors6, snuc->InErrors6, itv),
4122 out + 3, outsize + 3, svg_p->restart);
4125 if (action & F_END) {
4126 draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
4127 spmin, spmax, out, outsize, svg_p, record_hdr);
4129 /* Free remaining structures */
4130 free_graphs(out, outsize, spmin, spmax);
4135 ***************************************************************************
4136 * Display CPU frequency statistics in SVG.
4139 * @a Activity structure with statistics.
4140 * @curr Index in array for current sample statistics.
4141 * @action Action expected from current function.
4142 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4143 * flag indicating that a restart record has been previously
4144 * found (.@restart) and time used for the X axis origin
4146 * @itv Interval of time in 1/100th of a second (unused here).
4147 * @record_hdr Pointer on record header of current stats sample.
4148 ***************************************************************************
4150 __print_funct_t svg_print_pwr_cpufreq_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4151 unsigned long long itv, struct record_header *record_hdr)
4153 struct stats_pwr_cpufreq *spc, *spp;
4155 int g_type[] = {SVG_LINE_GRAPH};
4156 char *title[] = {"CPU frequency"};
4157 char *g_title[] = {"MHz"};
4158 static double *spmin, *spmax;
4160 static int *outsize;
4164 if (action & F_BEGIN) {
4166 * Allocate arrays that will contain the graphs data
4167 * and the min/max values.
4169 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4172 if (action & F_MAIN) {
4174 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
4176 spc = (struct stats_pwr_cpufreq *) ((char *) a->buf[curr] + i * a->msize);
4177 spp = (struct stats_pwr_cpufreq *) ((char *) a->buf[!curr] + i * a->msize);
4179 /* Should current CPU (including CPU "all") be displayed? */
4180 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4185 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4186 ((double) spp->cpufreq) / 100,
4187 ((double) spc->cpufreq) / 100,
4188 out + i, outsize + i, svg_p->restart, svg_p->dt,
4189 spmin + i, spmax + i);
4193 if (action & F_END) {
4194 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
4196 /* Should current CPU (including CPU "all") be displayed? */
4197 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
4202 /* This is CPU "all" */
4203 strcpy(item_name, "all");
4206 sprintf(item_name, "%d", i - 1);
4209 draw_activity_graphs(a->g_nr, g_type,
4210 title, g_title, item_name, group,
4211 spmin + i, spmax + i, out + i, outsize + i,
4215 /* Free remaining structures */
4216 free_graphs(out, outsize, spmin, spmax);
4221 ***************************************************************************
4222 * Display fan statistics in SVG.
4225 * @a Activity structure with statistics.
4226 * @curr Index in array for current sample statistics.
4227 * @action Action expected from current function.
4228 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4229 * flag indicating that a restart record has been previously
4230 * found (.@restart) and time used for the X axis origin
4232 * @itv Interval of time in 1/100th of a second (unused here).
4233 * @record_hdr Pointer on record header of current stats sample.
4234 ***************************************************************************
4236 __print_funct_t svg_print_pwr_fan_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4237 unsigned long long itv, struct record_header *record_hdr)
4239 struct stats_pwr_fan *spc, *spp;
4241 int g_type[] = {SVG_LINE_GRAPH};
4242 char *title[] = {"Fan speed"};
4243 char *g_title[] = {"~rpm"};
4244 static double *spmin, *spmax;
4246 static int *outsize;
4247 char item_name[MAX_SENSORS_DEV_LEN + 8];
4250 if (action & F_BEGIN) {
4252 * Allocate arrays that will contain the graphs data
4253 * and the min/max values.
4255 out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
4258 if (action & F_MAIN) {
4260 for (i = 0; i < a->nr[curr]; i++) {
4262 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4263 spp = (struct stats_pwr_fan *) ((char *) a->buf[!curr] + i * a->msize);
4266 recappend(record_hdr->ust_time - svg_p->ust_time_ref,
4269 out + i, outsize + i, svg_p->restart, svg_p->dt,
4270 spmin + i, spmax + i);
4274 if (action & F_END) {
4275 for (i = 0; i < svg_p->nr_max; i++) {
4277 spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
4279 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4280 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4282 draw_activity_graphs(a->g_nr, g_type,
4283 title, g_title, item_name, group,
4284 spmin + i, spmax + i, out + i, outsize + i,
4288 /* Free remaining structures */
4289 free_graphs(out, outsize, spmin, spmax);
4294 ***************************************************************************
4295 * Display temperature statistics in SVG.
4298 * @a Activity structure with statistics.
4299 * @curr Index in array for current sample statistics.
4300 * @action Action expected from current function.
4301 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4302 * flag indicating that a restart record has been previously
4303 * found (.@restart) and time used for the X axis origin
4305 * @itv Interval of time in 1/100th of a second (unused here).
4306 * @record_hdr Pointer on record header of current stats sample.
4307 ***************************************************************************
4309 __print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4310 unsigned long long itv, struct record_header *record_hdr)
4312 struct stats_pwr_temp *spc;
4313 int group[] = {1, 1};
4314 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4315 char *title[] = {"Device temperature (1)",
4316 "Device temperature (2)"};
4317 char *g_title[] = {"~degC",
4319 static double *spmin, *spmax;
4321 static int *outsize;
4322 char item_name[MAX_SENSORS_DEV_LEN + 8];
4326 if (action & F_BEGIN) {
4328 * Allocate arrays that will contain the graphs data
4329 * and the min/max values.
4331 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4334 if (action & F_MAIN) {
4335 /* For each temperature sensor */
4336 for (i = 0; i < a->nr[curr]; i++) {
4338 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4340 /* Look for min/max values */
4341 if (spc->temp < *(spmin + 2 * i)) {
4342 *(spmin + 2 * i) = spc->temp;
4344 if (spc->temp > *(spmax + 2 * i)) {
4345 *(spmax + 2 * i) = spc->temp;
4347 tval = (spc->temp_max - spc->temp_min) ?
4348 (spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
4350 if (tval < *(spmin + 2 * i + 1)) {
4351 *(spmin + 2 * i + 1) = tval;
4353 if (tval > *(spmax + 2 * i + 1)) {
4354 *(spmax + 2 * i + 1) = tval;
4358 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4360 out + 2 * i, outsize + 2 * i, svg_p->restart);
4362 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4364 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4368 if (action & F_END) {
4369 for (i = 0; i < svg_p->nr_max; i++) {
4371 spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
4373 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4374 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4376 draw_activity_graphs(a->g_nr, g_type,
4377 title, g_title, item_name, group,
4378 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4382 /* Free remaining structures */
4383 free_graphs(out, outsize, spmin, spmax);
4388 ***************************************************************************
4389 * Display voltage inputs statistics in SVG.
4392 * @a Activity structure with statistics.
4393 * @curr Index in array for current sample statistics.
4394 * @action Action expected from current function.
4395 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4396 * flag indicating that a restart record has been previously
4397 * found (.@restart) and time used for the X axis origin
4399 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4400 * @record_hdr Pointer on record header of current stats sample.
4401 ***************************************************************************
4403 __print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4404 unsigned long long itv, struct record_header *record_hdr)
4406 struct stats_pwr_in *spc;
4407 int group[] = {1, 1};
4408 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4409 char *title[] = {"Voltage inputs (1)",
4410 "Voltage inputs (2)"};
4411 char *g_title[] = {"inV",
4413 static double *spmin, *spmax;
4415 static int *outsize;
4416 char item_name[MAX_SENSORS_DEV_LEN + 8];
4420 if (action & F_BEGIN) {
4422 * Allocate arrays that will contain the graphs data
4423 * and the min/max values.
4425 out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
4428 if (action & F_MAIN) {
4429 /* For each voltage input sensor */
4430 for (i = 0; i < a->nr[curr]; i++) {
4432 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4434 /* Look for min/max values */
4435 if (spc->in < *(spmin + 2 * i)) {
4436 *(spmin + 2 * i) = spc->in;
4438 if (spc->in > *(spmax + 2 * i)) {
4439 *(spmax + 2 * i) = spc->in;
4441 tval = (spc->in_max - spc->in_min) ?
4442 (spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
4444 if (tval < *(spmin + 2 * i + 1)) {
4445 *(spmin + 2 * i + 1) = tval;
4447 if (tval > *(spmax + 2 * i + 1)) {
4448 *(spmax + 2 * i + 1) = tval;
4452 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4454 out + 2 * i, outsize + 2 * i, svg_p->restart);
4456 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4458 out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
4462 if (action & F_END) {
4463 for (i = 0; i < svg_p->nr_max; i++) {
4465 spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
4467 snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
4468 item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
4470 draw_activity_graphs(a->g_nr, g_type,
4471 title, g_title, item_name, group,
4472 spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
4476 /* Free remaining structures */
4477 free_graphs(out, outsize, spmin, spmax);
4482 ***************************************************************************
4483 * Display huge pages statistics in SVG.
4486 * @a Activity structure with statistics.
4487 * @curr Index in array for current sample statistics.
4488 * @action Action expected from current function.
4489 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4490 * flag indicating that a restart record has been previously
4491 * found (.@restart) and time used for the X axis origin
4493 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4494 * @record_hdr Pointer on record header of current stats sample.
4495 ***************************************************************************
4497 __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4498 unsigned long long itv, struct record_header *record_hdr)
4501 *smc = (struct stats_huge *) a->buf[curr];
4502 int group[] = {2, 1};
4503 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4504 char *title[] = {"Huge pages utilization (1)",
4505 "Huge pages utilization (2)"};
4506 char *g_title[] = {"~kbhugfree", "~kbhugused",
4508 int g_fields[] = {0};
4509 unsigned int local_types_nr[] = {0, 1, 0};
4510 static double *spmin, *spmax;
4512 static int *outsize;
4515 if (action & F_BEGIN) {
4517 * Allocate arrays that will contain the graphs data
4518 * and the min/max values.
4520 out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
4523 if (action & F_MAIN) {
4524 /* Check for min/max values */
4525 save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
4526 itv, spmin, spmax, g_fields);
4528 if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
4529 *(spmin + 1) = smc->tlhkb - smc->frhkb;
4531 if (smc->tlhkb - smc->frhkb > *(spmax + 1)) {
4532 *(spmax + 1) = smc->tlhkb - smc->frhkb;
4534 tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
4535 if (tval < *(spmin + 2)) {
4536 *(spmin + 2) = tval;
4538 if (tval > *(spmax + 2)) {
4539 *(spmax + 2) = tval;
4543 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4544 (unsigned long) smc->frhkb,
4545 out, outsize, svg_p->restart);
4547 lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
4548 (unsigned long) smc->tlhkb - smc->frhkb,
4549 out + 1, outsize + 1, svg_p->restart);
4551 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4553 out + 2, outsize + 2, svg_p->dt);
4556 if (action & F_END) {
4557 draw_activity_graphs(a->g_nr, g_type,
4558 title, g_title, NULL, group,
4559 spmin, spmax, out, outsize, svg_p, record_hdr);
4561 /* Free remaining structures */
4562 free_graphs(out, outsize, spmin, spmax);
4567 ***************************************************************************
4568 * Display filesystem statistics in SVG.
4571 * @a Activity structure with statistics.
4572 * @curr Index in array for current sample statistics.
4573 * @action Action expected from current function.
4574 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4575 * flag indicating that a restart record has been previously
4576 * found (.@restart) and time used for the X axis origin
4578 * @itv Interval of time in 1/100th of a second (unused here).
4579 * @record_hdr Pointer on record header of current stats sample.
4580 ***************************************************************************
4582 __print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4583 unsigned long long itv, struct record_header *record_hdr)
4585 struct stats_filesystem *sfc, *sfp;
4586 int group[] = {2, 2, 2, 1};
4587 int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
4588 SVG_LINE_GRAPH, SVG_BAR_GRAPH};
4589 char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
4590 "Filesystem statistics (3)", "Filesystem statistics (4)"};
4591 char *g_title[] = {"~MBfsfree", "~MBfsused",
4592 "%ufsused", "%fsused",
4593 "Ifree/1000", "Iused/1000",
4595 static double *spmin, *spmax;
4597 static int *outsize;
4598 char *item_name = NULL;
4600 int i, k, pos, restart;
4602 if (action & F_BEGIN) {
4604 * Allocate arrays (#0..6) that will contain the graphs data
4605 * and the min/max values.
4606 * Also allocate two additional arrays (#7..8) for each filesystem:
4607 * out + 7 will contain the filesystem name,
4608 * out + 8 will contain the mount point.
4610 out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
4613 if (action & F_MAIN) {
4614 /* For each filesystem structure */
4615 for (i = 0; i < a->nr[curr]; i++) {
4616 sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
4618 /* Look for corresponding graph */
4619 for (k = 0; k < svg_p->nr_max; k++) {
4620 item_name = *(out + k * 9 + 7);
4621 if (!strcmp(sfc->fs_name, item_name))
4626 if (k == svg_p->nr_max) {
4627 /* Graph not found: Look for first free entry */
4628 for (k = 0; k < svg_p->nr_max; k++) {
4629 item_name = *(out + k * 9 + 7);
4630 if (!strcmp(item_name, ""))
4633 if (k == svg_p->nr_max) {
4634 /* No free graph entry: Extend all buffers */
4635 reallocate_all_graph_lines(svg_p->nr_max,
4636 &out, &outsize, &spmin, &spmax);
4643 if (!item_name[0]) {
4644 /* Save filesystem name and mount point (if not already done) */
4645 strncpy(item_name, sfc->fs_name, CHUNKSIZE);
4646 item_name[CHUNKSIZE - 1] = '\0';
4647 item_name = *(out + pos + 8);
4648 strncpy(item_name, sfc->mountp, CHUNKSIZE);
4649 item_name[CHUNKSIZE - 1] = '\0';
4653 for (k = 0; k < a->nr[!curr]; k++) {
4654 sfp = (struct stats_filesystem *) ((char *) a->buf[!curr] + k * a->msize);
4655 if (!strcmp(sfc->fs_name, sfp->fs_name)) {
4656 /* Filesystem found in previous sample */
4657 restart = svg_p->restart;
4661 /* Check for min/max values */
4663 /* Compute fsfree min/max values */
4664 tval = (double) sfc->f_bfree;
4665 if (tval > *(spmax + pos)) {
4666 *(spmax + pos) = tval;
4668 if (tval < *(spmin + pos)) {
4669 *(spmin + pos) = tval;
4671 /* Compute fsused min/max values */
4672 tval = (double) (sfc->f_blocks - sfc->f_bfree);
4673 if (tval > *(spmax + pos + 1)) {
4674 *(spmax + pos + 1) = tval;
4676 if (tval < *(spmin + pos + 1)) {
4677 *(spmin + pos + 1) = tval;
4679 /* Compute %ufsused min/max values */
4680 tval = sfc->f_blocks ?
4681 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0;
4682 if (tval > *(spmax + pos + 2)) {
4683 *(spmax + pos + 2) = tval;
4685 if (tval < *(spmin + pos + 2)) {
4686 *(spmin + pos + 2) = tval;
4688 /* Compute %fsused min/max values */
4689 tval = sfc->f_blocks ?
4690 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0;
4691 if (tval > *(spmax + pos + 3)) {
4692 *(spmax + pos + 3) = tval;
4694 if (tval < *(spmin + pos + 3)) {
4695 *(spmin + pos + 3) = tval;
4697 /* Compute Ifree min/max values */
4698 tval = (double) sfc->f_ffree;
4699 if (tval > *(spmax + pos + 4)) {
4700 *(spmax + pos + 4) = tval;
4702 if (tval < *(spmin + pos + 4)) {
4703 *(spmin + pos + 4) = tval;
4705 /* Compute Iused min/max values */
4706 tval = (double) (sfc->f_files - sfc->f_ffree);
4707 if (tval > *(spmax + pos + 5)) {
4708 *(spmax + pos + 5) = tval;
4710 if (tval < *(spmin + pos + 5)) {
4711 *(spmin + pos + 5) = tval;
4713 /* Compute %Iused min/max values */
4714 tval = sfc->f_files ?
4715 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0;
4716 if (tval > *(spmax + pos + 6)) {
4717 *(spmax + pos + 6) = tval;
4719 if (tval < *(spmin + pos + 6)) {
4720 *(spmin + pos + 6) = tval;
4724 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4725 (double) sfc->f_bfree / 1024 / 1024,
4726 out + pos, outsize + pos, restart);
4728 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4729 (double) (sfc->f_blocks - sfc->f_bfree) / 1024 / 1024,
4730 out + pos + 1, outsize + pos + 1, restart);
4732 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4735 SP_VALUE(sfc->f_bavail, sfc->f_blocks, sfc->f_blocks) : 0.0,
4736 out + pos + 2, outsize + pos + 2, svg_p->dt);
4738 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4741 SP_VALUE(sfc->f_bfree, sfc->f_blocks, sfc->f_blocks) : 0.0,
4742 out + pos + 3, outsize + pos + 3, svg_p->dt);
4744 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4745 ((double) sfc->f_ffree) / 1000,
4746 out + pos + 4, outsize + pos + 4, restart);
4748 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4749 ((double) (sfc->f_files - sfc->f_ffree)) / 1000,
4750 out + pos + 5, outsize + pos + 5, restart);
4752 brappend(record_hdr->ust_time - svg_p->ust_time_ref,
4755 SP_VALUE(sfc->f_ffree, sfc->f_files, sfc->f_files) : 0.0,
4756 out + pos + 6, outsize + pos + 6, svg_p->dt);
4760 if (action & F_END) {
4762 for (i = 0; i < svg_p->nr_max; i++) {
4764 /* Check if there is something to display */
4769 /* Conversion B -> MB and inodes/1000 */
4770 for (k = 0; k < 2; k++) {
4771 *(spmin + pos + k) /= (1024 * 1024);
4772 *(spmax + pos + k) /= (1024 * 1024);
4773 *(spmin + pos + 4 + k) /= 1000;
4774 *(spmax + pos + 4 + k) /= 1000;
4777 if (DISPLAY_MOUNT(a->opt_flags)) {
4778 item_name = *(out + pos + 8);
4781 item_name = *(out + pos + 7);
4784 draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
4785 spmin + pos, spmax + pos, out + pos, outsize + pos,
4789 /* Free remaining structures */
4790 free_graphs(out, outsize, spmin, spmax);
4795 ***************************************************************************
4796 * Display Fibre Channel HBA statistics in SVG.
4799 * @a Activity structure with statistics.
4800 * @curr Index in array for current sample statistics.
4801 * @action Action expected from current function.
4802 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4803 * flag indicating that a restart record has been previously
4804 * found (.@restart) and time used for the X axis origin
4806 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4807 * @record_hdr Pointer on record header of current stats sample.
4808 ***************************************************************************
4810 __print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4811 unsigned long long itv, struct record_header *record_hdr)
4813 struct stats_fchost *sfcc, *sfcp;
4814 int group[] = {2, 2};
4815 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4816 char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
4817 char *g_title[] = {"fch_rxf/s", "fch_txf/s",
4818 "fch_rxw/s", "fch_txw/s"};
4819 int g_fields[] = {0, 1, 2, 3};
4820 static double *spmin, *spmax;
4822 static int *outsize;
4824 int i, j, j0, k, found, pos, restart, *unregistered;
4826 if (action & F_BEGIN) {
4828 * Allocate arrays (#0..3) that will contain the graphs data
4829 * and the min/max values.
4830 * Also allocate one additional array (#4) that will contain
4831 * FC HBA name (out + 4) and a positive value (TRUE) if the interface
4832 * has either still not been registered, or has been unregistered
4835 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
4838 if (action & F_MAIN) {
4839 restart = svg_p->restart;
4841 * Mark previously registered interfaces as now
4842 * possibly unregistered for all graphs.
4844 for (k = 0; k < svg_p->nr_max; k++) {
4845 unregistered = outsize + k * 5 + 4;
4846 if (*unregistered == FALSE) {
4847 *unregistered = MAYBE;
4851 /* For each FC HBA */
4852 for (i = 0; i < a->nr[curr]; i++) {
4853 sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
4855 /* Look for corresponding graph */
4856 for (k = 0; k < svg_p->nr_max; k++) {
4857 item_name = *(out + k * 5 + 4);
4858 if (!strcmp(sfcc->fchost_name, item_name))
4862 if (k == svg_p->nr_max) {
4863 /* Graph not found: Look for first free entry */
4864 for (k = 0; k < svg_p->nr_max; k++) {
4865 item_name = *(out + k * 5 + 4);
4866 if (!strcmp(item_name, ""))
4869 if (k == svg_p->nr_max) {
4870 /* No free graph entry: Extend all buffers */
4871 reallocate_all_graph_lines(svg_p->nr_max,
4872 &out, &outsize, &spmin, &spmax);
4878 unregistered = outsize + pos + 4;
4880 /* Look for corresponding structure in previous iteration */
4882 if (j > a->nr[!curr]) {
4890 if (j > a->nr[!curr]) {
4893 sfcp = (struct stats_fchost *) ((char *) a->buf[!curr] + j * a->msize);
4894 if (!strcmp(sfcc->fchost_name, sfcp->fchost_name)) {
4906 * If current interface was marked as previously unregistered,
4907 * then set restart variable to TRUE so that the graph will be
4908 * discontinuous, and mark it as now registered.
4910 if (*unregistered == TRUE) {
4913 *unregistered = FALSE;
4915 item_name = *(out + pos + 4);
4916 if (!item_name[0]) {
4917 /* Save FC HBA name */
4918 strncpy(item_name, sfcc->fchost_name, CHUNKSIZE);
4919 item_name[CHUNKSIZE - 1] = '\0';
4922 /* Look for min/max values */
4923 save_extrema(a->gtypes_nr, (void *) sfcc, (void *) sfcp,
4924 itv, spmin + pos, spmax + pos, g_fields);
4927 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4928 S_VALUE(sfcp->f_rxframes, sfcc->f_rxframes, itv),
4929 out + pos, outsize + pos, restart);
4931 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4932 S_VALUE(sfcp->f_txframes, sfcc->f_txframes, itv),
4933 out + pos + 1, outsize + pos + 1, restart);
4935 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4936 S_VALUE(sfcp->f_rxwords, sfcc->f_rxwords, itv),
4937 out + pos + 2, outsize + pos + 2, restart);
4939 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
4940 S_VALUE(sfcp->f_txwords, sfcc->f_txwords, itv),
4941 out + pos + 3, outsize + pos + 3, restart);
4944 /* Mark interfaces not seen here as now unregistered */
4945 for (k = 0; k < svg_p->nr_max; k++) {
4946 unregistered = outsize + k * 5 + 4;
4947 if (*unregistered != FALSE) {
4948 *unregistered = TRUE;
4953 if (action & F_END) {
4954 for (i = 0; i < svg_p->nr_max; i++) {
4956 /* Check if there is something to display */
4961 item_name = *(out + pos + 4);
4962 draw_activity_graphs(a->g_nr, g_type,
4963 title, g_title, item_name, group,
4964 spmin + pos, spmax + pos, out + pos, outsize + pos,
4968 /* Free remaining structures */
4969 free_graphs(out, outsize, spmin, spmax);
4974 ***************************************************************************
4975 * Display softnet statistics in SVG.
4978 * @a Activity structure with statistics.
4979 * @curr Index in array for current sample statistics.
4980 * @action Action expected from current function.
4981 * @svg_p SVG specific parameters: Current graph number (.@graph_no),
4982 * flag indicating that a restart record has been previously
4983 * found (.@restart) and time used for the X axis origin
4985 * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
4986 * @record_hdr Pointer on record header of current stats sample.
4987 ***************************************************************************
4989 __print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
4990 unsigned long long itv, struct record_header *record_hdr)
4992 struct stats_softnet *ssnc, *ssnp;
4993 int group[] = {2, 3};
4994 int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
4995 char *title[] = {"Software-based network processing statistics (1)",
4996 "Software-based network processing statistics (2)"};
4997 char *g_title[] = {"total/s", "dropd/s",
4998 "squeezd/s", "rx_rps/s", "flw_lim/s"};
4999 int g_fields[] = {0, 1, 2, 3, 4};
5000 static double *spmin, *spmax;
5002 static int *outsize;
5006 if (action & F_BEGIN) {
5008 * Allocate arrays that will contain the graphs data
5009 * and the min/max values.
5011 out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
5014 if (action & F_MAIN) {
5016 for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
5018 ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
5019 ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
5021 /* Should current CPU (including CPU "all") be displayed? */
5022 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5028 /* Check for min/max values */
5029 save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
5030 itv, spmin + pos, spmax + pos, g_fields);
5033 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5034 S_VALUE(ssnp->processed, ssnc->processed, itv),
5035 out + pos, outsize + pos, svg_p->restart);
5037 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5038 S_VALUE(ssnp->dropped, ssnc->dropped, itv),
5039 out + pos + 1, outsize + pos + 1, svg_p->restart);
5041 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5042 S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
5043 out + pos + 2, outsize + pos + 2, svg_p->restart);
5045 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5046 S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
5047 out + pos + 3, outsize + pos + 3, svg_p->restart);
5049 lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
5050 S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
5051 out + pos + 4, outsize + pos + 4, svg_p->restart);
5055 if (action & F_END) {
5056 for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
5058 /* Should current CPU (including CPU "all") be displayed? */
5059 if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
5066 /* This is CPU "all" */
5067 strcpy(item_name, "all");
5070 sprintf(item_name, "%d", i - 1);
5073 draw_activity_graphs(a->g_nr, g_type,
5074 title, g_title, item_name, group,
5075 spmin + pos, spmax + pos, out + pos, outsize + pos,
5079 /* Free remaining structures */
5080 free_graphs(out, outsize, spmin, spmax);