version 1.1.1.1, 2012/02/21 22:19:56
|
version 1.1.1.3, 2019/10/21 14:58:35
|
Line 1
|
Line 1
|
/* |
/* |
* graph.c Graph creation utility |
* graph.c Graph creation utility |
* |
* |
* Copyright (c) 2001-2005 Thomas Graf <tgraf@suug.ch> | * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch> |
| * Copyright (c) 2013 Red Hat, Inc. |
* |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* copy of this software and associated documentation files (the "Software"), |
Line 26
|
Line 27
|
#include <bmon/graph.h> |
#include <bmon/graph.h> |
#include <bmon/input.h> |
#include <bmon/input.h> |
#include <bmon/conf.h> |
#include <bmon/conf.h> |
#include <bmon/item.h> | #include <bmon/history.h> |
#include <bmon/node.h> | |
#include <bmon/conf.h> |
#include <bmon/conf.h> |
|
#include <bmon/unit.h> |
#include <bmon/utils.h> |
#include <bmon/utils.h> |
|
|
|
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, | static inline size_t table_size(struct graph_cfg *cfg) |
double half_step) | |
{ |
{ |
int i; | return cfg->gc_height * graph_row_size(cfg); |
char *col = D_AT_COL(t->t_data, data_idx); | } |
|
|
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) { | static inline char *at_col(char *row, int ncol) |
for (i = 0; i < t->t_height; i++) | { |
*(D_AT_ROW(col, i)) = get_unk_char(); | return row + ncol; |
} 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 void create_table(table_t *t, hist_data_t *src, int index, int height, | static inline char *tbl_pos(struct graph_cfg *cfg, char *tbl, int nrow, int ncol) |
int unit) | |
{ |
{ |
int i, di; | return at_col(at_row(cfg, tbl, nrow), ncol); |
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)); | |
|
|
memset(t->t_data, get_bg_char(), dsize); | 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++) | if (!tbl->gt_table) { |
*(D_AT_COL(D_AT_ROW(t->t_data, i), HISTORY_SIZE)) = '\0'; | tbl->gt_table = xcalloc(table_size(cfg), sizeof(char)); |
| tbl->gt_scale = xcalloc(cfg->gc_height, sizeof(double)); |
| } |
|
|
for (i = 0; i < HISTORY_SIZE; i++) | memset(tbl->gt_table, cfg->gc_background, table_size(cfg)); |
if (max < src->hd_data[i] && src->hd_data[i] != UNK_DATA) | |
max = src->hd_data[i]; | |
|
|
step = (double) max / (double) height; | /* end each line with a \0 */ |
half_step = step / 2.0f; | for (i = 0; i < cfg->gc_height; i++) |
| *tbl_pos(cfg, tbl->gt_table, i, cfg->gc_width) = '\0'; |
|
|
for (i = 0; i < height; i++) | /* leave table blank if there is no data */ |
t->t_y_scale[i] = (double) (i + 1) * step; | if (!h || !data->hs_data) |
| return; |
|
|
for (di = 0, i = (index - 1); i >= 0; di++, i--) | if (cfg->gc_width > h->h_definition->hd_size) |
put_col(t, di, src, i, half_step); | BUG(); |
|
|
for (i = (HISTORY_SIZE - 1); di < HISTORY_SIZE; di++, i--) | /* find the largest peak */ |
put_col(t, di, src, i, half_step); | 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; |
| } |
|
|
{ | step = (double) max / (double) cfg->gc_height; |
b_cnt_t div; | half_step = step / 2.0f; |
int h = (height / 3) * 2; | |
|
|
if (h >= height) | for (i = 0; i < cfg->gc_height; i++) |
h = (height - 1); | tbl->gt_scale[i] = (double) (i + 1) * step; |
|
|
div = get_divisor(t->t_y_scale[h], unit, &t->t_y_unit, NULL); | for (n = h->h_index, i = 0; i < cfg->gc_width; i++) { |
| char * col = at_col(tbl->gt_table, i); |
for (i = 0; i < height; i++) | |
t->t_y_scale[i] /= (double) div; | |
} | |
} | |
|
|
graph_t * create_graph(hist_elem_t *src, int height, int unit) | if (--n < 0) |
{ | n = h->h_definition->hd_size - 1; |
graph_t *g; | v = history_data(h, data, n); |
|
|
g = xcalloc(1, sizeof(graph_t)); | 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; |
|
|
create_table(&g->g_rx, &src->he_rx, src->he_index, height, unit); | for (t = 0; t < cfg->gc_height; t++) |
create_table(&g->g_tx, &src->he_tx, src->he_index, height, unit); | if (v >= (tbl->gt_scale[t] - half_step)) |
| *(at_row(cfg, col, t)) = cfg->gc_foreground; |
| } |
| } |
|
|
return g; | 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; |
} |
} |
|
|
graph_t * create_configued_graph(history_t *src, int height, int unit, | struct graph *graph_alloc(struct history *h, struct graph_cfg *cfg) |
int x_unit) | |
{ |
{ |
graph_t *g; | struct graph *g; |
hist_elem_t *e = NULL; | |
char *u = "s"; | |
int h = 0; | |
|
|
switch (x_unit) { | if (!cfg->gc_height) |
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; | |
} | |
} | |
break; | |
} | |
| |
if (NULL == e) | |
BUG(); |
BUG(); |
|
|
g = create_graph(e, height, unit); | g = xcalloc(1, sizeof(*g)); |
|
|
if (h) | memcpy(&g->g_cfg, cfg, sizeof(*cfg)); |
g->g_flags |= GRAPH_HAS_FREEABLE_X_UNIT; | |
|
|
g->g_rx.t_x_unit = u; | if (h != NULL && |
g->g_tx.t_x_unit = u; | (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; |
return g; |
} |
} |
|
|
static void free_table(table_t *t) | void graph_refill(struct graph *g, struct history *h) |
{ |
{ |
xfree(t->t_y_scale); | fill_table(g, &g->g_rx, h, h ? &h->h_rx : NULL); |
xfree(t->t_data); | 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) | if (!g) |
xfree(g->g_rx.t_x_unit); | return; |
| |
free_table(&g->g_rx); | xfree(g->g_rx.gt_table); |
free_table(&g->g_tx); | xfree(g->g_rx.gt_scale); |
| xfree(g->g_tx.gt_table); |
| xfree(g->g_tx.gt_scale); |
xfree(g); |
xfree(g); |
} |
} |
|
|
|
#if 0 |
|
|
void new_graph(void) |
void new_graph(void) |
{ |
{ |
if (get_ngraphs() >= (MAX_GRAPHS - 1)) | if (ngraphs >= (MAX_GRAPHS - 1)) |
return; |
return; |
set_ngraphs(get_ngraphs() + 1); | set_ngraphs_hard(ngraphs + 1); |
} |
} |
|
|
void del_graph(void) |
void del_graph(void) |
{ |
{ |
if (get_ngraphs() <= 1) | if (ngraphs <= 1) |
return; |
return; |
set_ngraphs(get_ngraphs() - 1); | set_ngraphs_hard(ngraphs - 1); |
} |
} |
|
|
int next_graph(void) |
int next_graph(void) |
{ |
{ |
item_t *it = get_current_item(); | struct item *it = item_current(); |
if (it == NULL) |
if (it == NULL) |
return EMPTY_LIST; |
return EMPTY_LIST; |
|
|
if (it->i_graph_sel >= (get_ngraphs() - 1)) | if (it->i_graph_sel >= (ngraphs - 1)) |
it->i_graph_sel = 0; |
it->i_graph_sel = 0; |
else |
else |
it->i_graph_sel++; |
it->i_graph_sel++; |
Line 202 int next_graph(void)
|
Line 201 int next_graph(void)
|
|
|
int prev_graph(void) |
int prev_graph(void) |
{ |
{ |
item_t *it = get_current_item(); | struct item *it = item_current(); |
if (it == NULL) |
if (it == NULL) |
return EMPTY_LIST; |
return EMPTY_LIST; |
|
|
if (it->i_graph_sel <= 0) |
if (it->i_graph_sel <= 0) |
it->i_graph_sel = get_ngraphs() - 1; | it->i_graph_sel = ngraphs - 1; |
else |
else |
it->i_graph_sel--; |
it->i_graph_sel--; |
|
|
return 0; |
return 0; |
} |
} |
|
|
|
#endif |