static void gfio_update_thread_status_all(char *status_message, double perc);
void report_error(GError *error);
-static void iops_graph_y_axis_unit_change(struct graph *g, int power_of_ten)
-{
- switch (power_of_ten) {
- case 9: graph_y_title(g, "Billions of IOs / sec");
- break;
- case 6: graph_y_title(g, "Millions of IOs / sec");
- break;
- case 3: graph_y_title(g, "Thousands of IOs / sec");
- break;
- case 0:
- default: graph_y_title(g, "IOs / sec");
- break;
- }
-}
-
static struct graph *setup_iops_graph(void)
{
struct graph *g;
g = graph_new(DRAWING_AREA_XDIM / 2.0, DRAWING_AREA_YDIM, gfio_graph_font);
- graph_title(g, "IOPS");
+ graph_title(g, "IOPS (IOs/sec)");
graph_x_title(g, "Time (secs)");
- graph_y_title(g, "IOs / sec");
graph_add_label(g, "Read IOPS");
graph_add_label(g, "Write IOPS");
graph_set_color(g, "Read IOPS", 0.13, 0.54, 0.13);
graph_set_color(g, "Write IOPS", 1.0, 0.0, 0.0);
line_graph_set_data_count_limit(g, gfio_graph_limit);
- graph_y_axis_unit_change_notify(g, iops_graph_y_axis_unit_change);
- graph_add_extra_space(g, 0.005, 0.005, 0.03, 0.03);
+ graph_add_extra_space(g, 0.0, 0.0, 0.0, 0.0);
return g;
}
-static void bandwidth_graph_y_axis_unit_change(struct graph *g, int power_of_ten)
-{
- switch (power_of_ten) {
- case 9: graph_y_title(g, "Petabytes / sec");
- break;
- case 6: graph_y_title(g, "Gigabytes / sec");
- break;
- case 3: graph_y_title(g, "Megabytes / sec");
- break;
- case 0:
- default: graph_y_title(g, "Kilobytes / sec");
- break;
- }
-}
-
static struct graph *setup_bandwidth_graph(void)
{
struct graph *g;
g = graph_new(DRAWING_AREA_XDIM / 2.0, DRAWING_AREA_YDIM, gfio_graph_font);
- graph_title(g, "Bandwidth");
+ graph_title(g, "Bandwidth (bytes/sec)");
graph_x_title(g, "Time (secs)");
- graph_y_title(g, "Kbytes / sec");
graph_add_label(g, "Read Bandwidth");
graph_add_label(g, "Write Bandwidth");
graph_set_color(g, "Read Bandwidth", 0.13, 0.54, 0.13);
graph_set_color(g, "Write Bandwidth", 1.0, 0.0, 0.0);
+ graph_set_base_offset(g, 1);
line_graph_set_data_count_limit(g, 100);
- graph_y_axis_unit_change_notify(g, bandwidth_graph_y_axis_unit_change);
- graph_add_extra_space(g, 0.005, 0.005, 0.03, 0.03);
-
+ graph_add_extra_space(g, 0.0, 0.0, 0.0, 0.0);
return g;
}
const char *font;
graph_axis_unit_change_callback x_axis_unit_change_callback;
graph_axis_unit_change_callback y_axis_unit_change_callback;
+ unsigned int base_offset;
double left_extra;
double right_extra;
double top_extra;
static void graph_draw_x_ticks(struct graph *g, cairo_t *cr,
double x1, double y1, double x2, double y2,
- double minx, double maxx, int nticks)
+ double minx, double maxx, int nticks, int add_tm_text)
{
struct tickmark *tm;
double tx;
static double dash[] = { 1.0, 2.0 };
nticks = calc_tickmarks(minx, maxx, nticks, &tm, &power_of_ten,
- g->x_axis_unit_change_callback == NULL);
+ g->x_axis_unit_change_callback == NULL, g->base_offset);
if (g->x_axis_unit_change_callback)
g->x_axis_unit_change_callback(g, power_of_ten);
for (i = 0; i < nticks; i++) {
tx = (((tm[i].value) - minx) / (maxx - minx)) * (x2 - x1) + x1;
- if (tx < x1 || tx > x2)
+
+ /* really tx < yx || tx > x2, but protect against rounding */
+ if (x1 - tx > 0.01 || tx - x2 > 0.01)
continue;
/* Draw tick mark */
cairo_stroke(cr);
cairo_restore(cr);
+ if (!add_tm_text)
+ continue;
+
/* draw tickmark label */
draw_centered_text(g, cr, tx, y2 * 1.04, 12.0, tm[i].string);
cairo_stroke(cr);
}
}
-static void graph_draw_y_ticks(struct graph *g, cairo_t *cr,
+static double graph_draw_y_ticks(struct graph *g, cairo_t *cr,
double x1, double y1, double x2, double y2,
- double miny, double maxy, int nticks)
+ double miny, double maxy, int nticks, int add_tm_text)
{
struct tickmark *tm;
double ty;
static double dash[] = { 2.0, 2.0 };
nticks = calc_tickmarks(miny, maxy, nticks, &tm, &power_of_ten,
- g->y_axis_unit_change_callback == NULL);
+ g->y_axis_unit_change_callback == NULL, g->base_offset);
if (g->y_axis_unit_change_callback)
g->y_axis_unit_change_callback(g, power_of_ten);
+ /*
+ * Use highest tickmark as top of graph, not highest value. Otherwise
+ * it's impossible to see what the max value is, if the graph is
+ * fairly flat.
+ */
+ maxy = tm[nticks - 1].value;
+
for (i = 0; i < nticks; i++) {
ty = y2 - (((tm[i].value) - miny) / (maxy - miny)) * (y2 - y1);
- if (ty < y1 || ty > y2)
+
+ /* really ty < y1 || ty > y2, but protect against rounding */
+ if (y1 - ty > 0.01 || ty - y2 > 0.01)
continue;
+
/* draw tick mark */
cairo_move_to(cr, x1, ty);
cairo_line_to(cr, x1 - (x2 - x1) * 0.02, ty);
cairo_stroke(cr);
cairo_restore(cr);
+ if (!add_tm_text)
+ continue;
+
/* draw tickmark label */
draw_right_justified_text(g, cr, x1 - (x2 - x1) * 0.025, ty, 12.0, tm[i].string);
cairo_stroke(cr);
}
+
+ /*
+ * Return new max to use
+ */
+ return maxy;
}
void bar_graph_draw(struct graph *bg, cairo_t *cr)
graph_draw_common(bg, cr, &x1, &y1, &x2, &y2);
nlabels = count_labels(bg->labels);
- space_per_label = (x2 - x1) / (double) nlabels;
+ space_per_label = (x2 - x1) / (double) nlabels;
mindata = find_min_data(bg->labels);
maxdata = find_max_data(bg->labels);
return;
}
- graph_draw_y_ticks(bg, cr, x1, y1, x2, y2, mindata, maxdata, 10);
+ graph_draw_y_ticks(bg, cr, x1, y1, x2, y2, mindata, maxdata, 10, 1);
i = 0;
for (lb = bg->labels; lb; lb = lb->next) {
gminy = miny - bottom_extra;
gmaxy = maxy + top_extra;
- graph_draw_x_ticks(g, cr, x1, y1, x2, y2, gminx, gmaxx, 10);
- graph_draw_y_ticks(g, cr, x1, y1, x2, y2, gminy, gmaxy, 10);
+ graph_draw_x_ticks(g, cr, x1, y1, x2, y2, gminx, gmaxx, 10, good_data);
+ gmaxy = graph_draw_y_ticks(g, cr, x1, y1, x2, y2, gminy, gmaxy, 10, good_data);
if (!good_data)
goto skip_data;
g->bottom_extra = bottom_percent;
}
+/*
+ * Normally values are logged in a base unit of 0, but for other purposes
+ * it makes more sense to log in higher unit. For instance for bandwidth
+ * purposes, you may want to log in KB/sec (or MB/sec) rather than bytes/sec.
+ */
+void graph_set_base_offset(struct graph *g, unsigned int base_offset)
+{
+ g->base_offset = base_offset;
+}
+
int graph_has_tooltips(struct graph *g)
{
struct graph_label *i;
extern const char *graph_find_tooltip(struct graph *g, int x, int y);
extern int graph_contains_xy(struct graph *p, int x, int y);
+extern void graph_set_base_offset(struct graph *g, unsigned int base_offset);
+
#endif
}
static void shorten(struct tickmark *tm, int nticks, int *power_of_ten,
- int use_KMG_symbols)
+ int use_KMG_symbols, int base_offset)
{
- int i, l, minshorten;
+ const char shorten_chr[] = { 0, 'K', 'M', 'G', 'P', 'E', 0 };
+ int i, l, minshorten, shorten_idx = 0;
char *str;
- char shorten_char = '?';
minshorten = 100;
for (i = 0; i < nticks; i++) {
continue;
if (l > 9 && strcmp(&str[l - 9], "000000000") == 0) {
*power_of_ten = 9;
- shorten_char = use_KMG_symbols ? 'G' : '\0';
+ shorten_idx = 3;
} else if (6 < minshorten && l > 6 &&
strcmp(&str[l - 6], "000000") == 0) {
*power_of_ten = 6;
- shorten_char = use_KMG_symbols ? 'M' : '\0';
+ shorten_idx = 2;
} else if (l > 3 && strcmp(&str[l - 3], "000") == 0) {
*power_of_ten = 3;
- shorten_char = use_KMG_symbols ? 'K': '\0';
+ shorten_idx = 1;
} else {
*power_of_ten = 0;
}
if (minshorten == 0)
return;
+ if (!use_KMG_symbols)
+ shorten_idx = 0;
+ else if (base_offset)
+ shorten_idx += base_offset;
for (i = 0; i < nticks; i++) {
str = tm[i].string;
l = strlen(str);
- str[l - minshorten] = shorten_char;
- str[l - minshorten + 1] = '\0';
+ str[l - minshorten] = shorten_chr[shorten_idx];
+ if (shorten_idx)
+ str[l - minshorten + 1] = '\0';
}
}
int calc_tickmarks(double min, double max, int nticks, struct tickmark **tm,
- int *power_of_ten, int use_KMG_symbols)
+ int *power_of_ten, int use_KMG_symbols, int base_offset)
{
char str[100];
int nfrac;
sprintf((*tm)[i].string, str, x);
i++;
}
- shorten(*tm, i, power_of_ten, use_KMG_symbols);
+ shorten(*tm, i, power_of_ten, use_KMG_symbols, base_offset);
return i;
}
};
int calc_tickmarks(double min, double max, int nticks, struct tickmark **tm,
- int *power_of_ten, int use_KMG_symbols);
+ int *power_of_ten, int use_KMG_symbols, int base_off);
#endif