diff --git a/src/rrd_graph.c b/src/rrd_graph.c
index 643abe4236a827eae37488263ac8d51e9a72c43e..c6805450e68d0733b45d232a978dd37daeab1750 100644 (file)
--- a/src/rrd_graph.c
+++ b/src/rrd_graph.c
/****************************************************************************
- * RRDtool 1.3.2 Copyright by Tobi Oetiker, 1997-2008
+ * RRDtool 1.4.3 Copyright by Tobi Oetiker, 1997-2010
****************************************************************************
* rrd__graph.c produce graphs from data in rrdfiles
****************************************************************************/
#include <fcntl.h>
#endif
-#ifdef HAVE_TIME_H
#include <time.h>
-#endif
-#ifdef HAVE_LOCALE_H
#include <locale.h>
+
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
#endif
#include "rrd_graph.h"
conv_if(VRULE, GF_VRULE);
conv_if(LINE, GF_LINE);
conv_if(AREA, GF_AREA);
+ conv_if(GRAD, GF_GRAD);
conv_if(STACK, GF_STACK);
conv_if(TICK, GF_TICK);
conv_if(TEXTALIGN, GF_TEXTALIGN);
}
if (!skip) {
unsigned long ft_step = im->gdes[i].step; /* ft_step will record what we got from fetch */
+ const char *rrd_daemon;
+ int status;
- /* Flush the file if
- * - a connection to the daemon has been established
- * - this is the first occurrence of that RRD file
- */
- if (rrdc_is_connected(im->daemon_addr))
+ if (im->gdes[i].daemon[0] != 0)
+ rrd_daemon = im->gdes[i].daemon;
+ else
+ rrd_daemon = im->daemon_addr;
+
+ /* "daemon" may be NULL. ENV_RRDCACHED_ADDRESS is evaluated in that
+ * case. If "daemon" holds the same value as in the previous
+ * iteration, no actual new connection is established - the
+ * existing connection is re-used. */
+ rrdc_connect (rrd_daemon);
+
+ /* If connecting was successfull, use the daemon to query the data.
+ * If there is no connection, for example because no daemon address
+ * was specified, (try to) use the local file directly. */
+ if (rrdc_is_connected (rrd_daemon))
{
- int status;
-
- status = 0;
- for (ii = 0; ii < i; ii++)
- {
- if (strcmp (im->gdes[i].rrd, im->gdes[ii].rrd) == 0)
- {
- status = 1;
- break;
- }
- }
-
- if (status == 0)
- {
- status = rrdc_flush (im->gdes[i].rrd);
- if (status != 0)
- {
- rrd_set_error ("rrdc_flush (%s) failed with status %i.",
- im->gdes[i].rrd, status);
- return (-1);
- }
+ status = rrdc_fetch (im->gdes[i].rrd,
+ cf_to_string (im->gdes[i].cf),
+ &im->gdes[i].start,
+ &im->gdes[i].end,
+ &ft_step,
+ &im->gdes[i].ds_cnt,
+ &im->gdes[i].ds_namv,
+ &im->gdes[i].data);
+ if (status != 0)
+ return (status);
+ }
+ else
+ {
+ if ((rrd_fetch_fn(im->gdes[i].rrd,
+ im->gdes[i].cf,
+ &im->gdes[i].start,
+ &im->gdes[i].end,
+ &ft_step,
+ &im->gdes[i].ds_cnt,
+ &im->gdes[i].ds_namv,
+ &im->gdes[i].data)) == -1) {
+ return -1;
}
- } /* if (rrdc_is_connected()) */
-
- if ((rrd_fetch_fn(im->gdes[i].rrd,
- im->gdes[i].cf,
- &im->gdes[i].start,
- &im->gdes[i].end,
- &ft_step,
- &im->gdes[i].ds_cnt,
- &im->gdes[i].ds_namv,
- &im->gdes[i].data)) == -1) {
- return -1;
}
im->gdes[i].data_first = 1;
/* memory for the processed data */
for (i = 0; i < im->gdes_c; i++) {
- if ((im->gdes[i].gf == GF_LINE) ||
- (im->gdes[i].gf == GF_AREA) || (im->gdes[i].gf == GF_TICK)) {
+ if ((im->gdes[i].gf == GF_LINE)
+ || (im->gdes[i].gf == GF_AREA)
+ || (im->gdes[i].gf == GF_TICK)
+ || (im->gdes[i].gf == GF_GRAD)
+ ) {
if ((im->gdes[i].p_data = (rrd_value_t*)malloc((im->xsize + 1)
* sizeof(rrd_value_t))) == NULL) {
rrd_set_error("malloc data_proc");
switch (im->gdes[ii].gf) {
case GF_LINE:
case GF_AREA:
+ case GF_GRAD:
case GF_TICK:
if (!im->gdes[ii].stack)
paintval = 0.0;
} else
if (((long int) gr_time >=
(long int) im->gdes[vidx].start)
- && ((long int) gr_time <=
+ && ((long int) gr_time <
(long int) im->gdes[vidx].end)) {
value = im->gdes[vidx].data[(unsigned long)
floor((double)
return 0;
}
-
+static int find_first_weekday(void){
+ static int first_weekday = -1;
+ if (first_weekday == -1){
+#ifdef HAVE__NL_TIME_WEEK_1STDAY
+ /* according to http://sourceware.org/ml/libc-locales/2009-q1/msg00011.html */
+ long week_1stday_l = (long) nl_langinfo (_NL_TIME_WEEK_1STDAY);
+ if (week_1stday_l == 19971130) first_weekday = 0; /* Sun */
+ else if (week_1stday_l == 19971201) first_weekday = 1; /* Mon */
+ else first_weekday = 1; /* we go for a monday default */
+#else
+ first_weekday = 1;
+#endif
+ }
+ return first_weekday;
+}
/* identify the point where the first gridline, label ... gets placed */
tm. tm_sec = 0;
tm. tm_min = 0;
tm. tm_hour = 0;
- tm. tm_mday -= tm.tm_wday - 1; /* -1 because we want the monday */
+ tm. tm_mday -= tm.tm_wday - find_first_weekday();
- if (tm.tm_wday == 0)
- tm. tm_mday -= 7; /* we want the *previous* monday */
+ if (tm.tm_wday == 0 && find_first_weekday() > 0)
+ tm. tm_mday -= 7; /* we want the *previous* week */
break;
case TMT_MONTH:
break;
case GF_LINE:
case GF_AREA:
+ case GF_GRAD:
case GF_TICK:
graphelement = 1;
break;
prt_fctn != 'r' &&
prt_fctn != 'j' &&
prt_fctn != 'c' &&
+ prt_fctn != 'u' &&
prt_fctn != 's' && prt_fctn != '\0' && prt_fctn != 'g') {
free(legspace);
rrd_set_error
if (prt_fctn == 'c')
leg_x = (double)(legendwidth - fill) / 2.0;
if (prt_fctn == 'r')
- leg_x = legendwidth - fill - border;
+ leg_x = legendwidth - fill + border;
for (ii = mark; ii <= i; ii++) {
if (im->gdes[ii].legend[0] == '\0')
continue; /* skip empty legends */
leg_y += im->text_prop[TEXT_PROP_LEGEND].size * 1.8;
if (prt_fctn == 's')
leg_y -= im->text_prop[TEXT_PROP_LEGEND].size;
+ if (prt_fctn == 'u')
+ leg_y -= im->text_prop[TEXT_PROP_LEGEND].size *1.8;
if(calc_width && (fill > legendwidth)){
legendwidth = fill;
boxV = boxH;
/* shift the box up a bit */
Y0 -= boxV * 0.4;
- if (im->gdes[i].gf == GF_HRULE) { /* [-] */
+
+ if (im->dynamic_labels && im->gdes[i].gf == GF_HRULE) { /* [-] */
cairo_save(im->cr);
cairo_new_path(im->cr);
cairo_set_line_width(im->cr, 1.0);
X0 + boxH, Y0 - boxV / 2,
1.0, im->gdes[i].col);
gfx_close_path(im);
- } else if (im->gdes[i].gf == GF_VRULE) { /* [|] */
+ } else if (im->dynamic_labels && im->gdes[i].gf == GF_VRULE) { /* [|] */
cairo_save(im->cr);
cairo_new_path(im->cr);
cairo_set_line_width(im->cr, 1.0);
X0 + boxH / 2, Y0 - boxV,
1.0, im->gdes[i].col);
gfx_close_path(im);
- } else if (im->gdes[i].gf == GF_LINE) { /* [/] */
+ } else if (im->dynamic_labels && im->gdes[i].gf == GF_LINE) { /* [/] */
cairo_save(im->cr);
cairo_new_path(im->cr);
cairo_set_line_width(im->cr, im->gdes[i].linewidth);
break;
case GF_LINE:
case GF_AREA:
+ case GF_GRAD:
/* fix data points at oo and -oo */
for (ii = 0; ii < im->xsize; ii++) {
if (isinf(im->gdes[i].p_data[ii])) {
cairo_stroke(im->cr);
cairo_restore(im->cr);
} else {
+ double lastx=0;
+ double lasty=0;
int idxI = -1;
double *foreY =
(double *) malloc(sizeof(double) * im->xsize * 2);
[cntI + 1], 4)) {
cntI++;
}
- gfx_new_area(im,
- backX[0], backY[0],
- foreX[0], foreY[0],
- foreX[cntI],
- foreY[cntI], im->gdes[i].col);
- while (cntI < idxI) {
+ if (im->gdes[i].gf != GF_GRAD) {
+ gfx_new_area(im,
+ backX[0], backY[0],
+ foreX[0], foreY[0],
+ foreX[cntI],
+ foreY[cntI], im->gdes[i].col);
+ } else {
+ lastx = foreX[cntI];
+ lasty = foreY[cntI];
+ }
+ while (cntI < idxI) {
lastI = cntI;
cntI++;
while (cntI < idxI
+ 1], 4)) {
cntI++;
}
- gfx_add_point(im, foreX[cntI], foreY[cntI]);
+ if (im->gdes[i].gf != GF_GRAD) {
+ gfx_add_point(im, foreX[cntI], foreY[cntI]);
+ } else {
+ gfx_add_rect_fadey(im,
+ lastx, foreY[0],
+ foreX[cntI], foreY[cntI], lasty,
+ im->gdes[i].col,
+ im->gdes[i].col2,
+ im->gdes[i].gradheight
+ );
+ lastx = foreX[cntI];
+ lasty = foreY[cntI];
+ }
}
- gfx_add_point(im, backX[idxI], backY[idxI]);
+ if (im->gdes[i].gf != GF_GRAD) {
+ gfx_add_point(im, backX[idxI], backY[idxI]);
+ } else {
+ gfx_add_rect_fadey(im,
+ lastx, foreY[0],
+ backX[idxI], backY[idxI], lasty,
+ im->gdes[i].col,
+ im->gdes[i].col2,
+ im->gdes[i].gradheight);
+ lastx = backX[idxI];
+ lasty = backY[idxI];
+ }
while (idxI > 1) {
lastI = idxI;
idxI--;
- 1], 4)) {
idxI--;
}
- gfx_add_point(im, backX[idxI], backY[idxI]);
+ if (im->gdes[i].gf != GF_GRAD) {
+ gfx_add_point(im, backX[idxI], backY[idxI]);
+ } else {
+ gfx_add_rect_fadey(im,
+ lastx, foreY[0],
+ backX[idxI], backY[idxI], lasty,
+ im->gdes[i].col,
+ im->gdes[i].col2,
+ im->gdes[i].gradheight);
+ lastx = backX[idxI];
+ lasty = backY[idxI];
+ }
}
idxI = -1;
drawem = 0;
- gfx_close_path(im);
+ if (im->gdes[i].gf != GF_GRAD)
+ gfx_close_path(im);
}
if (drawem != 0) {
drawem = 0;
im->gdes[im->gdes_c - 1].col.green = 0.0;
im->gdes[im->gdes_c - 1].col.blue = 0.0;
im->gdes[im->gdes_c - 1].col.alpha = 0.0;
+ im->gdes[im->gdes_c - 1].col2.red = 0.0;
+ im->gdes[im->gdes_c - 1].col2.green = 0.0;
+ im->gdes[im->gdes_c - 1].col2.blue = 0.0;
+ im->gdes[im->gdes_c - 1].col2.alpha = 0.0;
+ im->gdes[im->gdes_c - 1].gradheight = 50.0;
im->gdes[im->gdes_c - 1].legend[0] = '\0';
im->gdes[im->gdes_c - 1].format[0] = '\0';
im->gdes[im->gdes_c - 1].strftm = 0;
im->gdes[im->gdes_c - 1].cf = CF_AVERAGE;
im->gdes[im->gdes_c - 1].yrule = DNAN;
im->gdes[im->gdes_c - 1].xrule = 0;
+ im->gdes[im->gdes_c - 1].daemon[0] = 0;
return 0;
}
{
image_desc_t im;
rrd_info_t *grinfo;
+ char *old_locale;
rrd_graph_init(&im);
/* a dummy surface so that we can measure text sizes for placements */
-
+ old_locale = setlocale(LC_NUMERIC, "C");
rrd_graph_options(argc, argv, &im);
if (rrd_test_error()) {
rrd_info_free(im.grinfo);
}
rrd_graph_script(argc, argv, &im, 1);
+ setlocale(LC_NUMERIC, old_locale); /* reenable locale for rendering the graph */
+
if (rrd_test_error()) {
rrd_info_free(im.grinfo);
im_free(&im);
im->draw_x_grid = 1;
im->draw_y_grid = 1;
im->draw_3d_border = 2;
+ im->dynamic_labels = 0;
im->extra_flags = 0;
im->font_options = cairo_font_options_create();
im->forceleftspace = 0;
long long_tmp;
rrd_time_value_t start_tv, end_tv;
long unsigned int color;
- char *old_locale = "";
/* defines for long options without a short equivalent. should be bytes,
and may not collide with (the ASCII value of) short options */
{ "legend-direction", required_argument, 0, 1006},
{ "border", required_argument, 0, 1007},
{ "grid-dash", required_argument, 0, 1008},
+ { "dynamic-labels", no_argument, 0, 1009},
{ 0, 0, 0, 0}
};
/* *INDENT-ON* */
int col_start, col_end;
opt = getopt_long(argc, argv,
- "Aa:B:b:c:Dd:Ee:Ff:G:gh:IiJjL:l:Nn:Bb:oPR:rS:s:T:t:u:v:W:w:X:x:Yy:z",
+ "Aa:B:b:c:Dd:Ee:Ff:G:gh:IiJjL:l:Mm:Nn:oPR:rS:s:T:t:u:v:W:w:X:x:Yy:z",
long_options, &option_index);
if (opt == EOF)
break;
case LONGOPT_UNITS_SI:
if (im->extra_flags & FORCE_UNITS) {
rrd_set_error("--units can only be used once!");
- setlocale(LC_NUMERIC, old_locale);
return;
}
if (strcmp(optarg, "si") == 0)
im->forceleftspace = 1;
break;
case 'T':
- old_locale = setlocale(LC_NUMERIC, "C");
im->tabwidth = atof(optarg);
- setlocale(LC_NUMERIC, old_locale);
break;
case 'S':
- old_locale = setlocale(LC_NUMERIC, "C");
im->step = atoi(optarg);
- setlocale(LC_NUMERIC, old_locale);
break;
case 'N':
im->gridfit = 0;
im->draw_y_grid = 0;
break;
};
- old_locale = setlocale(LC_NUMERIC, "C");
if (sscanf(optarg, "%lf:%d", &im->ygridstep, &im->ylabfact) == 2) {
- setlocale(LC_NUMERIC, old_locale);
if (im->ygridstep <= 0) {
rrd_set_error("grid step must be > 0");
return;
return;
}
} else {
- setlocale(LC_NUMERIC, old_locale);
rrd_set_error("invalid y-grid format");
return;
}
rrd_set_error("expected grid-dash format float:float");
return;
}
- break;
+ break;
+ case 1009: /* enable dynamic labels */
+ im->dynamic_labels = 1;
+ break;
case 1002: /* right y axis */
if(sscanf(optarg,
im->ylegend[150] = '\0';
break;
case 'u':
- old_locale = setlocale(LC_NUMERIC, "C");
im->maxval = atof(optarg);
- setlocale(LC_NUMERIC, old_locale);
break;
case 'l':
- old_locale = setlocale(LC_NUMERIC, "C");
im->minval = atof(optarg);
- setlocale(LC_NUMERIC, old_locale);
break;
case 'b':
im->base = atol(optarg);
double size = 1;
int end;
- old_locale = setlocale(LC_NUMERIC, "C");
if (sscanf(optarg, "%10[A-Z]:%lf%n", prop, &size, &end) >= 2) {
int sindex, propidx;
- setlocale(LC_NUMERIC, old_locale);
if ((sindex = text_prop_conv(prop)) != -1) {
for (propidx = sindex;
propidx < TEXT_PROP_LAST; propidx++) {
return;
}
} else {
- setlocale(LC_NUMERIC, old_locale);
rrd_set_error("invalid text property format");
return;
}
break;
}
case 'm':
- old_locale = setlocale(LC_NUMERIC, "C");
im->zoom = atof(optarg);
- setlocale(LC_NUMERIC, old_locale);
if (im->zoom <= 0.0) {
rrd_set_error("zoom factor must be > 0");
return;
}
} /* while (1) */
- { /* try to connect to rrdcached */
- int status = rrdc_connect(im->daemon_addr);
- if (status != 0) return;
- }
-
pango_cairo_context_set_font_options(pango_layout_get_context(im->layout), im->font_options);
pango_layout_context_changed(im->layout);
double param;
char func[30];
int n;
- char *old_locale;
n = 0;
- old_locale = setlocale(LC_NUMERIC, "C");
sscanf(str, "%le,%29[A-Z]%n", ¶m, func, &n);
- setlocale(LC_NUMERIC, old_locale);
if (n == (int) strlen(str)) { /* matched */
;
} else {