static int final_height = 0;
static int final_width = 0;
-struct graph_line_data *alloc_line_data(int seconds, int stop_seconds)
+struct graph_line_data *alloc_line_data(int min_seconds, int max_seconds, int stop_seconds)
{
int size = sizeof(struct graph_line_data) + (stop_seconds + 1) * sizeof(struct graph_line_pair);
struct graph_line_data *gld;
fprintf(stderr, "Unable to allocate memory for graph data\n");
exit(1);
}
- gld->seconds = seconds;
+ gld->min_seconds = min_seconds;
+ gld->max_seconds = max_seconds;
gld->stop_seconds = stop_seconds;
return gld;
}
free(gld);
}
-struct graph_dot_data *alloc_dot_data(int seconds, u64 max_offset, int stop_seconds)
+struct graph_dot_data *alloc_dot_data(int min_seconds, int max_seconds, u64 min_offset, u64 max_offset, int stop_seconds)
{
int size;
int arr_size;
fprintf(stderr, "Unable to allocate memory for graph data\n");
exit(1);
}
- gdd->seconds = seconds;
+ gdd->min_seconds = min_seconds;
+ gdd->max_seconds = max_seconds;
gdd->stop_seconds = stop_seconds;
gdd->rows = rows;
gdd->cols = cols;
+ gdd->min_offset = min_offset;
gdd->max_offset = max_offset;
return gdd;
}
void set_gdd_bit(struct graph_dot_data *gdd, u64 offset, double bytes, double time)
{
- double bytes_per_row = (double)gdd->max_offset / gdd->rows;
-
- double secs_per_col = (double)gdd->seconds / gdd->cols;
+ double bytes_per_row = (double)(gdd->max_offset - gdd->min_offset + 1) / gdd->rows;
+ double secs_per_col = (double)(gdd->max_seconds - gdd->min_seconds) / gdd->cols;
double col;
double row;
int col_int;
int bit_mod;
double mod = bytes_per_row;
- if (offset > gdd->max_offset)
+ if (offset > gdd->max_offset || offset < gdd->min_offset)
return;
gdd->total_ios++;
time = time / 1000000000.0;
while (bytes > 0) {
- row = (double)offset / bytes_per_row;
- col = time / secs_per_col;
+ row = (double)(offset - gdd->min_offset) / bytes_per_row;
+ col = (time - gdd->min_seconds) / secs_per_col;
col_int = floor(col);
row_int = floor(row);
return (int)axis_x_off_double(x);
}
-
/*
* this draws a backing rectangle for the plot and it
* also creates a new svg element so our offsets can
if (plot->no_legend)
local_legend_width = 0;
- plot->total_width = axis_x_off(graph_width) + graph_left_pad / 2 + local_legend_width;;
+ plot->total_width = axis_x_off(graph_width) + graph_left_pad / 2 + local_legend_width;
plot->total_height = axis_y() + tick_label_pad + tick_font_size;
if (plot->add_xlabel)
if (!tick_only) {
snprintf(line, line_len, "<text x=\"%d\" y=\"%d\" font-family=\"%s\" font-size=\"%d\" "
"fill=\"black\" style=\"text-anchor: %s\">%d</text>\n",
- tick_x, text_y, font_family, tick_font_size, anchor, step * i);
+ tick_x, text_y, font_family, tick_font_size, anchor,
+ first + step * i);
write(plot->fd, line, strlen(line));
}
tick_x += pixels_per_tick;
"fill=\"black\" style=\"text-anchor: %s\">%d%s</text>\n",
text_x,
axis_y_off(tick_y - tick_font_size / 2),
- font_family, tick_font_size, anchor, step * i, units);
+ font_family, tick_font_size, anchor, first + step * i, units);
write(plot->fd, line, strlen(line));
tick_y += pixels_per_tick;
}
int close_plot(struct plot *plot)
{
close_svg(plot->fd);
- plot->start_y_offset += plot->total_height;
- plot->add_xlabel = 0;
- return 0;
-}
-
-int close_plot_no_height(struct plot *plot)
-{
- close_svg(plot->fd);
- plot->add_xlabel = 0;
+ if (plot->direction == PLOT_DOWN)
+ plot->start_y_offset += plot->total_height;
+ else if (plot->direction == PLOT_ACROSS)
+ plot->start_x_offset += plot->total_width;
return 0;
}
-int close_plot_col(struct plot *plot)
-{
- close_svg(plot->fd);
- plot->start_x_offset += plot->total_width;
- plot->add_xlabel = 0;
- return 0;
-}
-
-
struct plot *alloc_plot(void)
{
struct plot *plot;
int fd = plot->fd;
char *start = "<path d=\"";
double yscale = ((double)gld->max) / graph_height;
- double xscale = (double)(gld->seconds - 1) / graph_width;
+ double xscale = (double)(gld->max_seconds - gld->min_seconds - 1) / graph_width;
char c = 'M';
double x;
int printed_header = 0;
else if (rolling_avg_secs)
rolling = rolling_avg_secs;
else
- rolling = gld->stop_seconds / 25;
+ rolling = (gld->stop_seconds - gld->min_seconds) / 25;
- for (i = 0; i < gld->stop_seconds; i++) {
+ for (i = gld->min_seconds; i < gld->stop_seconds; i++) {
avg = rolling_avg(gld->data, i, rolling);
if (yscale == 0)
val = 0;
if (val < 0)
val = 0;
- x = (double)i / xscale;
+ x = (double)(i - gld->min_seconds) / xscale;
if (!thresh1 && !thresh2) {
if (!printed_header) {
snprintf(line, line_len, "\" fill=\"none\" stroke=\"%s\" stroke-width=\"2\"/>\n", color);
write(fd, line, strlen(line));
}
+ if (plot->timeline)
+ svg_write_time_line(plot, plot->timeline);
return 0;
}
unsigned char val;
int bit_index;
int bit_mod;
- double blocks_per_row = gdd->max_offset / gdd->rows;
- double movie_blocks_per_cell = gdd->max_offset / (graph_width * graph_height);
+ double blocks_per_row = (gdd->max_offset - gdd->min_offset + 1) / gdd->rows;
+ double movie_blocks_per_cell = (gdd->max_offset - gdd->min_offset + 1) / (graph_width * graph_height);
double cell_index;
int margin_orig = graph_inner_y_margin;
graph_inner_y_margin += 5;
- ph->history_max = gdd->max_offset / movie_blocks_per_cell;
+ ph->history_max = (gdd->max_offset - gdd->min_offset + 1) / movie_blocks_per_cell;
for (row = gdd->rows - 1; row >= 0; row--) {
bit_index = row * gdd->cols + col;