--- embedaddon/bmon/src/graph.c 2012/02/21 22:19:56 1.1.1.1 +++ embedaddon/bmon/src/graph.c 2014/07/30 07:55:27 1.1.1.2 @@ -1,7 +1,8 @@ /* * graph.c Graph creation utility * - * Copyright (c) 2001-2005 Thomas Graf + * Copyright (c) 2001-2013 Thomas Graf + * Copyright (c) 2013 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,173 +27,191 @@ #include #include #include -#include -#include +#include #include +#include #include +size_t graph_row_size(struct graph_cfg *cfg) +{ + /* +1 for trailing \0 */ + return cfg->gc_width + 1; +} -static void put_col(table_t *t, int data_idx, hist_data_t *src, int hist_idx, - double half_step) +static inline size_t table_size(struct graph_cfg *cfg) { - int i; - char *col = D_AT_COL(t->t_data, data_idx); + return cfg->gc_height * graph_row_size(cfg); +} - rate_cnt_t tot = src->hd_data[hist_idx]; +static inline char *at_row(struct graph_cfg *cfg, char *col, int nrow) +{ + return col + (nrow * graph_row_size(cfg)); +} - if (tot == UNK_DATA) { - for (i = 0; i < t->t_height; i++) - *(D_AT_ROW(col, i)) = get_unk_char(); - } else if (tot) { - *(D_AT_ROW(col, 0)) = ':'; - - for (i = 0; i < t->t_height; i++) - if (tot >= (t->t_y_scale[i] - half_step)) - *(D_AT_ROW(col, i)) = get_fg_char(); - } +static inline char *at_col(char *row, int ncol) +{ + return row + ncol; } -static void create_table(table_t *t, hist_data_t *src, int index, int height, - int unit) +static inline char *tbl_pos(struct graph_cfg *cfg, char *tbl, int nrow, int ncol) { - int i, di; - size_t dsize = height * (HISTORY_SIZE + 1); - rate_cnt_t max = 0; - double half_step, step; - - t->t_index = index; - t->t_height = height; - t->t_y_scale = xcalloc(height, sizeof(double)); - t->t_data = xcalloc(dsize, sizeof(char)); + return at_col(at_row(cfg, tbl, nrow), ncol); +} - memset(t->t_data, get_bg_char(), dsize); +static void write_column(struct graph_cfg *cfg, struct graph_table *tbl, int ncol, + uint64_t value, double *scale, double half_step) +{ + char *col = at_col(tbl->gt_table, ncol); + int i; - for (i = 0; i < height; i++) - *(D_AT_COL(D_AT_ROW(t->t_data, i), HISTORY_SIZE)) = '\0'; +#if 0 + if (value == UNK_DATA) { + for (i = 0; i < height; i++) + *(at_row(g, col, i)) = unk_char; +#endif + if (value) { + *(at_row(cfg, col, 0)) = ':'; - for (i = 0; i < HISTORY_SIZE; i++) - if (max < src->hd_data[i] && src->hd_data[i] != UNK_DATA) - max = src->hd_data[i]; + for (i = 0; i < cfg->gc_height; i++) + if (value >= (scale[i] - half_step)) + *(at_row(cfg, col, i)) = cfg->gc_foreground; + } +} - step = (double) max / (double) height; - half_step = step / 2.0f; +static void fill_table(struct graph *g, struct graph_table *tbl, + struct history *h, struct history_store *data) +{ + struct graph_cfg *cfg = &g->g_cfg; + uint64_t max = 0; + double v; + int i, n, t; + float half_step, step; - for (i = 0; i < height; i++) - t->t_y_scale[i] = (double) (i + 1) * step; + if (!tbl->gt_table) { + tbl->gt_table = xcalloc(table_size(cfg), sizeof(char)); + tbl->gt_scale = xcalloc(cfg->gc_height, sizeof(double)); + } - for (di = 0, i = (index - 1); i >= 0; di++, i--) - put_col(t, di, src, i, half_step); + memset(tbl->gt_table, cfg->gc_background, table_size(cfg)); - for (i = (HISTORY_SIZE - 1); di < HISTORY_SIZE; di++, i--) - put_col(t, di, src, i, half_step); + /* end each line with a \0 */ + for (i = 0; i < cfg->gc_height; i++) + *tbl_pos(cfg, tbl->gt_table, i, cfg->gc_width) = '\0'; - { - b_cnt_t div; - int h = (height / 3) * 2; + /* leave table blank if there is no data */ + if (!h || !data->hs_data) + return; - if (h >= height) - h = (height - 1); + if (cfg->gc_width > h->h_definition->hd_size) + BUG(); - div = get_divisor(t->t_y_scale[h], unit, &t->t_y_unit, NULL); - - for (i = 0; i < height; i++) - t->t_y_scale[i] /= (double) div; + /* find the largest peak */ + for (n = h->h_index, i = 0; i < cfg->gc_width; i++) { + if (--n < 0) + n = h->h_definition->hd_size - 1; + v = history_data(h, data, n); + if (v != HISTORY_UNKNOWN && max < v) + max = v; } -} -graph_t * create_graph(hist_elem_t *src, int height, int unit) -{ - graph_t *g; + step = (double) max / (double) cfg->gc_height; + half_step = step / 2.0f; - g = xcalloc(1, sizeof(graph_t)); + for (i = 0; i < cfg->gc_height; i++) + tbl->gt_scale[i] = (double) (i + 1) * step; - create_table(&g->g_rx, &src->he_rx, src->he_index, height, unit); - create_table(&g->g_tx, &src->he_tx, src->he_index, height, unit); + for (n = h->h_index, i = 0; i < cfg->gc_width; i++) { + char * col = at_col(tbl->gt_table, i); - return g; -} + if (--n < 0) + n = h->h_definition->hd_size - 1; + v = history_data(h, data, n); -graph_t * create_configued_graph(history_t *src, int height, int unit, - int x_unit) -{ - graph_t *g; - hist_elem_t *e = NULL; - char *u = "s"; - int h = 0; + if (v == HISTORY_UNKNOWN) { + for (t = 0; t < cfg->gc_height; t++) + *(at_row(cfg, col, t)) = cfg->gc_unknown; + } else if (v > 0) { + *(at_row(cfg, col, 0)) = cfg->gc_noise; - switch (x_unit) { - case X_SEC: u = "s"; e = &src->h_sec; break; - case X_MIN: u = "m"; e = &src->h_min; break; - case X_HOUR: u = "h"; e = &src->h_hour; break; - case X_DAY: u = "d"; e = &src->h_day; break; - case X_READ: { - if (get_read_interval() != 1.0f) { - char buf[32]; - float ri = get_read_interval(); - - snprintf(buf, sizeof(buf), "(%.2fs)", ri); - u = strdup(buf); - h = 1; - e = &src->h_read; - } else { - u = "s"; - e = &src->h_sec; - } + for (t = 0; t < cfg->gc_height; t++) + if (v >= (tbl->gt_scale[t] - half_step)) + *(at_row(cfg, col, t)) = cfg->gc_foreground; } - break; } - if (NULL == e) + n = (cfg->gc_height / 3) * 2; + if (n >= cfg->gc_height) + n = (cfg->gc_height - 1); + + v = unit_divisor(tbl->gt_scale[n], cfg->gc_unit, + &tbl->gt_y_unit, NULL); + + for (i = 0; i < cfg->gc_height; i++) + tbl->gt_scale[i] /= v; +} + +struct graph *graph_alloc(struct history *h, struct graph_cfg *cfg) +{ + struct graph *g; + + if (!cfg->gc_height) BUG(); - g = create_graph(e, height, unit); + g = xcalloc(1, sizeof(*g)); - if (h) - g->g_flags |= GRAPH_HAS_FREEABLE_X_UNIT; + memcpy(&g->g_cfg, cfg, sizeof(*cfg)); - g->g_rx.t_x_unit = u; - g->g_tx.t_x_unit = u; + if (h != NULL && + (cfg->gc_width > h->h_definition->hd_size || !cfg->gc_width)) + g->g_cfg.gc_width = h->h_definition->hd_size; + if (!g->g_cfg.gc_width) + BUG(); + return g; } -static void free_table(table_t *t) +void graph_refill(struct graph *g, struct history *h) { - xfree(t->t_y_scale); - xfree(t->t_data); + fill_table(g, &g->g_rx, h, h ? &h->h_rx : NULL); + fill_table(g, &g->g_tx, h, h ? &h->h_tx : NULL); } -void free_graph(graph_t *g) +void graph_free(struct graph *g) { - if (g->g_flags & GRAPH_HAS_FREEABLE_X_UNIT) - xfree(g->g_rx.t_x_unit); - - free_table(&g->g_rx); - free_table(&g->g_tx); + if (!g) + return; + + xfree(g->g_rx.gt_table); + xfree(g->g_rx.gt_scale); + xfree(g->g_tx.gt_table); + xfree(g->g_tx.gt_scale); xfree(g); } +#if 0 + void new_graph(void) { - if (get_ngraphs() >= (MAX_GRAPHS - 1)) + if (ngraphs >= (MAX_GRAPHS - 1)) return; - set_ngraphs(get_ngraphs() + 1); + set_ngraphs_hard(ngraphs + 1); } void del_graph(void) { - if (get_ngraphs() <= 1) + if (ngraphs <= 1) return; - set_ngraphs(get_ngraphs() - 1); + set_ngraphs_hard(ngraphs - 1); } int next_graph(void) { - item_t *it = get_current_item(); + struct item *it = item_current(); if (it == NULL) return EMPTY_LIST; - if (it->i_graph_sel >= (get_ngraphs() - 1)) + if (it->i_graph_sel >= (ngraphs - 1)) it->i_graph_sel = 0; else it->i_graph_sel++; @@ -202,14 +221,16 @@ int next_graph(void) int prev_graph(void) { - item_t *it = get_current_item(); + struct item *it = item_current(); if (it == NULL) return EMPTY_LIST; if (it->i_graph_sel <= 0) - it->i_graph_sel = get_ngraphs() - 1; + it->i_graph_sel = ngraphs - 1; else it->i_graph_sel--; return 0; } + +#endif