X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_graph.c;h=5c739becc9cf8459cbdaf0042f957815ce2cc2b4;hp=f5a63c320f105643b1a91f9526a9d21be5e38b4c;hb=c6824ca3f64bd2945fa4b6a772ae5322949d399f;hpb=a98fc4d8a1733d6be8eb5d52430491de5305d88b diff --git a/src/rrd_graph.c b/src/rrd_graph.c index f5a63c3..5c739be 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -337,6 +337,12 @@ int im_free( free(im->gdes[i].rpnp); } free(im->gdes); + + for (i = 0; i < DIM(text_prop);i++){ + pango_font_description_free(im->text_prop[i].font_desc); + im->text_prop[i].font_desc = NULL; + } + if (im->font_options) cairo_font_options_destroy(im->font_options); @@ -344,6 +350,8 @@ int im_free( status = cairo_status(im->cr); cairo_destroy(im->cr); } + + if (im->rendered_image) { free(im->rendered_image); } @@ -846,24 +854,24 @@ int data_fetch( } if (!skip) { unsigned long ft_step = im->gdes[i].step; /* ft_step will record what we got from fetch */ - const char *daemon; + const char *rrd_daemon; int status; if (im->gdes[i].daemon[0] != 0) - daemon = im->gdes[i].daemon; + rrd_daemon = im->gdes[i].daemon; else - daemon = im->daemon_addr; + 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 (daemon); + 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 (daemon)) + if (rrdc_is_connected (rrd_daemon)) { status = rrdc_fetch (im->gdes[i].rrd, cf_to_string (im->gdes[i].cf), @@ -1597,8 +1605,12 @@ int print_calc( if (im->gdes[i].strftm) { prline.u_str = (char*)malloc((FMT_LEG_LEN + 2) * sizeof(char)); - strftime(prline.u_str, - FMT_LEG_LEN, im->gdes[i].format, &tmvdef); + if (im->gdes[vidx].vf.never == 1) { + time_clean(prline.u_str, im->gdes[i].format); + } else { + strftime(prline.u_str, + FMT_LEG_LEN, im->gdes[i].format, &tmvdef); + } } else if (bad_format(im->gdes[i].format)) { rrd_set_error ("bad format for PRINT in '%s'", im->gdes[i].format); @@ -1615,8 +1627,12 @@ int print_calc( /* GF_GPRINT */ if (im->gdes[i].strftm) { - strftime(im->gdes[i].legend, - FMT_LEG_LEN, im->gdes[i].format, &tmvdef); + if (im->gdes[vidx].vf.never == 1) { + time_clean(im->gdes[i].legend, im->gdes[i].format); + } else { + strftime(im->gdes[i].legend, + FMT_LEG_LEN, im->gdes[i].format, &tmvdef); + } } else { if (bad_format(im->gdes[i].format)) { rrd_set_error @@ -4060,6 +4076,8 @@ rrd_set_font_desc ( if (font){ strncpy(im->text_prop[prop].font, font, sizeof(text_prop[prop].font) - 1); im->text_prop[prop].font[sizeof(text_prop[prop].font) - 1] = '\0'; + /* if we already got one, drop it first */ + pango_font_description_free(im->text_prop[prop].font_desc); im->text_prop[prop].font_desc = pango_font_description_from_string( font ); }; if (size > 0){ @@ -4153,6 +4171,7 @@ void rrd_graph_init( for (i = 0; i < DIM(text_prop); i++) { im->text_prop[i].size = -1; + im->text_prop[i].font_desc = NULL; rrd_set_font_desc(im,i, deffont ? deffont : text_prop[i].font,text_prop[i].size); } @@ -4167,6 +4186,7 @@ void rrd_graph_init( pango_cairo_update_context(im->cr,context); im->layout = pango_layout_new(context); + g_object_unref (context); // im->layout = pango_cairo_create_layout(im->cr); @@ -4895,6 +4915,7 @@ int vdef_parse( gdes->vf.param = param; gdes->vf.val = DNAN; /* undefined */ gdes->vf.when = 0; /* undefined */ + gdes->vf.never = 1; } else { rrd_set_error ("Parameter '%f' out of range in VDEF '%s'\n", @@ -4916,6 +4937,7 @@ int vdef_parse( gdes->vf.param = DNAN; gdes->vf.val = DNAN; gdes->vf.when = 0; + gdes->vf.never = 1; } else { rrd_set_error ("Function '%s' needs no parameter in VDEF '%s'\n", @@ -4961,6 +4983,7 @@ int vdef_calc( field = round((dst->vf.param * (double)(steps - 1)) / 100.0); dst->vf.val = array[field]; dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; free(array); #if 0 for (step = 0; step < steps; step++) @@ -4994,6 +5017,7 @@ int vdef_calc( field = round( dst->vf.param * (double)(nancount - 1) / 100.0); dst->vf.val = array[field]; dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; free(array); } break; @@ -5004,15 +5028,18 @@ int vdef_calc( if (step == steps) { dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } else { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } while (step != steps) { if (finite(data[step * src->ds_cnt])) { if (data[step * src->ds_cnt] > dst->vf.val) { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } } step++; @@ -5035,9 +5062,11 @@ int vdef_calc( if (dst->vf.op == VDEF_TOTAL) { dst->vf.val = sum * src->step; dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; } else if (dst->vf.op == VDEF_AVERAGE) { dst->vf.val = sum / cnt; dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; } else { average = sum / cnt; sum = 0.0; @@ -5048,10 +5077,12 @@ int vdef_calc( } dst->vf.val = pow(sum / cnt, 0.5); dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; }; } else { dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } } break; @@ -5062,15 +5093,18 @@ int vdef_calc( if (step == steps) { dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } else { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } while (step != steps) { if (finite(data[step * src->ds_cnt])) { if (data[step * src->ds_cnt] < dst->vf.val) { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } } step++; @@ -5087,9 +5121,11 @@ int vdef_calc( if (step == steps) { /* all entries were NaN */ dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } else { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + step * src->step; + dst->vf.never = 0; } break; case VDEF_LAST: @@ -5103,9 +5139,11 @@ int vdef_calc( if (step < 0) { /* all entries were NaN */ dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } else { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } break; case VDEF_LSLSLOPE: @@ -5143,16 +5181,20 @@ int vdef_calc( if (dst->vf.op == VDEF_LSLSLOPE) { dst->vf.val = slope; dst->vf.when = 0; + dst->vf.never = 1; } else if (dst->vf.op == VDEF_LSLINT) { dst->vf.val = y_intercept; dst->vf.when = 0; + dst->vf.never = 1; } else if (dst->vf.op == VDEF_LSLCORREL) { dst->vf.val = correl; dst->vf.when = 0; + dst->vf.never = 1; }; } else { dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } } break; @@ -5201,3 +5243,156 @@ void grinfo_push( im->grinfo = im->grinfo_current; } } + + +void time_clean( + char *result, + char *format) +{ + int j, jj; + +/* Handling based on + - ANSI C99 Specifications http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf + - Single UNIX Specification version 2 http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html + - POSIX:2001/Single UNIX Specification version 3 http://www.opengroup.org/onlinepubs/009695399/functions/strftime.html + - POSIX:2008 Specifications http://www.opengroup.org/onlinepubs/9699919799/functions/strftime.html + Specifications tells + "If a conversion specifier is not one of the above, the behavior is undefined." + + C99 tells + "A conversion specifier consists of a % character, possibly followed by an E or O modifier character (described below), followed by a character that determines the behavior of the conversion specifier. + + POSIX:2001 tells + "A conversion specification consists of a '%' character, possibly followed by an E or O modifier, and a terminating conversion specifier character that determines the conversion specification's behavior." + + POSIX:2008 introduce more complexe behavior that are not handled here. + + According to this, this code will replace: + - % followed by @ by a %@ + - % followed by by a %SPACE + - % followed by . by a %. + - % followed by % by a % + - % followed by t by a TAB + - % followed by E then anything by '-' + - % followed by O then anything by '-' + - % followed by anything else by at least one '-'. More characters may be added to better fit expected output length +*/ + + jj = 0; + for(j = 0; (j < FMT_LEG_LEN - 1) && (jj < FMT_LEG_LEN); j++) { /* we don't need to parse the last char */ + if (format[j] == '%') { + if ((format[j+1] == 'E') || (format[j+1] == 'O')) { + result[jj++] = '-'; + j+=2; /* We skip next 2 following char */ + } else if ((format[j+1] == 'C') || (format[j+1] == 'd') || + (format[j+1] == 'g') || (format[j+1] == 'H') || + (format[j+1] == 'I') || (format[j+1] == 'm') || + (format[j+1] == 'M') || (format[j+1] == 'S') || + (format[j+1] == 'U') || (format[j+1] == 'V') || + (format[j+1] == 'W') || (format[j+1] == 'y')) { + result[jj++] = '-'; + if (jj < FMT_LEG_LEN) { + result[jj++] = '-'; + } + j++; /* We skip the following char */ + } else if (format[j+1] == 'j') { + result[jj++] = '-'; + if (jj < FMT_LEG_LEN - 1) { + result[jj++] = '-'; + result[jj++] = '-'; + } + j++; /* We skip the following char */ + } else if ((format[j+1] == 'G') || (format[j+1] == 'Y')) { + /* Assuming Year on 4 digit */ + result[jj++] = '-'; + if (jj < FMT_LEG_LEN - 2) { + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '-'; + } + j++; /* We skip the following char */ + } else if (format[j+1] == 'R') { + result[jj++] = '-'; + if (jj < FMT_LEG_LEN - 3) { + result[jj++] = '-'; + result[jj++] = ':'; + result[jj++] = '-'; + result[jj++] = '-'; + } + j++; /* We skip the following char */ + } else if (format[j+1] == 'T') { + result[jj++] = '-'; + if (jj < FMT_LEG_LEN - 6) { + result[jj++] = '-'; + result[jj++] = ':'; + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = ':'; + result[jj++] = '-'; + result[jj++] = '-'; + } + j++; /* We skip the following char */ + } else if (format[j+1] == 'F') { + result[jj++] = '-'; + if (jj < FMT_LEG_LEN - 8) { + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '-'; + } + j++; /* We skip the following char */ + } else if (format[j+1] == 'D') { + result[jj++] = '-'; + if (jj < FMT_LEG_LEN - 6) { + result[jj++] = '-'; + result[jj++] = '/'; + result[jj++] = '-'; + result[jj++] = '-'; + result[jj++] = '/'; + result[jj++] = '-'; + result[jj++] = '-'; + } + j++; /* We skip the following char */ + } else if (format[j+1] == 'n') { + result[jj++] = '\r'; + result[jj++] = '\n'; + j++; /* We skip the following char */ + } else if (format[j+1] == 't') { + result[jj++] = '\t'; + j++; /* We skip the following char */ + } else if (format[j+1] == '%') { + result[jj++] = '%'; + j++; /* We skip the following char */ + } else if (format[j+1] == ' ') { + if (jj < FMT_LEG_LEN - 1) { + result[jj++] = '%'; + result[jj++] = ' '; + } + j++; /* We skip the following char */ + } else if (format[j+1] == '.') { + if (jj < FMT_LEG_LEN - 1) { + result[jj++] = '%'; + result[jj++] = '.'; + } + j++; /* We skip the following char */ + } else if (format[j+1] == '@') { + if (jj < FMT_LEG_LEN - 1) { + result[jj++] = '%'; + result[jj++] = '@'; + } + j++; /* We skip the following char */ + } else { + result[jj++] = '-'; + j++; /* We skip the following char */ + } + } else { + result[jj++] = format[j]; + } + } + result[jj] = '\0'; /* We must force the end of the string */ +}