/*
- * svg_stats.c: Funtions used by sadf to display statistics in SVG format.
- * (C) 2016-2017 by Sebastien GODARD (sysstat <at> orange.fr)
+ * svg_stats.c: Functions used by sadf to display statistics in SVG format.
+ * (C) 2016-2021 by Sebastien GODARD (sysstat <at> orange.fr)
*
***************************************************************************
* This program is free software; you can redistribute it and/or modify it *
#define _(string) (string)
#endif
-extern unsigned int flags;
-extern unsigned int dm_major;
-
-unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
- 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
- 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
- 0xcc3300, 0x50040f, 0xffffbf, 0x193d55};
-#define SVG_COLORS_IDX_MASK 0x0f
+extern uint64_t flags;
+extern int palette;
+
+unsigned int svg_colors[SVG_COL_PALETTE_NR][SVG_COL_PALETTE_SIZE] =
+ {{0x00cc00, 0xff00bf, 0x00ffff, 0xff0000, /* Default palette */
+ 0xe85f00, 0x0000ff, 0x006020, 0x7030a0,
+ 0xffff00, 0x666635, 0xd60093, 0x00bfbf,
+ 0xcc3300, 0x50040f, 0xffffbf, 0x193d55,
+ 0x000000, 0xffffff, 0x202020, 0xffff00,
+ 0xffff00, 0x808080, 0xa52a2a, 0xff0000},
+
+ {0x000000, 0x1a1aff, 0x1affb2, 0xb21aff, /* Custom color palette */
+ 0x1ab2ff, 0xff1a1a, 0xffb31a, 0xb2ff1a,
+ 0xefefef, 0x000000, 0x1a1aff, 0x1affb2,
+ 0xb21aff, 0x1ab2ff, 0xff1a1a, 0xffb31a,
+ 0xffffff, 0x000000, 0xbebebe, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000},
+
+ {0x696969, 0xbebebe, 0x000000, 0xa9a9a9, /* Black & white palette */
+ 0x708090, 0xc0c0c0, 0x808080, 0xd3d3d3,
+ 0x909090, 0x696969, 0xbebebe, 0x000000,
+ 0x000000, 0xa9a9a9, 0xc0c0c0, 0x808080,
+ 0xffffff, 0x000000, 0xbebebe, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000}};
/*
***************************************************************************
* the fields in the statistics structure.
*
* OUT:
- * @spmin Array containg the possible new min values for current activity.
- * @spmax Array containg the possible new max values for current activity.
+ * @spmin Array containing the possible new min values for current activity.
+ * @spmax Array containing the possible new max values for current activity.
***************************************************************************
*/
void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
return out;
}
-/*
- ***************************************************************************
- * Reallocate all the arrays used to save graphs data, min and max values.
- * The new size is the double of the original one.
- *
- * IN:
- * @n Number of slots currently allocated.
- * @out Current pointer on arrays containing the graphs data.
- * @outsize Current pointer on array containing the size of each element
- * in array of chars.
- * @spmin Current pointer on array containing min values.
- * @spmax Current pointer on array containing max values.
- *
- * OUT:
- * @out New pointer on arrays containing the graphs data.
- * @outsize New pointer on array containing the size of each element
- * in array of chars.
- * @spmin New pointer on array containing min values.
- * @spmax New pointer on array containing max values.
- ***************************************************************************
- */
-void reallocate_all_graph_lines(int n, char ***out, int **outsize,
- double **spmin, double **spmax)
-{
- char *out_p;
- int i;
-
- /* Reallocate all the arrays */
- SREALLOC(*out, char *, n * sizeof(char *) * 2);
- SREALLOC(*outsize, int, n * sizeof(int) * 2);
- SREALLOC(*spmin, double, n * sizeof(double) * 2);
- SREALLOC(*spmax, double, n * sizeof(double) * 2);
-
- /* Allocate arrays of chars that will contain graphs data for the newly allocated slots */
- for (i = 0; i < n; i++) {
- if ((out_p = (char *) malloc(CHUNKSIZE * sizeof(char))) == NULL) {
- perror("malloc");
- exit(4);
- }
- *(*out + n + i) = out_p;
- *out_p = '\0';
- *(*outsize + n + i) = CHUNKSIZE;
- *(*spmin + n + i) = DBL_MAX;
- *(*spmax + n + i) = -DBL_MAX;
- }
-}
-
/*
***************************************************************************
* Save SVG code for current graph.
int *outsize, unsigned long long dt)
{
char data[128];
+ unsigned long long t = 0;
/* Prepare additional graph definition data */
if ((value == 0.0) || (dt == 0))
/* Don't draw a flat rectangle! */
return;
+ if (dt < timetag) {
+ t = timetag -dt;
+ }
snprintf(data, 128, "<rect x=\"%llu\" y=\"%.2f\" height=\"%.2f\" width=\"%llu\"/>",
- timetag - dt, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
+ t, MINIMUM(offset, 100.0), MINIMUM(value, (100.0 - offset)), dt);
data[127] = '\0';
save_svg_data(data, out, outsize);
int *outsize, int restart, unsigned long long dt,
double *spmin, double *spmax)
{
- char data[128], data1[128], data2[128];
+ char data[512], data1[128], data2[128];
+ unsigned long long t = 0;
/* Save min and max values */
if (value < *spmin) {
if (value > *spmax) {
*spmax = value;
}
+ if (dt < timetag) {
+ t = timetag -dt;
+ }
/* Prepare additional graph definition data */
if (restart) {
- snprintf(data1, 128, " M%llu,%.2f", timetag - dt, p_value);
- data1[127] = '\0';
+ snprintf(data1, sizeof(data1), " M%llu,%.2f", t, p_value);
+ data1[sizeof(data1) - 1] = '\0';
}
if (p_value != value) {
- snprintf(data2, 128, " L%llu,%.2f", timetag, value);
- data2[127] = '\0';
+ snprintf(data2, sizeof(data2), " L%llu,%.2f", timetag, value);
+ data2[sizeof(data2) - 1] = '\0';
}
- snprintf(data, 128, "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
+ snprintf(data, sizeof(data), "%s L%llu,%.2f%s", restart ? data1 : "", timetag, p_value,
p_value != value ? data2 : "");
- data[127] = '\0';
+ data[sizeof(data) - 1] = '\0';
save_svg_data(data, out, outsize);
}
int j = 0;
char stmp[32];
+ /* Print marker in debug mode */
+ if (DISPLAY_DEBUG_MODE(flags)) {
+ printf("<!-- Hgrid -->\n");
+ }
+
do {
/* Display horizontal lines (except on X axis) */
if (j > 0) {
printf("<polyline points=\"0,%.2f %d,%.2f\" style=\"vector-effect: non-scaling-stroke; "
- "stroke: #202020\" transform=\"scale(1,%f)\"/>\n",
- ypos * j, SVG_G_XSIZE, ypos * j, yfactor);
+ "stroke: #%06x\" transform=\"scale(1,%f)\"/>\n",
+ ypos * j, SVG_G_XSIZE, ypos * j,
+ svg_colors[palette][SVG_COL_GRID_IDX],
+ yfactor);
}
/*
* to make sure they are properly aligned.
*/
sprintf(stmp, "%.2f", ypos * j);
- printf("<text x=\"0\" y=\"%ld\" style=\"fill: white; stroke: none; font-size: 12px; "
+ printf("<text x=\"0\" y=\"%ld\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
"text-anchor: end\">%.*f.</text>\n",
- (long) (atof(stmp) * yfactor), dp, ypos * j);
+ (long) (atof(stmp) * yfactor),
+ svg_colors[palette][SVG_COL_AXIS_IDX],
+ dp, ypos * j);
j++;
}
while ((ypos * j <= lmax) && (j < MAX_HLINES_NR));
stamp.ust_time = svg_p->ust_time_ref; /* Only ust_time field needs to be set. TRUE_TIME not allowed */
+ /* Print marker in debug mode */
+ if (DISPLAY_DEBUG_MODE(flags)) {
+ printf("<!-- Vgrid -->\n");
+ }
+
/*
* What really matters to know when we should stop drawing vertical lines
* is the time end. v_gridnr is only informative and used to calculate
for (j = 0; (j <= (2 * v_gridnr)) && (stamp.ust_time <= svg_p->ust_time_end); j++) {
/* Display vertical lines */
- sa_get_record_timestamp_struct(flags, &stamp, &rectime, NULL);
+ if (sa_get_record_timestamp_struct(flags, &stamp, &rectime)) {
+#ifdef DEBUG
+ fprintf(stderr, "%s: ust_time: %llu\n", __FUNCTION__, stamp.ust_time);
+#endif
+ exit(1);
+ }
set_record_timestamp_string(flags, &stamp, NULL, cur_time, TIMESTAMP_LEN, &rectime);
printf("<polyline points=\"%ld,0 %ld,%d\" style=\"vector-effect: non-scaling-stroke; "
- "stroke: #202020\" transform=\"scale(%f,1)\"/>\n",
- xpos * j, xpos * j, -SVG_G_YSIZE, xfactor);
+ "stroke: #%06x\" transform=\"scale(%f,1)\"/>\n",
+ xpos * j, xpos * j, -SVG_G_YSIZE,
+ svg_colors[palette][SVG_COL_GRID_IDX],
+ xfactor);
/*
* Display graduations.
* NB: We may have tm_min != 0 if we have more than 24H worth of data in one datafile.
* In this case, we should rather display the exact time instead of only the hour.
*/
if (DISPLAY_ONE_DAY(flags) && (rectime.tm_min == 0)) {
- printf("<text x=\"%ld\" y=\"15\" style=\"fill: white; stroke: none; font-size: 14px; "
+ printf("<text x=\"%ld\" y=\"15\" style=\"fill: #%06x; stroke: none; font-size: 14px; "
"text-anchor: start\">%2d:00</text>\n",
- (long) (xpos * j * xfactor) - 15, rectime.tm_hour);
+ (long) (xpos * j * xfactor) - 15,
+ svg_colors[palette][SVG_COL_AXIS_IDX],
+ rectime.tm_hour);
}
else {
- printf("<text x=\"%ld\" y=\"10\" style=\"fill: white; stroke: none; font-size: 12px; "
+ printf("<text x=\"%ld\" y=\"10\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
"text-anchor: start\" transform=\"rotate(45,%ld,0)\">%s</text>\n",
- (long) (xpos * j * xfactor), (long) (xpos * j * xfactor), cur_time);
+ (long) (xpos * j * xfactor),
+ svg_colors[palette][SVG_COL_AXIS_IDX],
+ (long) (xpos * j * xfactor), cur_time);
}
stamp.ust_time += xpos;
}
if (!PRINT_LOCAL_TIME(flags)) {
- printf("<text x=\"-10\" y=\"30\" style=\"fill: yellow; stroke: none; font-size: 12px; "
- "text-anchor: end\">UTC</text>\n");
+ printf("<text x=\"-10\" y=\"30\" style=\"fill: #%06x; stroke: none; font-size: 12px; "
+ "text-anchor: end\">UTC</text>\n",
+ svg_colors[palette][SVG_COL_INFO_IDX]);
}
}
* times used as start and end values on the X axis
* (.@ust_time_ref and .@ust_time_end).
* @record_hdr Pointer on record header of current stats sample.
+ * @skip_void Set to <> 0 if graphs with no data should be skipped.
+ * This is typicallly used to not display CPU offline on the
+ * whole period.
+ * @a Current activity structure.
+ * @xid Current activity extra id number.
+ *
+ * RETURNS:
+ * TRUE if at least one graph has been displayed.
***************************************************************************
*/
-void draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
- int group[], double *spmin, double *spmax, char **out, int *outsize,
- struct svg_parm *svg_p, struct record_header *record_hdr)
+int draw_activity_graphs(int g_nr, int g_type[], char *title[], char *g_title[], char *item_name,
+ int group[], double *spmin, double *spmax, char **out, int *outsize,
+ struct svg_parm *svg_p, struct record_header *record_hdr, int skip_void,
+ struct activity *a, unsigned int xid)
{
char *out_p;
- int i, j, dp, pos = 0, views_nr = 0;
+ int i, j, dp, pos = 0, views_nr = 0, displayed = FALSE, palpos;
int v_gridnr, xv, yv;
unsigned int asfactor[16];
long int xpos;
double lmax, xfactor, yfactor, ypos, gmin, gmax;
char val[32], cur_date[TIMESTAMP_LEN];
+ struct tm rectime;
- /* Translate to proper position for current activity */
- printf("<g id=\"g%d\" transform=\"translate(0,%d)\">\n",
- svg_p->graph_no,
- SVG_H_YSIZE + svg_p->graph_no * SVG_T_YSIZE);
+ /* Print activity name in debug mode */
+ if (DISPLAY_DEBUG_MODE(flags)) {
+ printf("<!-- Name: %s -->\n", a->name);
+ }
/* For each view which is part of current activity */
for (i = 0; i < g_nr; i++) {
+ /* Print view number in debug mode */
+ if (DISPLAY_DEBUG_MODE(flags)) {
+ printf("<!-- View %d -->\n", i + 1);
+ }
+
+ /* Used as index in color palette */
+ palpos = (palette == SVG_BW_COL_PALETTE ? 0 : pos);
+
/* Get global min and max value for current view */
get_global_extrema(pos, group[i], spmin, spmax, &gmin, &gmax);
skip_current_view(out, &pos, group[i]);
continue;
}
+ /* Skip void graphs */
+ if (skip_void && ((*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)))
+ continue;
+
+ if (!displayed) {
+ /* Translate to proper position for current activity */
+ printf("<g id=\"g%d-%d\" transform=\"translate(0,%d)\">\n",
+ a->id, xid,
+ SVG_H_YSIZE +
+ SVG_C_YSIZE * (DISPLAY_TOC(flags) ? svg_p->nr_act_dispd : 0) +
+ SVG_T_YSIZE * svg_p->graph_no);
+ displayed = TRUE;
+ }
+
/* Increment number of views actually displayed */
views_nr++;
}
/* Graph background */
- printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\"/>\n",
- xv, yv, SVG_V_YSIZE, SVG_V_XSIZE);
+ printf("<rect x=\"%d\" y=\"%d\" height=\"%d\" width=\"%d\" fill=\"#%06x\"/>\n",
+ xv, yv, SVG_V_YSIZE, SVG_V_XSIZE,
+ svg_colors[palette][SVG_COL_BCKGRD_IDX]);
/* Graph title */
- printf("<text x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none\">%s",
- xv, 20 + yv, title[i]);
+ printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">%s",
+ xv, 20 + yv,
+ svg_colors[palette][SVG_COL_TITLE_IDX],
+ title[i]);
if (item_name) {
printf(" [%s]", item_name);
}
printf("\n");
- printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: yellow; stroke: none; font-size: 12px\">"
+ printf("<tspan x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
"(Min, Max values)</tspan>\n</text>\n",
- xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25);
+ xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + 25,
+ svg_colors[palette][SVG_COL_INFO_IDX]);
/*
* At least two samples are needed.
if ((record_hdr->ust_time == svg_p->ust_time_first) ||
(*(spmin + pos) == DBL_MAX) || (*(spmax + pos) == -DBL_MIN)) {
/* No data found */
- printf("<text x=\"%d\" y=\"%d\" style=\"fill: red; stroke: none\">No data</text>\n",
- xv, yv + SVG_M_YSIZE);
+ printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none\">No data</text>\n",
+ xv, yv + SVG_M_YSIZE,
+ svg_colors[palette][SVG_COL_ERROR_IDX]);
skip_current_view(out, &pos, group[i]);
continue;
}
/* X and Y axis */
- printf("<polyline points=\"%d,%d %d,%d %d,%d\" stroke=\"white\" stroke-width=\"2\"/>\n",
+ printf("<polyline points=\"%d,%d %d,%d %d,%d\" style=\"fill: #%06x; stroke: #%06x; stroke-width: 2\"/>\n",
xv + SVG_M_XSIZE, yv + SVG_M_YSIZE,
xv + SVG_M_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
- xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE);
+ xv + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + SVG_G_YSIZE,
+ svg_colors[palette][SVG_COL_BCKGRD_IDX],
+ svg_colors[palette][SVG_COL_AXIS_IDX]);
/* Autoscaling graphs if needed */
gr_autoscaling(asfactor, 16, group[i], g_type[i], pos, gmax, spmax);
printf("<text x=\"%d\" y=\"%d\" style=\"fill: #%06x; stroke: none; font-size: 12px\">"
"%s %s(%.*f, %.*f)</text>\n",
xv + 5 + SVG_M_XSIZE + SVG_G_XSIZE, yv + SVG_M_YSIZE + j * 15,
- svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
+ svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], g_title[pos + j] + dp,
asfactor[j] == 1 ? "" : val,
!dp * 2, *(spmin + pos + j) * asfactor[j],
!dp * 2, *(spmax + pos + j) * asfactor[j]);
if (DISPLAY_INFO(flags)) {
/* Display additional info (hostname, date) */
printf("<text x=\"%d\" y=\"%d\" "
- "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
+ "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
"%s\n",
xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE,
+ svg_colors[palette][SVG_COL_INFO_IDX],
svg_p->file_hdr->sa_nodename);
/* Get report date */
- set_report_date(localtime((const time_t *) &(svg_p->file_hdr->sa_ust_time)),
+ set_report_date(localtime_r((const time_t *) &(svg_p->file_hdr->sa_ust_time), &rectime),
cur_date, sizeof(cur_date));
printf("<tspan x=\"%d\" y=\"%d\" "
- "style=\"fill: yellow; text-anchor: end; stroke: none; font-size: 14px\">"
+ "style=\"fill: #%06x; text-anchor: end; stroke: none; font-size: 14px\">"
"%s</tspan>\n</text>\n",
xv + SVG_V_XSIZE - 5, yv + SVG_M_YSIZE + SVG_G_YSIZE + 14,
+ svg_colors[palette][SVG_COL_INFO_IDX],
cur_date);
}
/* Display vertical lines and graduations */
display_vgrid(xpos, xfactor, v_gridnr, svg_p);
+ /* Print marker in debug mode */
+ if (DISPLAY_DEBUG_MODE(flags)) {
+ printf("<!-- Graphs -->\n");
+ }
+
/* Draw current graphs set */
for (j = 0; j < group[i]; j++) {
out_p = *(out + pos + j);
if (g_type[i] == SVG_LINE_GRAPH) {
/* Line graphs */
- printf("<path id=\"g%dp%d\" d=\"%s\" "
+ printf("<path d=\"%s\" "
"style=\"vector-effect: non-scaling-stroke; "
"stroke: #%06x; stroke-width: 1; fill-opacity: 0\" "
"transform=\"scale(%f,%f)\"/>\n",
- svg_p->graph_no, pos + j, out_p,
- svg_colors[(pos + j) & SVG_COLORS_IDX_MASK],
+ out_p,
+ svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK],
xfactor,
yfactor * asfactor[j]);
}
else if (*out_p) { /* Ignore flat bars */
/* Bar graphs */
printf("<g style=\"fill: #%06x; stroke: none\" transform=\"scale(%f,%f)\">\n",
- svg_colors[(pos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
+ svg_colors[palette][(palpos + j) & SVG_COLORS_IDX_MASK], xfactor, yfactor);
printf("%s\n", out_p);
printf("</g>\n");
}
printf("</g>\n");
pos += group[i];
}
- printf("</g>\n");
+ if (displayed) {
+ printf("</g>\n");
+
+ /* For next row of views */
+ (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
+ }
- /* For next row of views */
- (svg_p->graph_no) += PACK_VIEWS(flags) ? 1 : views_nr;
+ return displayed;
}
/*
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define CPU_ARRAY_SZ 10
__print_funct_t svg_print_cpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
struct stats_cpu *scc, *scp;
- unsigned long long tot_jiffies_c, tot_jiffies_p;
- unsigned long long deltot_jiffies;
+ unsigned long long deltot_jiffies = 1;
+ unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
int group1[] = {5};
int group2[] = {9};
int g_type[] = {SVG_BAR_GRAPH};
- char *title[] = {"CPU load"};
+ char *title[] = {"CPU utilization"};
char *g_title1[] = {"%user", "%nice", "%system", "%iowait", "%steal", "%idle"};
char *g_title2[] = {"%usr", "%nice", "%sys", "%iowait", "%steal", "%irq", "%soft", "%guest", "%gnice", "%idle"};
static double *spmin, *spmax;
static char **out;
static int *outsize;
- char item_name[8];
+ char item_name[16];
double offset, val;
int i, j, k, pos;
* Allocate arrays that will contain the graphs data
* and the min/max values.
*/
- out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(CPU_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
a->nr_ini = a->nr[curr];
}
+ /*
+ * Compute CPU "all" as sum of all individual CPU (on SMP machines)
+ * and look for offline CPU.
+ */
+ if (a->nr_ini > 1) {
+ deltot_jiffies = get_global_cpu_statistics(a, !curr, curr,
+ flags, offline_cpu_bitmap);
+ }
+
/* For each CPU */
for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
- scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
- scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
-
/* Should current CPU (including CPU "all") be displayed? */
- if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
- /* No */
+ if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) ||
+ offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07)))
+ /* Don't display CPU */
continue;
- /*
- * Yes: Compute the total number of jiffies spent by current processor.
- * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
- * already include them.
- */
- tot_jiffies_c = scc->cpu_user + scc->cpu_nice +
- scc->cpu_sys + scc->cpu_idle +
- scc->cpu_iowait + scc->cpu_hardirq +
- scc->cpu_steal + scc->cpu_softirq;
- tot_jiffies_p = scp->cpu_user + scp->cpu_nice +
- scp->cpu_sys + scp->cpu_idle +
- scp->cpu_iowait + scp->cpu_hardirq +
- scp->cpu_steal + scp->cpu_softirq;
-
- /* Total number of jiffies spent on the interval */
- deltot_jiffies = get_interval(tot_jiffies_p, tot_jiffies_c);
-
- pos = i * 10;
+ scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
+ scp = (struct stats_cpu *) ((char *) a->buf[!curr] + i * a->msize);
+
+ pos = i * CPU_ARRAY_SZ;
offset = 0.0;
- if (i) { /* Don't test CPU "all" here */
- /*
- * If the CPU is offline then it is omited from /proc/stat:
- * All the fields couldn't have been read and the sum of them is zero.
- * (Remember that guest/guest_nice times are already included in
- * user/nice modes.)
- */
- if (tot_jiffies_c == 0) {
+ if (i == 0) {
+ /* This is CPU "all" */
+ if (a->nr_ini == 1) {
/*
- * Set current struct fields (which have been set to zero)
- * to values from previous iteration. Hence their values won't
- * jump from zero when the CPU comes back online.
+ * This is a UP machine. In this case
+ * interval has still not been calculated.
*/
- *scc = *scp;
-
- /* An offline CPU is not displayed */
- continue;
+ deltot_jiffies = get_per_cpu_interval(scc, scp);
}
- if (tot_jiffies_p == 0)
- /* CPU has just come back online */
- continue;
-
+ if (!deltot_jiffies) {
+ /* CPU "all" cannot be tickless */
+ deltot_jiffies = 1;
+ }
+ }
+ else {
/*
* Recalculate interval for current proc.
* If result is 0 then current CPU is a tickless one.
}
if (action & F_END) {
+ int xid = 0, displayed;
+
if (DISPLAY_IDLE(flags)) {
/* Include additional %idle field */
group1[0]++;
group2[0]++;
}
- for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
+ for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
/* Should current CPU (including CPU "all") be displayed? */
if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
/* No */
continue;
- pos = i * 10;
+ pos = i * CPU_ARRAY_SZ;
if (!i) {
/* This is CPU "all" */
strcpy(item_name, "all");
}
if (DISPLAY_CPU_DEF(a->opt_flags)) {
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title1, item_name, group1,
- spmin + pos, spmax + pos, out + pos, outsize + pos,
- svg_p, record_hdr);
+ displayed = draw_activity_graphs(a->g_nr, g_type,
+ title, g_title1, item_name, group1,
+ spmin + pos, spmax + pos, out + pos, outsize + pos,
+ svg_p, record_hdr, i, a, xid);
}
else {
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title2, item_name, group2,
- spmin + pos, spmax + pos, out + pos, outsize + pos,
- svg_p, record_hdr);
+ displayed = draw_activity_graphs(a->g_nr, g_type,
+ title, g_title2, item_name, group2,
+ spmin + pos, spmax + pos, out + pos, outsize + pos,
+ svg_p, record_hdr, i, a, xid);
+ }
+ if (displayed) {
+ xid++;
}
}
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
struct stats_io
*sic = (struct stats_io *) a->buf[curr],
*sip = (struct stats_io *) a->buf[!curr];
- int group[] = {3, 2};
+ int group[] = {4, 3};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
char *title[] = {"I/O and transfer rate statistics (1)", "I/O and transfer rate statistics (2)"};
- char *g_title[] = {"tps", "rtps", "wtps",
- "bread/s", "bwrtn/s"};
- int g_fields[] = {0, 1, 2, 3, 4};
+ char *g_title[] = {"tps", "rtps", "wtps", "dtps",
+ "bread/s", "bwrtn/s", "bdscd/s"};
+ /*
+ * tps:0, rtps:1, wtps:2, dtps:3, bread/s:4, bwrtn/s:5, bdscd/s:6
+ * g_fields[]:
+ * dk_drive=0
+ * dk_drive_rio:1
+ * dk_drive_wio:2
+ * dk_drive_rblk:4
+ * dk_drive_wblk:5
+ * dk_drive_dio:3
+ * dk_drive_dblk:6
+ */
+ int g_fields[] = {0, 1, 2, 4, 5, 3, 6};
static double *spmin, *spmax;
static char **out;
static int *outsize;
* Allocate arrays that will contain the graphs data
* and the min/max values.
*/
- out = allocate_graph_lines(5, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(7, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
sic->dk_drive_wio < sip->dk_drive_wio ? 0.0 :
S_VALUE(sip->dk_drive_wio, sic->dk_drive_wio, itv),
out + 2, outsize + 2, svg_p->restart);
+ /* dtps */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ sic->dk_drive_dio < sip->dk_drive_dio ? 0.0 :
+ S_VALUE(sip->dk_drive_dio, sic->dk_drive_dio, itv),
+ out + 3, outsize + 3, svg_p->restart);
/* bread/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
sic->dk_drive_rblk < sip->dk_drive_rblk ? 0.0 :
S_VALUE(sip->dk_drive_rblk, sic->dk_drive_rblk, itv),
- out + 3, outsize + 3, svg_p->restart);
+ out + 4, outsize + 4, svg_p->restart);
/* bwrtn/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
sic->dk_drive_wblk < sip->dk_drive_wblk ? 0.0 :
S_VALUE(sip->dk_drive_wblk, sic->dk_drive_wblk, itv),
- out + 4, outsize + 4, svg_p->restart);
+ out + 5, outsize + 5, svg_p->restart);
+ /* bdscd/s */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ sic->dk_drive_dblk < sip->dk_drive_dblk ? 0.0 :
+ S_VALUE(sip->dk_drive_dblk, sic->dk_drive_dblk, itv),
+ out + 6, outsize + 6, svg_p->restart);
}
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
static double *spmin, *spmax;
static char **out;
static int *outsize;
+ static int xid = 0;
double tval;
int i;
+ unsigned long long nousedmem;
if (action & F_BEGIN) {
/*
save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
itv, spmin, spmax, g_fields);
/* Compute %memused min/max values */
- tval = smc->tlmkb ? SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0;
+ nousedmem = smc->frmkb + smc->bufkb + smc->camkb + smc->slabkb;
+ if (nousedmem > smc->tlmkb) {
+ nousedmem = smc->tlmkb;
+ }
+ tval = smc->tlmkb ? SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0;
if (tval > *(spmax + 3)) {
*(spmax + 3) = tval;
}
*(spmin + 20) = tval;
}
/* Compute memused min/max values in MB */
- tval = ((double) (smc->tlmkb - smc->frmkb)) / 1024;
+ tval = ((double) (smc->tlmkb - nousedmem)) / 1024;
if (tval > *(spmax + 2)) {
*(spmax + 2) = tval;
}
out, outsize, svg_p->restart);
/* MBmemused */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
- ((double) (smc->tlmkb - smc->frmkb)) / 1024,
+ ((double) (smc->tlmkb - nousedmem)) / 1024,
out + 2, outsize + 2, svg_p->restart);
/* MBavail */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
brappend(record_hdr->ust_time - svg_p->ust_time_ref,
0.0,
smc->tlmkb ?
- SP_VALUE(smc->frmkb, smc->tlmkb, smc->tlmkb) : 0.0,
+ SP_VALUE(nousedmem, smc->tlmkb, smc->tlmkb) : 0.0,
out + 3, outsize + 3, svg_p->dt);
/* %commit */
brappend(record_hdr->ust_time - svg_p->ust_time_ref,
}
if (DISPLAY_MEMORY(a->opt_flags)) {
- draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
- g_type1, title1, g_title1, NULL, group1,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ if (draw_activity_graphs(DISPLAY_MEM_ALL(a->opt_flags) ? 6 : 5,
+ g_type1, title1, g_title1, NULL, group1,
+ spmin, spmax, out, outsize, svg_p, record_hdr,
+ FALSE, a, xid)) {
+ xid++;
+ }
}
if (DISPLAY_SWAP(a->opt_flags)) {
draw_activity_graphs(3, g_type2, title2, g_title2, NULL, group2,
spmin + 16, spmax + 16, out + 16, outsize + 16,
- svg_p, record_hdr);
+ svg_p, record_hdr, FALSE, a, xid);
}
/* Free remaining structures */
*skc = (struct stats_ktables *) a->buf[curr];
int group[] = {3, 1};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"Kernel tables (1)", "Kernel tables (2)"};
+ char *title[] = {"Kernel tables statistics (1)", "Kernel tables statistics (2)"};
char *g_title[] = {"~dentunusd", "~file-nr", "~inode-nr",
"~pty-nr"};
int g_fields[] = {1, 2, 0, 3};
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
*sqc = (struct stats_queue *) a->buf[curr];
int group[] = {2, 1, 3};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"Queue length", "Task list", "Load average"};
+ char *title[] = {"Queue length", "Task list statistics", "Load average statistics"};
char *g_title[] = {"~runq-sz", "~blocked",
"~plist-sz",
"ldavg-1", "ldavg-5", "ldavg-15"};
*(spmin + 5) /= 100; *(spmax + 5) /= 100;
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define DISK_ARRAY_SZ 9
__print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
struct stats_disk *sdc, *sdp, sdpzero;
struct ext_disk_stats xds;
- int group[] = {1, 2, 2, 2, 1};
+ int group[] = {1, 3, 2, 1, 1};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_LINE_GRAPH, SVG_BAR_GRAPH};
- char *title[] = {"Disk statistics (1)", "Disk statistics (2)",
- "Disk statistics (3)", "Disk statistics (4)",
- "Disk statistics (5)"};
+ char *title[] = {"Block devices statistics (1)", "Block devices statistics (2)",
+ "Block devices statistics (3)", "Block devices statistics (4)",
+ "Block devices statistics (5)"};
char *g_title[] = {"tps",
- "rkB/s", "wkB/s",
+ "rkB/s", "wkB/s", "dkB/s",
"areq-sz", "aqu-sz",
- "await", "svctm",
+ "await",
"%util"};
int g_fields[] = {0, 1, 2};
unsigned int local_types_nr[] = {1, 0, 0};
static double *spmin, *spmax;
static char **out;
static int *outsize;
- char *item_name, *persist_dev_name;
- double rkB, wkB, aqusz;
+ char *dev_name, *item_name;
+ double rkB, wkB, dkB, aqusz;
int i, j, k, pos, restart, *unregistered;
if (action & F_BEGIN) {
* Allocate arrays (#0..7) that will contain the graphs data
* and the min/max values.
* Also allocate one additional array (#8) for each disk device:
- * spmax + 8 will contain the device major number,
- * spmin + 8 will contain the device minor number,
+ * out + 8 will contain the device name (WWN id, pretty name or devm-n),
* outsize + 8 will contain a positive value (TRUE) if the device
* has either still not been registered, or has been unregistered.
*/
- out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(DISK_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
memset(&sdpzero, 0, STATS_DISK_SIZE);
- restart = svg_p->restart;
/*
* Mark previously registered devices as now
* possibly unregistered for all graphs.
*/
- for (k = 0; k < svg_p->nr_max; k++) {
- unregistered = outsize + k * 9 + 8;
+ for (k = 0; k < a->item_list_sz; k++) {
+ unregistered = outsize + k * DISK_ARRAY_SZ + 8;
if (*unregistered == FALSE) {
*unregistered = MAYBE;
}
/* For each device structure */
for (i = 0; i < a->nr[curr]; i++) {
sdc = (struct stats_disk *) ((char *) a->buf[curr] + i * a->msize);
+ restart = svg_p->restart;
+
+ /* Get device name */
+ dev_name = get_device_name(sdc->major, sdc->minor, sdc->wwn, sdc->part_nr,
+ DISPLAY_PRETTY(flags), DISPLAY_PERSIST_NAME_S(flags),
+ USE_STABLE_ID(flags), NULL);
+
+ if (a->item_list != NULL) {
+ /* A list of devices has been entered on the command line */
+ if (!search_list_item(a->item_list, dev_name))
+ /* Device not found */
+ continue;
+ }
/* Look for corresponding graph */
- for (k = 0; k < svg_p->nr_max; k++) {
- if ((sdc->major == *(spmax + k * 9 + 8)) &&
- (sdc->minor == *(spmin + k * 9 + 8)))
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * DISK_ARRAY_SZ + 8);
+ if (!strcmp(dev_name, item_name))
/* Graph found! */
break;
}
- if (k == svg_p->nr_max) {
+ if (k == a->item_list_sz) {
/* Graph not found: Look for first free entry */
- for (k = 0; k < svg_p->nr_max; k++) {
- if (*(spmax + k * 9 + 8) == -DBL_MAX)
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * DISK_ARRAY_SZ + 8);
+ if (!strcmp(item_name, ""))
break;
}
- if (k == svg_p->nr_max) {
- /* No free graph entry: Extend all buffers */
- reallocate_all_graph_lines(svg_p->nr_max,
- &out, &outsize, &spmin, &spmax);
- svg_p->nr_max *= 2;
+ if (k == a->item_list_sz) {
+ /* No free graph entry: Ignore it (should never happen) */
+#ifdef DEBUG
+ fprintf(stderr, "%s: Name=%s major=%d minor=%d\n",
+ __FUNCTION__, dev_name, sdc->major, sdc->minor);
+#endif
+ continue;
}
}
- pos = k * 9;
+ pos = k * DISK_ARRAY_SZ;
unregistered = outsize + pos + 8;
- j = check_disk_reg(a, curr, !curr, i);
- if (j < 0) {
- /* This is a newly registered interface. Previous stats are zero */
- sdp = &sdpzero;
- }
- else {
- sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
- }
-
/*
* If current device was marked as previously unregistered,
* then set restart variable to TRUE so that the graph will be
}
*unregistered = FALSE;
- if (*(spmax + pos + 8) == -DBL_MAX) {
- /* Save device major and minor numbers (if not already done) */
- *(spmax + pos + 8) = sdc->major;
- *(spmin + pos + 8) = sdc->minor;
+ item_name = *(out + pos + 8);
+ if (!item_name[0]) {
+ /* Save device name (WWN id or pretty name) if not already done */
+ strncpy(item_name, dev_name, CHUNKSIZE);
+ item_name[CHUNKSIZE - 1] = '\0';
+ }
+
+ j = check_disk_reg(a, curr, !curr, i);
+ if (j < 0) {
+ /* This is a newly registered interface. Previous stats are zero */
+ sdp = &sdpzero;
+ restart = TRUE;
+ }
+ else {
+ sdp = (struct stats_disk *) ((char *) a->buf[!curr] + j * a->msize);
}
/* Check for min/max values */
rkB = S_VALUE(sdp->rd_sect, sdc->rd_sect, itv) / 2;
wkB = S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2;
+ dkB = S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2;
if (rkB < *(spmin + pos + 1)) {
*(spmin + pos + 1) = rkB;
}
if (wkB > *(spmax + pos + 2)) {
*(spmax + pos + 2) = wkB;
}
+ if (dkB < *(spmin + pos + 3)) {
+ *(spmin + pos + 3) = dkB;
+ }
+ if (dkB > *(spmax + pos + 3)) {
+ *(spmax + pos + 3) = dkB;
+ }
compute_ext_disk_stats(sdc, sdp, itv, &xds);
- if ((xds.arqsz / 2) < *(spmin + pos + 3)) {
- *(spmin + pos + 3) = xds.arqsz / 2;
+ if ((xds.arqsz / 2) < *(spmin + pos + 4)) {
+ *(spmin + pos + 4) = xds.arqsz / 2;
}
- if ((xds.arqsz / 2) > *(spmax + pos + 3)) {
- *(spmax + pos + 3) = xds.arqsz / 2;
+ if ((xds.arqsz / 2) > *(spmax + pos + 4)) {
+ *(spmax + pos + 4) = xds.arqsz / 2;
}
aqusz = S_VALUE(sdp->rq_ticks, sdc->rq_ticks, itv) / 1000.0;
- if (aqusz < *(spmin + pos + 4)) {
- *(spmin + pos + 4) = aqusz;
- }
- if (aqusz > *(spmax + pos + 4)) {
- *(spmax + pos + 4) = aqusz;
+ if (aqusz < *(spmin + pos + 5)) {
+ *(spmin + pos + 5) = aqusz;
}
- if (xds.await < *(spmin + pos + 5)) {
- *(spmin + pos + 5) = xds.await;
+ if (aqusz > *(spmax + pos + 5)) {
+ *(spmax + pos + 5) = aqusz;
}
- if (xds.await > *(spmax + pos + 5)) {
- *(spmax + pos + 5) = xds.await;
+ if (xds.await < *(spmin + pos + 6)) {
+ *(spmin + pos + 6) = xds.await;
}
- if (xds.svctm < *(spmin + pos + 6)) {
- *(spmin + pos + 6) = xds.svctm;
- }
- if (xds.svctm > *(spmax + pos + 6)) {
- *(spmax + pos + 6) = xds.svctm;
+ if (xds.await > *(spmax + pos + 6)) {
+ *(spmax + pos + 6) = xds.await;
}
if ((xds.util / 10.0) < *(spmin + pos + 7)) {
*(spmin + pos + 7) = xds.util / 10.0;
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
S_VALUE(sdp->wr_sect, sdc->wr_sect, itv) / 2,
out + pos + 2, outsize + pos + 2, restart);
+ /* dkB/s */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ S_VALUE(sdp->dc_sect, sdc->dc_sect, itv) / 2,
+ out + pos + 3, outsize + pos + 3, restart);
/* areq-sz */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
xds.arqsz / 2,
- out + pos + 3, outsize + pos + 3, restart);
+ out + pos + 4, outsize + pos + 4, restart);
/* aqu-sz */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
aqusz,
- out + pos + 4, outsize + pos + 4, restart);
+ out + pos + 5, outsize + pos + 5, restart);
/* await */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
xds.await,
- out + pos + 5, outsize + pos + 5, restart);
- /* svctm */
- lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
- xds.svctm,
out + pos + 6, outsize + pos + 6, restart);
/* %util */
brappend(record_hdr->ust_time - svg_p->ust_time_ref,
}
/* Mark devices not seen here as now unregistered */
- for (k = 0; k < svg_p->nr_max; k++) {
- unregistered = outsize + k * 9 + 8;
+ for (k = 0; k < a->item_list_sz; k++) {
+ unregistered = outsize + k * DISK_ARRAY_SZ + 8;
if (*unregistered != FALSE) {
*unregistered = TRUE;
}
}
if (action & F_END) {
- for (i = 0; i < svg_p->nr_max; i++) {
+ int xid = 0;
+
+ for (i = 0; i < a->item_list_sz; i++) {
/* Check if there is something to display */
- pos = i * 9;
+ pos = i * DISK_ARRAY_SZ;
if (!**(out + pos))
continue;
- item_name = NULL;
- persist_dev_name = NULL;
-
- if (DISPLAY_PERSIST_NAME_S(flags)) {
- persist_dev_name = get_persistent_name_from_pretty(get_devname(*(spmax + pos + 8),
- *(spmin + pos + 8),
- TRUE));
- }
- if (persist_dev_name) {
- item_name = persist_dev_name;
- }
- else {
- if ((USE_PRETTY_OPTION(flags)) && (*(spmax + pos + 8) == dm_major)) {
- item_name = transform_devmapname(*(spmax + pos + 8), *(spmin + pos + 8));
- }
-
- if (!item_name) {
- item_name = get_devname(*(spmax + pos + 8), *(spmin + pos + 8),
- USE_PRETTY_OPTION(flags));
- }
+ item_name = *(out + pos + 8);
+ if (draw_activity_graphs(a->g_nr, g_type,
+ title, g_title, item_name, group,
+ spmin + pos, spmax + pos, out + pos, outsize + pos,
+ svg_p, record_hdr, FALSE, a, xid)) {
+ xid++;
}
-
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title, item_name, group,
- spmin + pos, spmax + pos, out + pos, outsize + pos,
- svg_p, record_hdr);
}
/* Free remaining structures */
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define NET_DEV_ARRAY_SZ 9
__print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
int group[] = {2, 2, 3, 1};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_BAR_GRAPH};
- char *title[] = {"Network statistics (1)", "Network statistics (2)",
- "Network statistics (3)", "Network statistics (4)"};
+ char *title[] = {"Network interfaces statistics (1)", "Network interfaces statistics (2)",
+ "Network interfaces statistics (3)", "Network interfaces statistics (4)"};
char *g_title[] = {"rxpck/s", "txpck/s",
"rxkB/s", "txkB/s",
"rxcmp/s", "txcmp/s", "rxmcst/s",
* outsize + 8 will contain a positive value (TRUE) if the interface
* has either still not been registered, or has been unregistered.
*/
- out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(NET_DEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
memset(&sndzero, 0, STATS_NET_DEV_SIZE);
- restart = svg_p->restart;
/*
* Mark previously registered interfaces as now
* possibly unregistered for all graphs.
*/
- for (k = 0; k < svg_p->nr_max; k++) {
- unregistered = outsize + k * 9 + 8;
+ for (k = 0; k < a->item_list_sz; k++) {
+ unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
if (*unregistered == FALSE) {
*unregistered = MAYBE;
}
/* For each network interfaces structure */
for (i = 0; i < a->nr[curr]; i++) {
sndc = (struct stats_net_dev *) ((char *) a->buf[curr] + i * a->msize);
+ restart = svg_p->restart;
+
+ if (a->item_list != NULL) {
+ /* A list of devices has been entered on the command line */
+ if (!search_list_item(a->item_list, sndc->interface))
+ /* Device not found */
+ continue;
+ }
/* Look for corresponding graph */
- for (k = 0; k < svg_p->nr_max; k++) {
- item_name = *(out + k * 9 + 8);
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
if (!strcmp(sndc->interface, item_name))
/* Graph found! */
break;
}
- if (k == svg_p->nr_max) {
+ if (k == a->item_list_sz) {
/* Graph not found: Look for first free entry */
- for (k = 0; k < svg_p->nr_max; k++) {
- item_name = *(out + k * 9 + 8);
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * NET_DEV_ARRAY_SZ + 8);
if (!strcmp(item_name, ""))
break;
}
- if (k == svg_p->nr_max) {
- /* No free graph entry: Extend all buffers */
- reallocate_all_graph_lines(svg_p->nr_max,
- &out, &outsize, &spmin, &spmax);
- svg_p->nr_max *= 2;
+ if (k == a->item_list_sz) {
+ /* No free graph entry: Ignore it (should never happen) */
+#ifdef DEBUG
+ fprintf(stderr, "%s: Name=%s\n",
+ __FUNCTION__, sndc->interface);
+#endif
+ continue;
}
}
-
- pos = k * 9;
+ pos = k * NET_DEV_ARRAY_SZ;
unregistered = outsize + pos + 8;
j = check_net_dev_reg(a, curr, !curr, i);
if (j < 0) {
/* This is a newly registered interface. Previous stats are zero */
sndp = &sndzero;
+ restart = TRUE;
}
else {
sndp = (struct stats_net_dev *) ((char *) a->buf[!curr] + j * a->msize);
}
*unregistered = FALSE;
+ item_name = *(out + pos + 8);
if (!item_name[0]) {
/* Save network interface name (if not already done) */
strncpy(item_name, sndc->interface, CHUNKSIZE);
}
/* Mark interfaces not seen here as now unregistered */
- for (k = 0; k < svg_p->nr_max; k++) {
- unregistered = outsize + k * 9 + 8;
+ for (k = 0; k < a->item_list_sz; k++) {
+ unregistered = outsize + k * NET_DEV_ARRAY_SZ + 8;
if (*unregistered != FALSE) {
*unregistered = TRUE;
}
}
if (action & F_END) {
- for (i = 0; i < svg_p->nr_max; i++) {
+ int xid = 0;
+
+ for (i = 0; i < a->item_list_sz; i++) {
/*
* Check if there is something to display.
* Don't test sndc->interface because maybe the network
* interface has been registered later.
*/
- pos = i * 9;
+ pos = i * NET_DEV_ARRAY_SZ;
if (!**(out + pos))
continue;
*(spmax + pos + 3) /= 1024;
item_name = *(out + pos + 8);
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title, item_name, group,
- spmin + pos, spmax + pos, out + pos, outsize + pos,
- svg_p, record_hdr);
+ if (draw_activity_graphs(a->g_nr, g_type,
+ title, g_title, item_name, group,
+ spmin + pos, spmax + pos, out + pos, outsize + pos,
+ svg_p, record_hdr, FALSE, a, xid)) {
+ xid++;
+ }
}
/* Free remaining structures */
/*
***************************************************************************
- * Display network interface errors statistics in SVG.
+ * Display network interfaces errors statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define NET_EDEV_ARRAY_SZ 10
__print_funct_t svg_print_net_edev_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
int group[] = {2, 2, 2, 3};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_LINE_GRAPH};
- char *title[] = {"Network errors statistics (1)", "Network errors statistics (2)",
- "Network errors statistics (3)", "Network errors statistics (4)"};
+ char *title[] = {"Network interfaces errors statistics (1)", "Network interfaces errors statistics (2)",
+ "Network interfaces errors statistics (3)", "Network interfaces errors statistics (4)"};
char *g_title[] = {"rxerr/s", "txerr/s",
"rxdrop/s", "txdrop/s",
"rxfifo/s", "txfifo/s",
* outsize + 9 will contain a positive value (TRUE) if the interface
* has either still not been registered, or has been unregistered.
*/
- out = allocate_graph_lines(10 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(NET_EDEV_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
memset(&snedzero, 0, STATS_NET_EDEV_SIZE);
- restart = svg_p->restart;
/*
* Mark previously registered interfaces as now
* possibly unregistered for all graphs.
*/
- for (k = 0; k < svg_p->nr_max; k++) {
- unregistered = outsize + k * 10 + 9;
+ for (k = 0; k < a->item_list_sz; k++) {
+ unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
if (*unregistered == FALSE) {
*unregistered = MAYBE;
}
/* For each network interfaces structure */
for (i = 0; i < a->nr[curr]; i++) {
snedc = (struct stats_net_edev *) ((char *) a->buf[curr] + i * a->msize);
- if (!strcmp(snedc->interface, ""))
- /* Empty structure: This is the end of the list */
- break;
+ restart = svg_p->restart;
+
+ if (a->item_list != NULL) {
+ /* A list of devices has been entered on the command line */
+ if (!search_list_item(a->item_list, snedc->interface))
+ /* Device not found */
+ continue;
+ }
/* Look for corresponding graph */
- for (k = 0; k < svg_p->nr_max; k++) {
- item_name = *(out + k * 10 + 9);
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
if (!strcmp(snedc->interface, item_name))
/* Graph found! */
break;
}
- if (k == svg_p->nr_max) {
+ if (k == a->item_list_sz) {
/* Graph not found: Look for first free entry */
- for (k = 0; k < svg_p->nr_max; k++) {
- item_name = *(out + k * 10 + 9);
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * NET_EDEV_ARRAY_SZ + 9);
if (!strcmp(item_name, ""))
break;
}
- if (k == svg_p->nr_max) {
- /* No free graph entry: Extend all buffers */
- reallocate_all_graph_lines(svg_p->nr_max,
- &out, &outsize, &spmin, &spmax);
- svg_p->nr_max *= 2;
+ if (k == a->item_list_sz) {
+ /* No free graph entry: Ignore it (should never happen) */
+#ifdef DEBUG
+ fprintf(stderr, "%s: Name=%s\n",
+ __FUNCTION__, snedc->interface);
+#endif
+ continue;
}
}
- pos = k * 10;
+ pos = k * NET_EDEV_ARRAY_SZ;
unregistered = outsize + pos + 9;
j = check_net_edev_reg(a, curr, !curr, i);
if (j < 0) {
/* This is a newly registered interface. Previous stats are zero */
snedp = &snedzero;
+ restart = TRUE;
}
else {
snedp = (struct stats_net_edev *) ((char *) a->buf[!curr] + j * a->msize);
}
*unregistered = FALSE;
+ item_name = *(out + pos + 9);
if (!item_name[0]) {
/* Save network interface name (if not already done) */
strncpy(item_name, snedc->interface, CHUNKSIZE);
}
/* Mark interfaces not seen here as now unregistered */
- for (k = 0; k < svg_p->nr_max; k++) {
- unregistered = outsize + k * 10 + 9;
+ for (k = 0; k < a->item_list_sz; k++) {
+ unregistered = outsize + k * NET_EDEV_ARRAY_SZ + 9;
if (*unregistered != FALSE) {
*unregistered = TRUE;
}
}
if (action & F_END) {
- for (i = 0; i < svg_p->nr_max; i++) {
+ int xid = 0;
+
+ for (i = 0; i < a->item_list_sz; i++) {
/*
* Check if there is something to display.
* Don't test snedc->interface because maybe the network
* interface has been registered later.
*/
- pos = i * 10;
+ pos = i * NET_EDEV_ARRAY_SZ;
if (!**(out + pos))
continue;
item_name = *(out + pos + 9);
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title, item_name, group,
- spmin + pos, spmax + pos, out + pos, outsize + pos,
- svg_p, record_hdr);
+ if (draw_activity_graphs(a->g_nr, g_type,
+ title, g_title, item_name, group,
+ spmin + pos, spmax + pos, out + pos, outsize + pos,
+ svg_p, record_hdr, FALSE, a, xid)) {
+ xid++;
+ }
}
/* Free remaining structures */
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display network socket statistics in SVG.
+ * Display socket statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
*snsc = (struct stats_net_sock *) a->buf[curr];
int group[] = {1, 5};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"IPv4 network sockets (1)", "IPv4 network sockets (2)"};
+ char *title[] = {"IPv4 sockets statistics (1)", "IPv4 sockets statistics (2)"};
char *g_title[] = {"~totsck",
"~tcpsck", "~udpsck", "~rawsck", "~ip-frag", "~tcp-tw"};
int g_fields[] = {0, 1, 5, 2, 3, 4};
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display IPv4 network statistics in SVG.
+ * Display IPv4 traffic statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
*snip = (struct stats_net_ip *) a->buf[!curr];
int group[] = {4, 2, 2};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"IPv4 network statistics (1)", "IPv4 network statistics (2)", "IPv4 network statistics (3)"};
+ char *title[] = {"IPv4 traffic statistics (1)", "IPv4 traffic statistics (2)", "IPv4 traffic statistics (3)"};
char *g_title[] = {"irec/s", "fwddgm/s", "idel/s", "orq/s",
"asmrq/s", "asmok/s",
"fragok/s", "fragcrt/s"};
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display IPv4 network errors statistics in SVG.
+ * Display IPv4 traffic errors statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
*sneip = (struct stats_net_eip *) a->buf[!curr];
int group[] = {3, 2, 3};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"IPv4 network errors statistics (1)", "IPv4 network errors statistics (2)",
- "IPv4 network errors statistics (3)"};
+ char *title[] = {"IPv4 traffic errors statistics (1)", "IPv4 traffic errors statistics (2)",
+ "IPv4 traffic errors statistics (3)"};
char *g_title[] = {"ihdrerr/s", "iadrerr/s", "iukwnpr/s",
"idisc/s", "odisc/s",
"onort/s", "asmf/s", "fragf/s"};
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display ICMPv4 network statistics in SVG.
+ * Display ICMPv4 traffic statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
int group[] = {2, 4, 4, 4};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_LINE_GRAPH};
- char *title[] = {"ICMPv4 network statistics (1)", "ICMPv4 network statistics (2)",
- "ICMPv4 network statistics (3)", "ICMPv4 network statistics (4)"};
+ char *title[] = {"ICMPv4 traffic statistics (1)", "ICMPv4 traffic statistics (2)",
+ "ICMPv4 traffic statistics (3)", "ICMPv4 traffic statistics (4)"};
char *g_title[] = {"imsg/s", "omsg/s",
"iech/s", "iechr/s", "oech/s", "oechr/s",
"itm/s", "itmr/s", "otm/s", "otmr/s",
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display ICMPv4 network errors statistics in SVG.
+ * Display ICMPv4 traffic errors statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
int group[] = {2, 2, 2, 2, 2, 2};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"ICMPv4 network errors statistics (1)", "ICMPv4 network errors statistics (2)",
- "ICMPv4 network errors statistics (3)", "ICMPv4 network errors statistics (4)",
- "ICMPv4 network errors statistics (5)", "ICMPv4 network errors statistics (6)"};
+ char *title[] = {"ICMPv4 traffic errors statistics (1)", "ICMPv4 traffic errors statistics (2)",
+ "ICMPv4 traffic errors statistics (3)", "ICMPv4 traffic errors statistics (4)",
+ "ICMPv4 traffic errors statistics (5)", "ICMPv4 traffic errors statistics (6)"};
char *g_title[] = {"ierr/s", "oerr/s",
"idstunr/s", "odstunr/s",
"itmex/s", "otmex/s",
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display TCPv4 network statistics in SVG.
+ * Display TCPv4 traffic statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
*sntp = (struct stats_net_tcp *) a->buf[!curr];
int group[] = {2, 2};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"TCPv4 network statistics (1)", "TCPv4 network statistics (2)"};
+ char *title[] = {"TCPv4 traffic statistics (1)", "TCPv4 traffic statistics (2)"};
char *g_title[] = {"active/s", "passive/s",
"iseg/s", "oseg/s"};
int g_fields[] = {0, 1, 2, 3};
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display TCPv4 network errors statistics in SVG.
+ * Display TCPv4 traffic errors statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
*snetp = (struct stats_net_etcp *) a->buf[!curr];
int group[] = {2, 3};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"TCPv4 network errors statistics (1)", "TCPv4 network errors statistics (2)"};
+ char *title[] = {"TCPv4 traffic errors statistics (1)", "TCPv4 traffic errors statistics (2)"};
char *g_title[] = {"atmptf/s", "estres/s",
"retrans/s", "isegerr/s", "orsts/s"};
int g_fields[] = {0, 1, 2, 3, 4};
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display UDPv4 network statistics in SVG.
+ * Display UDPv4 traffic statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
*snup = (struct stats_net_udp *) a->buf[!curr];
int group[] = {2, 2};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"UDPv4 network statistics (1)", "UDPv4 network statistics (2)"};
+ char *title[] = {"UDPv4 traffic statistics (1)", "UDPv4 traffic statistics (2)"};
char *g_title[] = {"idgm/s", "odgm/s",
"noport/s", "idgmerr/s"};
int g_fields[] = {0, 1, 2, 3};
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display IPV6 network socket statistics in SVG.
+ * Display IPV6 socket statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
*snsc = (struct stats_net_sock6 *) a->buf[curr];
int group[] = {4};
int g_type[] = {SVG_LINE_GRAPH};
- char *title[] = {"IPv6 network sockets"};
+ char *title[] = {"IPv6 sockets statistics"};
char *g_title[] = {"~tcp6sck", "~udp6sck", "~raw6sck", "~ip6-frag"};
int g_fields[] = {0, 1, 2, 3};
static double *spmin, *spmax;
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display IPv6 network statistics in SVG.
+ * Display IPv6 traffic statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
int group[] = {4, 2, 2, 2};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_LINE_GRAPH};
- char *title[] = {"IPv6 network statistics (1)", "IPv6 network statistics (2)",
- "IPv6 network statistics (3)", "IPv6 network statistics (4)"};
+ char *title[] = {"IPv6 traffic statistics (1)", "IPv6 traffic statistics (2)",
+ "IPv6 traffic statistics (3)", "IPv6 traffic statistics (4)"};
char *g_title[] = {"irec6/s", "fwddgm6/s", "idel6/s", "orq6/s",
"asmrq6/s", "asmok6/s",
"imcpck6/s", "omcpck6/s",
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display IPv6 network errors statistics in SVG.
+ * Display IPv6 traffic errors statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
int group[] = {4, 2, 2, 3};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_LINE_GRAPH};
- char *title[] = {"IPv6 network errors statistics (1)", "IPv6 network errors statistics (2)",
- "IPv6 network errors statistics (3)", "IPv6 network errors statistics (4)",
- "IPv6 network errors statistics (5)"};
+ char *title[] = {"IPv6 traffic errors statistics (1)", "IPv6 traffic errors statistics (2)",
+ "IPv6 traffic errors statistics (3)", "IPv6 traffic errors statistics (4)",
+ "IPv6 traffic errors statistics (5)"};
char *g_title[] = {"ihdrer6/s", "iadrer6/s", "iukwnp6/s", "i2big6/s",
"idisc6/s", "odisc6/s",
"inort6/s", "onort6/s",
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display ICMPv6 network statistics in SVG.
+ * Display ICMPv6 traffic statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
int group[] = {2, 3, 5, 3, 4};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"ICMPv6 network statistics (1)", "ICMPv6 network statistics (2)",
- "ICMPv6 network statistics (3)", "ICMPv6 network statistics (4)",
- "ICMPv6 network statistics (5)"};
+ char *title[] = {"ICMPv6 traffic statistics (1)", "ICMPv6 traffic statistics (2)",
+ "ICMPv6 traffic statistics (3)", "ICMPv6 traffic statistics (4)",
+ "ICMPv6 traffic statistics (5)"};
char *g_title[] = {"imsg6/s", "omsg6/s",
"iech6/s", "iechr6/s", "oechr6/s",
"igmbq6/s", "igmbr6/s", "ogmbr6/s", "igmbrd6/s", "ogmbrd6/s",
out + 12, outsize + 12, svg_p->restart);
/* inbsol6/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
- S_VALUE(snip->InNeighborSolicits6,snic->InNeighborSolicits6, itv),
+ S_VALUE(snip->InNeighborSolicits6, snic->InNeighborSolicits6, itv),
out + 13, outsize + 13, svg_p->restart);
/* onbsol6/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display ICMPv6 network errors statistics in SVG.
+ * Display ICMPv6 traffic errors statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
int group[] = {1, 2, 2, 2, 2, 2};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH,
SVG_LINE_GRAPH, SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"ICMPv6 network errors statistics (1)", "ICMPv6 network errors statistics (2)",
- "ICMPv6 network errors statistics (3)", "ICMPv6 network errors statistics (4)",
- "ICMPv6 network errors statistics (5)", "ICMPv6 network errors statistics (6)"};
+ char *title[] = {"ICMPv6 traffic errors statistics (1)", "ICMPv6 traffic errors statistics (2)",
+ "ICMPv6 traffic errors statistics (3)", "ICMPv6 traffic errors statistics (4)",
+ "ICMPv6 traffic errors statistics (5)", "ICMPv6 traffic errors statistics (6)"};
char *g_title[] = {"ierr6/s",
"idtunr6/s", "odtunr6/s",
"itmex6/s", "otmex6/s",
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
/*
***************************************************************************
- * Display UDPv6 network statistics in SVG.
+ * Display UDPv6 traffic statistics in SVG.
*
* IN:
* @a Activity structure with statistics.
*snup = (struct stats_net_udp6 *) a->buf[!curr];
int group[] = {2, 2};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
- char *title[] = {"UDPv6 network statistics (1)", "UDPv6 network statistics (2)"};
+ char *title[] = {"UDPv6 traffic statistics (1)", "UDPv6 traffic statistics (2)"};
char *g_title[] = {"idgm6/s", "odgm6/s",
"noport6/s", "idgmer6/s"};
int g_fields[] = {0, 1, 2, 3};
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
struct stats_pwr_cpufreq *spc, *spp;
int group[] = {1};
int g_type[] = {SVG_LINE_GRAPH};
- char *title[] = {"CPU frequency"};
+ char *title[] = {"CPU clock frequency"};
char *g_title[] = {"MHz"};
static double *spmin, *spmax;
static char **out;
static int *outsize;
- char item_name[8];
+ char item_name[16];
int i;
if (action & F_BEGIN) {
* Allocate arrays that will contain the graphs data
* and the min/max values.
*/
- out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
/* No */
continue;
+ /*
+ * Note: Don't skip offline CPU here as it is needed
+ * to make the graph go though 0.
+ */
+
/* MHz */
recappend(record_hdr->ust_time - svg_p->ust_time_ref,
((double) spp->cpufreq) / 100,
}
if (action & F_END) {
- for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
+ int xid = 0;
+
+ for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
/* Should current CPU (including CPU "all") be displayed? */
if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
strcpy(item_name, "all");
}
else {
+ /*
+ * If the maximum frequency reached by the CPU is 0, then
+ * the CPU has been offline on the whole period.
+ * => Don't display it.
+ */
+ if (*(spmax + i) == 0)
+ continue;
+
sprintf(item_name, "%d", i - 1);
}
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title, item_name, group,
- spmin + i, spmax + i, out + i, outsize + i,
- svg_p, record_hdr);
+ if (draw_activity_graphs(a->g_nr, g_type,
+ title, g_title, item_name, group,
+ spmin + i, spmax + i, out + i, outsize + i,
+ svg_p, record_hdr, i, a, xid)) {
+ xid++;
+ }
}
/* Free remaining structures */
struct stats_pwr_fan *spc, *spp;
int group[] = {1};
int g_type[] = {SVG_LINE_GRAPH};
- char *title[] = {"Fan speed"};
+ char *title[] = {"Fans speed"};
char *g_title[] = {"~rpm"};
static double *spmin, *spmax;
static char **out;
static int *outsize;
- char item_name[MAX_SENSORS_DEV_LEN + 8];
+ char item_name[MAX_SENSORS_DEV_LEN + 16];
int i;
if (action & F_BEGIN) {
* Allocate arrays that will contain the graphs data
* and the min/max values.
*/
- out = allocate_graph_lines(svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
}
if (action & F_END) {
- for (i = 0; i < svg_p->nr_max; i++) {
+ int xid = 0;
+
+ for (i = 0; i < a->item_list_sz; i++) {
spc = (struct stats_pwr_fan *) ((char *) a->buf[curr] + i * a->msize);
- snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
- item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
+ snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
+ item_name[sizeof(item_name) - 1] = '\0';
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title, item_name, group,
- spmin + i, spmax + i, out + i, outsize + i,
- svg_p, record_hdr);
+ if (draw_activity_graphs(a->g_nr, g_type,
+ title, g_title, item_name, group,
+ spmin + i, spmax + i, out + i, outsize + i,
+ svg_p, record_hdr, FALSE, a, xid)) {
+ xid++;
+ }
}
/* Free remaining structures */
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define TEMP_ARRAY_SZ 2
__print_funct_t svg_print_pwr_temp_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
struct stats_pwr_temp *spc;
int group[] = {1, 1};
int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
- char *title[] = {"Device temperature (1)",
- "Device temperature (2)"};
+ char *title[] = {"Devices temperature (1)",
+ "Devices temperature (2)"};
char *g_title[] = {"~degC",
"%temp"};
static double *spmin, *spmax;
static char **out;
static int *outsize;
- char item_name[MAX_SENSORS_DEV_LEN + 8];
+ char item_name[MAX_SENSORS_DEV_LEN + 16];
int i;
double tval;
* Allocate arrays that will contain the graphs data
* and the min/max values.
*/
- out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(TEMP_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
/* Look for min/max values */
- if (spc->temp < *(spmin + 2 * i)) {
- *(spmin + 2 * i) = spc->temp;
+ if (spc->temp < *(spmin + TEMP_ARRAY_SZ * i)) {
+ *(spmin + TEMP_ARRAY_SZ * i) = spc->temp;
}
- if (spc->temp > *(spmax + 2 * i)) {
- *(spmax + 2 * i) = spc->temp;
+ if (spc->temp > *(spmax + TEMP_ARRAY_SZ * i)) {
+ *(spmax + TEMP_ARRAY_SZ * i) = spc->temp;
}
tval = (spc->temp_max - spc->temp_min) ?
(spc->temp - spc->temp_min) / (spc->temp_max - spc->temp_min) * 100 :
0.0;
- if (tval < *(spmin + 2 * i + 1)) {
- *(spmin + 2 * i + 1) = tval;
+ if (tval < *(spmin + TEMP_ARRAY_SZ * i + 1)) {
+ *(spmin + TEMP_ARRAY_SZ * i + 1) = tval;
}
- if (tval > *(spmax + 2 * i + 1)) {
- *(spmax + 2 * i + 1) = tval;
+ if (tval > *(spmax + TEMP_ARRAY_SZ * i + 1)) {
+ *(spmax + TEMP_ARRAY_SZ * i + 1) = tval;
}
/* degC */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
(double) spc->temp,
- out + 2 * i, outsize + 2 * i, svg_p->restart);
+ out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i, svg_p->restart);
/* %temp */
brappend(record_hdr->ust_time - svg_p->ust_time_ref,
0.0, tval,
- out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
+ out + TEMP_ARRAY_SZ * i + 1, outsize + TEMP_ARRAY_SZ * i + 1, svg_p->dt);
}
}
if (action & F_END) {
- for (i = 0; i < svg_p->nr_max; i++) {
+ int xid = 0;
+
+ for (i = 0; i < a->item_list_sz; i++) {
spc = (struct stats_pwr_temp *) ((char *) a->buf[curr] + i * a->msize);
- snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
- item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
+ snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
+ item_name[sizeof(item_name) - 1] = '\0';
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title, item_name, group,
- spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
- svg_p, record_hdr);
+ if (draw_activity_graphs(a->g_nr, g_type,
+ title, g_title, item_name, group,
+ spmin + TEMP_ARRAY_SZ * i, spmax + TEMP_ARRAY_SZ * i,
+ out + TEMP_ARRAY_SZ * i, outsize + TEMP_ARRAY_SZ * i,
+ svg_p, record_hdr, FALSE, a, xid)) {
+ xid++;
+ }
}
/* Free remaining structures */
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define IN_ARRAY_SZ 2
__print_funct_t svg_print_pwr_in_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
struct stats_pwr_in *spc;
int group[] = {1, 1};
int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
- char *title[] = {"Voltage inputs (1)",
- "Voltage inputs (2)"};
+ char *title[] = {"Voltage inputs statistics (1)",
+ "Voltage inputs statistics (2)"};
char *g_title[] = {"inV",
"%in"};
static double *spmin, *spmax;
static char **out;
static int *outsize;
- char item_name[MAX_SENSORS_DEV_LEN + 8];
+ char item_name[MAX_SENSORS_DEV_LEN + 16];
int i;
double tval;
* Allocate arrays that will contain the graphs data
* and the min/max values.
*/
- out = allocate_graph_lines(2 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(IN_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
/* Look for min/max values */
- if (spc->in < *(spmin + 2 * i)) {
- *(spmin + 2 * i) = spc->in;
+ if (spc->in < *(spmin + IN_ARRAY_SZ * i)) {
+ *(spmin + IN_ARRAY_SZ * i) = spc->in;
}
- if (spc->in > *(spmax + 2 * i)) {
- *(spmax + 2 * i) = spc->in;
+ if (spc->in > *(spmax + IN_ARRAY_SZ * i)) {
+ *(spmax + IN_ARRAY_SZ * i) = spc->in;
}
tval = (spc->in_max - spc->in_min) ?
(spc->in - spc->in_min) / (spc->in_max - spc->in_min) * 100 :
0.0;
- if (tval < *(spmin + 2 * i + 1)) {
- *(spmin + 2 * i + 1) = tval;
+ if (tval < *(spmin + IN_ARRAY_SZ * i + 1)) {
+ *(spmin + IN_ARRAY_SZ * i + 1) = tval;
}
- if (tval > *(spmax + 2 * i + 1)) {
- *(spmax + 2 * i + 1) = tval;
+ if (tval > *(spmax + IN_ARRAY_SZ * i + 1)) {
+ *(spmax + IN_ARRAY_SZ * i + 1) = tval;
}
/* inV */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
(double) spc->in,
- out + 2 * i, outsize + 2 * i, svg_p->restart);
+ out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i, svg_p->restart);
/* %in */
brappend(record_hdr->ust_time - svg_p->ust_time_ref,
0.0, tval,
- out + 2 * i + 1, outsize + 2 * i + 1, svg_p->dt);
+ out + IN_ARRAY_SZ * i + 1, outsize + IN_ARRAY_SZ * i + 1, svg_p->dt);
}
}
if (action & F_END) {
- for (i = 0; i < svg_p->nr_max; i++) {
+ int xid = 0;
+
+ for (i = 0; i < a->item_list_sz; i++) {
spc = (struct stats_pwr_in *) ((char *) a->buf[curr] + i * a->msize);
- snprintf(item_name, MAX_SENSORS_DEV_LEN + 8, "%d: %s", i + 1, spc->device);
- item_name[MAX_SENSORS_DEV_LEN + 7] = '\0';
+ snprintf(item_name, sizeof(item_name), "%d: %s", i + 1, spc->device);
+ item_name[sizeof(item_name) - 1] = '\0';
- draw_activity_graphs(a->g_nr, g_type,
- title, g_title, item_name, group,
- spmin + 2 * i, spmax + 2 * i, out + 2 * i, outsize + 2 * i,
- svg_p, record_hdr);
+ if (draw_activity_graphs(a->g_nr, g_type,
+ title, g_title, item_name, group,
+ spmin + IN_ARRAY_SZ * i, spmax + IN_ARRAY_SZ * i,
+ out + IN_ARRAY_SZ * i, outsize + IN_ARRAY_SZ * i,
+ svg_p, record_hdr, FALSE, a, xid)) {
+ xid++;
+ }
}
/* Free remaining structures */
{
struct stats_huge
*smc = (struct stats_huge *) a->buf[curr];
- int group[] = {2, 1};
+ int group[] = {4, 1};
int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
char *title[] = {"Huge pages utilization (1)",
"Huge pages utilization (2)"};
- char *g_title[] = {"~kbhugfree", "~kbhugused",
+ char *g_title[] = {"~kbhugfree", "~kbhugused", "~kbhugrsvd", "~kbhugsurp",
"%hugused"};
- int g_fields[] = {0};
- unsigned int local_types_nr[] = {0, 1, 0};
+ int g_fields[] = {0, 5, 2, 3};
static double *spmin, *spmax;
static char **out;
static int *outsize;
/*
* Allocate arrays that will contain the graphs data
* and the min/max values.
+ * Allocate one additional array (#5) to save min/max
+ * values for tlhkb (unused).
*/
- out = allocate_graph_lines(3, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(6, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
/* Check for min/max values */
- save_extrema(local_types_nr, (void *) a->buf[curr], NULL,
+ save_extrema(a->gtypes_nr, (void *) a->buf[curr], NULL,
itv, spmin, spmax, g_fields);
if (smc->tlhkb - smc->frhkb < *(spmin + 1)) {
*(spmax + 1) = smc->tlhkb - smc->frhkb;
}
tval = smc->tlhkb ? SP_VALUE(smc->frhkb, smc->tlhkb, smc->tlhkb) : 0.0;
- if (tval < *(spmin + 2)) {
- *(spmin + 2) = tval;
+ if (tval < *(spmin + 4)) {
+ *(spmin + 4) = tval;
}
- if (tval > *(spmax + 2)) {
- *(spmax + 2) = tval;
+ if (tval > *(spmax + 4)) {
+ *(spmax + 4) = tval;
}
/* kbhugfree */
lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
(unsigned long long) smc->tlhkb - smc->frhkb,
out + 1, outsize + 1, svg_p->restart);
+ /* kbhugrsvd */
+ lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (unsigned long long) smc->rsvdhkb,
+ out + 2, outsize + 2, svg_p->restart);
+ /* kbhugsurp */
+ lniappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (unsigned long long) smc->surphkb,
+ out + 3, outsize + 3, svg_p->restart);
/* %hugused */
brappend(record_hdr->ust_time - svg_p->ust_time_ref,
0.0, tval,
- out + 2, outsize + 2, svg_p->dt);
+ out + 4, outsize + 4, svg_p->dt);
}
if (action & F_END) {
draw_activity_graphs(a->g_nr, g_type,
title, g_title, NULL, group,
- spmin, spmax, out, outsize, svg_p, record_hdr);
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define FS_ARRAY_SZ 8
__print_funct_t svg_print_filesystem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
int group[] = {2, 2, 2, 1};
int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH,
SVG_LINE_GRAPH, SVG_BAR_GRAPH};
- char *title[] = {"Filesystem statistics (1)", "Filesystem statistics (2)",
- "Filesystem statistics (3)", "Filesystem statistics (4)"};
+ char *title[] = {"Filesystems statistics (1)", "Filesystems statistics (2)",
+ "Filesystems statistics (3)", "Filesystems statistics (4)"};
char *g_title[] = {"~MBfsfree", "~MBfsused",
"%ufsused", "%fsused",
"Ifree/1000", "Iused/1000",
static double *spmin, *spmax;
static char **out;
static int *outsize;
- char *item_name = NULL;
+ char *dev_name, *item_name;
double tval;
int i, k, pos, restart;
/*
* Allocate arrays (#0..6) that will contain the graphs data
* and the min/max values.
- * Also allocate two additional arrays (#7..8) for each filesystem:
- * out + 7 will contain the filesystem name,
- * out + 8 will contain the mount point.
+ * Also allocate an additional arrays (#7) for each filesystem:
+ * out + 7 will contain the persistent or standard fs name, or mount point.
*/
- out = allocate_graph_lines(9 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(FS_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
for (i = 0; i < a->nr[curr]; i++) {
sfc = (struct stats_filesystem *) ((char *) a->buf[curr] + i * a->msize);
+ /* Get name to display (persistent or standard fs name, or mount point) */
+ dev_name = get_fs_name_to_display(a, flags, sfc);
+
+ if (a->item_list != NULL) {
+ /* A list of devices has been entered on the command line */
+ if (!search_list_item(a->item_list, dev_name))
+ /* Device not found */
+ continue;
+ }
+
/* Look for corresponding graph */
- for (k = 0; k < svg_p->nr_max; k++) {
- item_name = *(out + k * 9 + 7);
- if (!strcmp(sfc->fs_name, item_name))
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * FS_ARRAY_SZ + 7);
+ if (!strcmp(dev_name, item_name))
/* Graph found! */
break;
}
- if (k == svg_p->nr_max) {
+ if (k == a->item_list_sz) {
/* Graph not found: Look for first free entry */
- for (k = 0; k < svg_p->nr_max; k++) {
- item_name = *(out + k * 9 + 7);
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * FS_ARRAY_SZ + 7);
if (!strcmp(item_name, ""))
break;
}
- if (k == svg_p->nr_max) {
- /* No free graph entry: Extend all buffers */
- reallocate_all_graph_lines(svg_p->nr_max,
- &out, &outsize, &spmin, &spmax);
- svg_p->nr_max *= 2;
+ if (k == a->item_list_sz) {
+ /* No free graph entry: Ignore it (should never happen) */
+#ifdef DEBUG
+ fprintf(stderr, "%s: Name=%s\n",
+ __FUNCTION__, sfc->fs_name);
+#endif
+ continue;
}
}
- pos = k * 9;
+ pos = k * FS_ARRAY_SZ;
+ item_name = *(out + pos + 7);
if (!item_name[0]) {
/* Save filesystem name and mount point (if not already done) */
- strncpy(item_name, sfc->fs_name, CHUNKSIZE);
- item_name[CHUNKSIZE - 1] = '\0';
- item_name = *(out + pos + 8);
- strncpy(item_name, sfc->mountp, CHUNKSIZE);
+ strncpy(item_name, dev_name, CHUNKSIZE);
item_name[CHUNKSIZE - 1] = '\0';
}
}
if (action & F_END) {
+ int xid = 0;
- for (i = 0; i < svg_p->nr_max; i++) {
+ for (i = 0; i < a->item_list_sz; i++) {
/* Check if there is something to display */
- pos = i * 9;
+ pos = i * FS_ARRAY_SZ;
if (!**(out + pos))
continue;
- /* Conversion B -> MB and inodes/1000 */
+ /* Conversion B -> MiB and inodes/1000 */
for (k = 0; k < 2; k++) {
*(spmin + pos + k) /= (1024 * 1024);
*(spmax + pos + k) /= (1024 * 1024);
*(spmax + pos + 4 + k) /= 1000;
}
- if (DISPLAY_MOUNT(a->opt_flags)) {
- item_name = *(out + pos + 8);
- }
- else {
- item_name = *(out + pos + 7);
- }
+ item_name = *(out + pos + 7);
- draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
- spmin + pos, spmax + pos, out + pos, outsize + pos,
- svg_p, record_hdr);
+ if (draw_activity_graphs(a->g_nr, g_type, title, g_title, item_name, group,
+ spmin + pos, spmax + pos, out + pos, outsize + pos,
+ svg_p, record_hdr, FALSE, a, xid)) {
+ xid++;
+ }
}
/* Free remaining structures */
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define FC_ARRAY_SZ 5
__print_funct_t svg_print_fchost_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
- struct stats_fchost *sfcc, *sfcp;
+ struct stats_fchost *sfcc, *sfcp, sfczero;
int group[] = {2, 2};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
char *title[] = {"Fibre Channel HBA statistics (1)", "Fibre Channel HBA statistics (2)"};
* has either still not been registered, or has been unregistered
* (outsize + 4).
*/
- out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(FC_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
- restart = svg_p->restart;
+ memset(&sfczero, 0, sizeof(struct stats_fchost));
/*
* Mark previously registered interfaces as now
* possibly unregistered for all graphs.
*/
- for (k = 0; k < svg_p->nr_max; k++) {
- unregistered = outsize + k * 5 + 4;
+ for (k = 0; k < a->item_list_sz; k++) {
+ unregistered = outsize + k * FC_ARRAY_SZ + 4;
if (*unregistered == FALSE) {
*unregistered = MAYBE;
}
for (i = 0; i < a->nr[curr]; i++) {
found = FALSE;
+ sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
+ restart = svg_p->restart;
- if (a->nr[!curr] > 0) {
- sfcc = (struct stats_fchost *) ((char *) a->buf[curr] + i * a->msize);
-
- /* Look for corresponding graph */
- for (k = 0; k < svg_p->nr_max; k++) {
- item_name = *(out + k * 5 + 4);
- if (!strcmp(sfcc->fchost_name, item_name))
- /* Graph found! */
+ /* Look for corresponding graph */
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * FC_ARRAY_SZ + 4);
+ if (!strcmp(sfcc->fchost_name, item_name))
+ /* Graph found! */
+ break;
+ }
+ if (k == a->item_list_sz) {
+ /* Graph not found: Look for first free entry */
+ for (k = 0; k < a->item_list_sz; k++) {
+ item_name = *(out + k * FC_ARRAY_SZ + 4);
+ if (!strcmp(item_name, ""))
break;
}
- if (k == svg_p->nr_max) {
- /* Graph not found: Look for first free entry */
- for (k = 0; k < svg_p->nr_max; k++) {
- item_name = *(out + k * 5 + 4);
- if (!strcmp(item_name, ""))
- break;
- }
- if (k == svg_p->nr_max) {
- /* No free graph entry: Extend all buffers */
- reallocate_all_graph_lines(svg_p->nr_max,
- &out, &outsize, &spmin, &spmax);
- svg_p->nr_max *= 2;
- }
+ if (k == a->item_list_sz) {
+ /* No free graph entry: Ignore it (should never happen) */
+#ifdef DEBUG
+ fprintf(stderr, "%s: Name=%s\n",
+ __FUNCTION__, sfcc->fchost_name);
+#endif
+ continue;
}
+ }
- pos = k * 5;
- unregistered = outsize + pos + 4;
+ pos = k * FC_ARRAY_SZ;
+ unregistered = outsize + pos + 4;
+ if (a->nr[!curr] > 0) {
/* Look for corresponding structure in previous iteration */
j = i;
while (j != j0);
}
- if (!found)
- continue;
+ if (!found) {
+ /* This is a newly registered host */
+ sfcp = &sfczero;
+ restart = TRUE;
+ }
/*
* If current interface was marked as previously unregistered,
}
/* Mark interfaces not seen here as now unregistered */
- for (k = 0; k < svg_p->nr_max; k++) {
- unregistered = outsize + k * 5 + 4;
+ for (k = 0; k < a->item_list_sz; k++) {
+ unregistered = outsize + k * FC_ARRAY_SZ + 4;
if (*unregistered != FALSE) {
*unregistered = TRUE;
}
}
if (action & F_END) {
- for (i = 0; i < svg_p->nr_max; i++) {
+ for (i = 0; i < a->item_list_sz; i++) {
/* Check if there is something to display */
- pos = i * 5;
+ pos = i * FC_ARRAY_SZ;
if (!**(out + pos))
continue;
draw_activity_graphs(a->g_nr, g_type,
title, g_title, item_name, group,
spmin + pos, spmax + pos, out + pos, outsize + pos,
- svg_p, record_hdr);
+ svg_p, record_hdr, FALSE, a, i);
}
/* Free remaining structures */
* @record_hdr Pointer on record header of current stats sample.
***************************************************************************
*/
+#define SOFT_ARRAY_SZ 5
__print_funct_t svg_print_softnet_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
unsigned long long itv, struct record_header *record_hdr)
{
- struct stats_softnet *ssnc, *ssnp;
+ struct stats_softnet *ssnc, *ssnp, ssnczero;
int group[] = {2, 3};
int g_type[] = {SVG_LINE_GRAPH, SVG_LINE_GRAPH};
char *title[] = {"Software-based network processing statistics (1)",
static double *spmin, *spmax;
static char **out;
static int *outsize;
- char item_name[8];
- int i, pos;
+ char item_name[16];
+ unsigned char offline_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
+ int i, pos, restart;
if (action & F_BEGIN) {
/*
* Allocate arrays that will contain the graphs data
* and the min/max values.
*/
- out = allocate_graph_lines(5 * svg_p->nr_max, &outsize, &spmin, &spmax);
+ out = allocate_graph_lines(SOFT_ARRAY_SZ * a->item_list_sz, &outsize, &spmin, &spmax);
}
if (action & F_MAIN) {
- /* For each CPU */
- for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
+ memset(&ssnczero, 0, STATS_SOFTNET_SIZE);
- ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
- ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
+ /* @nr[curr] cannot normally be greater than @nr_ini */
+ if (a->nr[curr] > a->nr_ini) {
+ a->nr_ini = a->nr[curr];
+ }
+
+ /* Compute statistics for CPU "all" */
+ get_global_soft_statistics(a, !curr, curr, flags, offline_cpu_bitmap);
+
+ /* For each CPU */
+ for (i = 0; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
+ restart = svg_p->restart;
/* Should current CPU (including CPU "all") be displayed? */
if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
/* No */
continue;
- pos = i * 5;
+ ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
+ ssnp = (struct stats_softnet *) ((char *) a->buf[!curr] + i * a->msize);
+
+ /* Is current CPU marked offline? */
+ if (offline_cpu_bitmap[i >> 3] & (1 << (i & 0x07))) {
+ /*
+ * Yes and it doesn't follow a RESTART record.
+ * To add a discontinuity in graph, we simulate
+ * a RESTART mark.
+ */
+ restart = TRUE;
+ if (svg_p->restart) {
+ /*
+ * CPU is offline and it follows a real
+ * RESTART record. Ignore its current value
+ * (no previous sample).
+ */
+ ssnc = &ssnczero;
+ }
+ }
+ pos = i * SOFT_ARRAY_SZ;
/* Check for min/max values */
save_extrema(a->gtypes_nr, (void *) ssnc, (void *) ssnp,
/* total/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
S_VALUE(ssnp->processed, ssnc->processed, itv),
- out + pos, outsize + pos, svg_p->restart);
+ out + pos, outsize + pos, restart);
/* dropd/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
S_VALUE(ssnp->dropped, ssnc->dropped, itv),
- out + pos + 1, outsize + pos + 1, svg_p->restart);
+ out + pos + 1, outsize + pos + 1, restart);
/* squeezd/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
S_VALUE(ssnp->time_squeeze, ssnc->time_squeeze, itv),
- out + pos + 2, outsize + pos + 2, svg_p->restart);
+ out + pos + 2, outsize + pos + 2, restart);
/* rx_rps/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
S_VALUE(ssnp->received_rps, ssnc->received_rps, itv),
- out + pos + 3, outsize + pos + 3, svg_p->restart);
+ out + pos + 3, outsize + pos + 3, restart);
/* flw_lim/s */
lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
S_VALUE(ssnp->flow_limit, ssnc->flow_limit, itv),
- out + pos + 4, outsize + pos + 4, svg_p->restart);
+ out + pos + 4, outsize + pos + 4, restart);
}
}
if (action & F_END) {
- for (i = 0; (i < svg_p->nr_max) && (i < a->bitmap->b_size + 1); i++) {
+ for (i = 0; (i < a->item_list_sz) && (i < a->bitmap->b_size + 1); i++) {
/* Should current CPU (including CPU "all") be displayed? */
if (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))
/* No */
continue;
- pos = i * 5;
+ pos = i * SOFT_ARRAY_SZ;
if (!i) {
/* This is CPU "all" */
draw_activity_graphs(a->g_nr, g_type,
title, g_title, item_name, group,
spmin + pos, spmax + pos, out + pos, outsize + pos,
- svg_p, record_hdr);
+ svg_p, record_hdr, FALSE, a, i);
+ }
+
+ /* Free remaining structures */
+ free_graphs(out, outsize, spmin, spmax);
+ }
+}
+
+/*
+ ***************************************************************************
+ * Display pressure-stall CPU statistics in SVG.
+ *
+ * IN:
+ * @a Activity structure with statistics.
+ * @curr Index in array for current sample statistics.
+ * @action Action expected from current function.
+ * @svg_p SVG specific parameters: Current graph number (.@graph_no),
+ * flag indicating that a restart record has been previously
+ * found (.@restart) and time used for the X axis origin
+ * (@ust_time_ref).
+ * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
+ * @record_hdr Pointer on record header of current stats sample.
+ ***************************************************************************
+ */
+__print_funct_t svg_print_psicpu_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
+ unsigned long long itv, struct record_header *record_hdr)
+{
+ struct stats_psi_cpu
+ *psic = (struct stats_psi_cpu *) a->buf[curr],
+ *psip = (struct stats_psi_cpu *) a->buf[!curr];
+ int group[] = {3, 1};
+ int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH};
+ char *title[] = {"CPU pressure trends (some tasks)", "CPU stall time (some tasks)"};
+ char *g_title[] = {"%scpu-10", "%scpu-60", "%scpu-300",
+ "%scpu"};
+ static double *spmin, *spmax;
+ static char **out;
+ static int *outsize;
+ double tval;
+
+ if (action & F_BEGIN) {
+ /*
+ * Allocate arrays that will contain the graphs data
+ * and the min/max values.
+ */
+ out = allocate_graph_lines(4, &outsize, &spmin, &spmax);
+ }
+
+ if (action & F_MAIN) {
+ /* Check for min/max values */
+ if (psic->some_acpu_10 > *spmax) {
+ *spmax = psic->some_acpu_10;
+ }
+ if (psic->some_acpu_10 < *spmin) {
+ *spmin = psic->some_acpu_10;
+ }
+ if (psic->some_acpu_60 > *(spmax + 1)) {
+ *(spmax + 1) = psic->some_acpu_60;
+ }
+ if (psic->some_acpu_60 < *(spmin + 1)) {
+ *(spmin + 1) = psic->some_acpu_60;
+ }
+ if (psic->some_acpu_300 > *(spmax + 2)) {
+ *(spmax + 2) = psic->some_acpu_300;
+ }
+ if (psic->some_acpu_300 < *(spmin + 2)) {
+ *(spmin + 2) = psic->some_acpu_300;
+ }
+ tval = ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv);
+ if (tval > *(spmax + 3)) {
+ *(spmax + 3) = tval;
+ }
+ if (tval < *(spmin + 3)) {
+ *(spmin + 3) = tval;
+ }
+
+ /* %scpu-10 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_acpu_10 / 100,
+ out, outsize, svg_p->restart);
+ /* %scpu-60 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_acpu_60 / 100,
+ out + 1, outsize + 1, svg_p->restart);
+ /* %scpu-300 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_acpu_300 / 100,
+ out + 2, outsize + 2, svg_p->restart);
+ /* %scpu */
+ brappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ 0.0,
+ ((double) psic->some_cpu_total - psip->some_cpu_total) / (100 * itv),
+ out + 3, outsize + 3, svg_p->dt);
+ }
+
+ if (action & F_END) {
+ /* Fix min/max values for pressure ratios */
+ *spmin /= 100; *spmax /= 100;
+ *(spmin + 1) /= 100; *(spmax + 1) /= 100;
+ *(spmin + 2) /= 100; *(spmax + 2) /= 100;
+
+ draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
+
+ /* Free remaining structures */
+ free_graphs(out, outsize, spmin, spmax);
+ }
+}
+
+/*
+ ***************************************************************************
+ * Display pressure-stall I/O statistics in SVG.
+ *
+ * IN:
+ * @a Activity structure with statistics.
+ * @curr Index in array for current sample statistics.
+ * @action Action expected from current function.
+ * @svg_p SVG specific parameters: Current graph number (.@graph_no),
+ * flag indicating that a restart record has been previously
+ * found (.@restart) and time used for the X axis origin
+ * (@ust_time_ref).
+ * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
+ * @record_hdr Pointer on record header of current stats sample.
+ ***************************************************************************
+ */
+__print_funct_t svg_print_psiio_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
+ unsigned long long itv, struct record_header *record_hdr)
+{
+ struct stats_psi_io
+ *psic = (struct stats_psi_io *) a->buf[curr],
+ *psip = (struct stats_psi_io *) a->buf[!curr];
+ int group[] = {3, 1, 3, 1};
+ int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
+ char *title[] = {"I/O pressure trends (some tasks)", "I/O stall time (some tasks)",
+ "I/O pressure trends (full)", "I/O stall time (full)"};
+ char *g_title[] = {"%sio-10", "%sio-60", "%sio-300",
+ "%sio",
+ "%fio-10", "%fio-60", "%fio-300",
+ "%fio"};
+ static double *spmin, *spmax;
+ static char **out;
+ static int *outsize;
+ double tval;
+
+ if (action & F_BEGIN) {
+ /*
+ * Allocate arrays that will contain the graphs data
+ * and the min/max values.
+ */
+ out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
+ }
+
+ if (action & F_MAIN) {
+ /* Check for min/max values */
+ if (psic->some_aio_10 > *spmax) {
+ *spmax = psic->some_aio_10;
+ }
+ if (psic->some_aio_10 < *spmin) {
+ *spmin = psic->some_aio_10;
+ }
+ if (psic->some_aio_60 > *(spmax + 1)) {
+ *(spmax + 1) = psic->some_aio_60;
+ }
+ if (psic->some_aio_60 < *(spmin + 1)) {
+ *(spmin + 1) = psic->some_aio_60;
+ }
+ if (psic->some_aio_300 > *(spmax + 2)) {
+ *(spmax + 2) = psic->some_aio_300;
+ }
+ if (psic->some_aio_300 < *(spmin + 2)) {
+ *(spmin + 2) = psic->some_aio_300;
+ }
+ tval = ((double) psic->some_io_total - psip->some_io_total) / (100 * itv);
+ if (tval > *(spmax + 3)) {
+ *(spmax + 3) = tval;
+ }
+ if (tval < *(spmin + 3)) {
+ *(spmin + 3) = tval;
+ }
+
+ if (psic->full_aio_10 > *(spmax + 4)) {
+ *(spmax + 4) = psic->full_aio_10;
+ }
+ if (psic->full_aio_10 < *(spmin + 4)) {
+ *(spmin + 4) = psic->full_aio_10;
+ }
+ if (psic->full_aio_60 > *(spmax + 5)) {
+ *(spmax + 5) = psic->full_aio_60;
+ }
+ if (psic->full_aio_60 < *(spmin + 5)) {
+ *(spmin + 5) = psic->full_aio_60;
+ }
+ if (psic->full_aio_300 > *(spmax + 6)) {
+ *(spmax + 6) = psic->full_aio_300;
}
+ if (psic->full_aio_300 < *(spmin + 6)) {
+ *(spmin + 6) = psic->full_aio_300;
+ }
+ tval = ((double) psic->full_io_total - psip->full_io_total) / (100 * itv);
+ if (tval > *(spmax + 7)) {
+ *(spmax + 7) = tval;
+ }
+ if (tval < *(spmin + 7)) {
+ *(spmin + 7) = tval;
+ }
+
+ /* %sio-10 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_aio_10 / 100,
+ out, outsize, svg_p->restart);
+ /* %sio-60 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_aio_60 / 100,
+ out + 1, outsize + 1, svg_p->restart);
+ /* %sio-300 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_aio_300 / 100,
+ out + 2, outsize + 2, svg_p->restart);
+ /* %sio */
+ brappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ 0.0,
+ ((double) psic->some_io_total - psip->some_io_total) / (100 * itv),
+ out + 3, outsize + 3, svg_p->dt);
+
+ /* %fio-10 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->full_aio_10 / 100,
+ out + 4, outsize + 4, svg_p->restart);
+ /* %fio-60 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->full_aio_60 / 100,
+ out + 5, outsize + 5, svg_p->restart);
+ /* %fio-300 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->full_aio_300 / 100,
+ out + 6, outsize + 6, svg_p->restart);
+ /* %fio */
+ brappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ 0.0,
+ ((double) psic->full_io_total - psip->full_io_total) / (100 * itv),
+ out + 7, outsize + 7, svg_p->dt);
+ }
+
+ if (action & F_END) {
+ /* Fix min/max values for pressure ratios */
+ *spmin /= 100; *spmax /= 100;
+ *(spmin + 1) /= 100; *(spmax + 1) /= 100;
+ *(spmin + 2) /= 100; *(spmax + 2) /= 100;
+
+ *(spmin + 4) /= 100; *(spmax + 4) /= 100;
+ *(spmin + 5) /= 100; *(spmax + 5) /= 100;
+ *(spmin + 6) /= 100; *(spmax + 6) /= 100;
+
+ draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
+
+ /* Free remaining structures */
+ free_graphs(out, outsize, spmin, spmax);
+ }
+}
+
+/*
+ ***************************************************************************
+ * Display pressure-stall memory statistics in SVG.
+ *
+ * IN:
+ * @a Activity structure with statistics.
+ * @curr Index in array for current sample statistics.
+ * @action Action expected from current function.
+ * @svg_p SVG specific parameters: Current graph number (.@graph_no),
+ * flag indicating that a restart record has been previously
+ * found (.@restart) and time used for the X axis origin
+ * (@ust_time_ref).
+ * @itv Interval of time in 1/100th of a second (only with F_MAIN action).
+ * @record_hdr Pointer on record header of current stats sample.
+ ***************************************************************************
+ */
+__print_funct_t svg_print_psimem_stats(struct activity *a, int curr, int action, struct svg_parm *svg_p,
+ unsigned long long itv, struct record_header *record_hdr)
+{
+ struct stats_psi_mem
+ *psic = (struct stats_psi_mem *) a->buf[curr],
+ *psip = (struct stats_psi_mem *) a->buf[!curr];
+ int group[] = {3, 1, 3, 1};
+ int g_type[] = {SVG_LINE_GRAPH, SVG_BAR_GRAPH, SVG_LINE_GRAPH, SVG_BAR_GRAPH};
+ char *title[] = {"Memory pressure trends (some tasks)", "Memory stall time (some tasks)",
+ "Memory pressure trends (full)", "Memory stall time (full)"};
+ char *g_title[] = {"%smem-10", "%smem-60", "%smem-300",
+ "%smem",
+ "%fmem-10", "%fmem-60", "%fmem-300",
+ "%fmem"};
+ static double *spmin, *spmax;
+ static char **out;
+ static int *outsize;
+ double tval;
+
+ if (action & F_BEGIN) {
+ /*
+ * Allocate arrays that will contain the graphs data
+ * and the min/max values.
+ */
+ out = allocate_graph_lines(8, &outsize, &spmin, &spmax);
+ }
+
+ if (action & F_MAIN) {
+ /* Check for min/max values */
+ if (psic->some_amem_10 > *spmax) {
+ *spmax = psic->some_amem_10;
+ }
+ if (psic->some_amem_10 < *spmin) {
+ *spmin = psic->some_amem_10;
+ }
+ if (psic->some_amem_60 > *(spmax + 1)) {
+ *(spmax + 1) = psic->some_amem_60;
+ }
+ if (psic->some_amem_60 < *(spmin + 1)) {
+ *(spmin + 1) = psic->some_amem_60;
+ }
+ if (psic->some_amem_300 > *(spmax + 2)) {
+ *(spmax + 2) = psic->some_amem_300;
+ }
+ if (psic->some_amem_300 < *(spmin + 2)) {
+ *(spmin + 2) = psic->some_amem_300;
+ }
+ tval = ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv);
+ if (tval > *(spmax + 3)) {
+ *(spmax + 3) = tval;
+ }
+ if (tval < *(spmin + 3)) {
+ *(spmin + 3) = tval;
+ }
+
+ if (psic->full_amem_10 > *(spmax + 4)) {
+ *(spmax + 4) = psic->full_amem_10;
+ }
+ if (psic->full_amem_10 < *(spmin + 4)) {
+ *(spmin + 4) = psic->full_amem_10;
+ }
+ if (psic->full_amem_60 > *(spmax + 5)) {
+ *(spmax + 5) = psic->full_amem_60;
+ }
+ if (psic->full_amem_60 < *(spmin + 5)) {
+ *(spmin + 5) = psic->full_amem_60;
+ }
+ if (psic->full_amem_300 > *(spmax + 6)) {
+ *(spmax + 6) = psic->full_amem_300;
+ }
+ if (psic->full_amem_300 < *(spmin + 6)) {
+ *(spmin + 6) = psic->full_amem_300;
+ }
+ tval = ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv);
+ if (tval > *(spmax + 7)) {
+ *(spmax + 7) = tval;
+ }
+ if (tval < *(spmin + 7)) {
+ *(spmin + 7) = tval;
+ }
+
+ /* %smem-10 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_amem_10 / 100,
+ out, outsize, svg_p->restart);
+ /* %smem-60 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_amem_60 / 100,
+ out + 1, outsize + 1, svg_p->restart);
+ /* %smem-300 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->some_amem_300 / 100,
+ out + 2, outsize + 2, svg_p->restart);
+ /* %smem */
+ brappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ 0.0,
+ ((double) psic->some_mem_total - psip->some_mem_total) / (100 * itv),
+ out + 3, outsize + 3, svg_p->dt);
+
+ /* %fmem-10 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->full_amem_10 / 100,
+ out + 4, outsize + 4, svg_p->restart);
+ /* %fmem-60 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->full_amem_60 / 100,
+ out + 5, outsize + 5, svg_p->restart);
+ /* %fmem-300 */
+ lnappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ (double) psic->full_amem_300 / 100,
+ out + 6, outsize + 6, svg_p->restart);
+ /* %fmem */
+ brappend(record_hdr->ust_time - svg_p->ust_time_ref,
+ 0.0,
+ ((double) psic->full_mem_total - psip->full_mem_total) / (100 * itv),
+ out + 7, outsize + 7, svg_p->dt);
+ }
+
+ if (action & F_END) {
+ /* Fix min/max values for pressure ratios */
+ *spmin /= 100; *spmax /= 100;
+ *(spmin + 1) /= 100; *(spmax + 1) /= 100;
+ *(spmin + 2) /= 100; *(spmax + 2) /= 100;
+
+ *(spmin + 4) /= 100; *(spmax + 4) /= 100;
+ *(spmin + 5) /= 100; *(spmax + 5) /= 100;
+ *(spmin + 6) /= 100; *(spmax + 6) /= 100;
+
+ draw_activity_graphs(a->g_nr, g_type, title, g_title, NULL, group,
+ spmin, spmax, out, outsize, svg_p, record_hdr, FALSE, a, 0);
/* Free remaining structures */
free_graphs(out, outsize, spmin, spmax);