How many digits should rrdtool assume the y-axis labels to be? You
may have to use this option to make enough space once you start
-fideling with the y-axis labeling.
+fiddling with the y-axis labeling.
[B<--units=si>]
[B<-z>|B<--lazy>]
- Only generate the graph if the current graph is out of date or not
- existent.
+ Only generate the graph if the current graph is out of date or not existent.
+ Note, that only the image size will be returned, if you run with lazy even
+ when using graphv.
+
+[B<--daemon> I<address>]
+
+Address of the L<rrdcached(1)> daemon. If specified, a C<flush> command is sent
+to the server before reading the RRD files. This allows the graph to contain
+fresh data even if the daemon is configured to cache values for a long time. To
+specify a UNIX domain socket use the prefix C<unix:>, see example below. Other
+addresses are interpreted as normal network addresses, i.E<nbsp>e. IPv4 or IPv6
+addresses in most cases.
+
+ rrdtool graph [...] --daemon unix:/var/run/rrdcached.sock [...]
+
[B<-f>|B<--imginfo> I<printfstr>]
After the image has been created, the graph function uses printf
See L<rrdgraph_graph> for the exact format.
-=back
-
=head2 graphv
Calling rrdtool with the graphv option will return information in the
Especially the 'graph_*' keys are new. They help applications that want to
know what is where on the graph.
+=head1 ENVIRONMENT VARIABLES
+
+The following environment variables may be used to change the behavior of
+C<rrdtoolE<nbsp>graph>:
+
+=over 4
+
+=item B<RRDCACHED_ADDRESS>
+
+If this environment variable is set it will have the same effect as specifying
+the C<--daemon> option on the command line. If both are present, the command
+line argument takes precedence.
+
+=back
+
=head1 SEE ALSO
L<rrdgraph> gives an overview of how B<rrdtool graph> works.
#endif
#include "rrd_graph.h"
+#include "rrd_client.h"
/* some constant definitions */
if (im == NULL)
return 0;
+
+ if (im->use_rrdcached)
+ {
+ rrdc_disconnect ();
+ im->use_rrdcached = 0;
+ }
+
for (i = 0; i < (unsigned) im->gdes_c; i++) {
if (im->gdes[i].data_first) {
/* careful here, because a single pointer can occur several times */
&im->gdes[i].start,
&im->gdes[i].end,
&ft_step,
+ im->use_rrdcached ? 1 : 0,
&im->gdes[i].ds_cnt,
&im->gdes[i].ds_namv,
&im->gdes[i].data)) == -1) {
PangoFontMap *font_map = pango_cairo_font_map_get_default();
/* if we are lazy and there is nothing to PRINT ... quit now */
- if (lazy && im->prt_c == 0)
+ if (lazy && im->prt_c == 0) {
+ info.u_cnt = im->ximg;
+ grinfo_push(im, sprintf_alloc("image_width"), RD_I_CNT, info);
+ info.u_cnt = im->yimg;
+ grinfo_push(im, sprintf_alloc("image_height"), RD_I_CNT, info);
return 0;
+ }
/* pull the data from the rrd files ... */
if (data_fetch(im) == -1)
return -1;
return -1;
/* calculate and PRINT and GPRINT definitions. We have to do it at
* this point because it will affect the length of the legends
- * if there are no graph elements we stop here ...
+ * if there are no graph elements (i==0) we stop here ...
* if we are lazy, try to quit ...
*/
- i = print_calc(im);
+ i = print_calc(im);
if (i < 0)
return -1;
+
if ((i == 0) || lazy)
return 0;
+
/**************************************************************
*** Calculating sizes and locations became a bit confusing ***
*** so I moved this into a separate function. ***
walker = walker->next;
}
walker = grinfo;
- while (walker) {
+ *xsize = 0;
+ *ysize = 0;
+ *ymin = 0;
+ *ymax = 0;
+ while (walker) {
if (strcmp(walker->key, "image_width") == 0) {
*xsize = walker->value.u_int;
} else if (strcmp(walker->key, "image_height") == 0) {
im->grinfo_current = (rrd_info_t *) NULL;
im->imgformat = IF_PNG;
im->imginfo = NULL;
+ im->use_rrdcached = 0;
im->lazy = 0;
im->logarithmic = 0;
im->maxval = DNAN;
{ "watermark", required_argument, 0, 'W'},
{ "alt-y-mrtg", no_argument, 0, 1000}, /* this has no effect it is just here to save old apps from crashing when they use it */
{ "pango-markup", no_argument, 0, 'P'},
+ { "daemon", required_argument, 0, 'd'},
{ 0, 0, 0, 0}
};
/* *INDENT-ON* */
int col_start, col_end;
opt = getopt_long(argc, argv,
- "s:e:x:y:v:w:h:D:iu:l:rb:oc:n:m:t:f:a:I:zgjFYAMEX:L:S:T:NR:B:W:kP",
+ "s:e:x:y:v:w:h:D:iu:l:rb:oc:n:m:t:f:a:I:zgjFYAMEX:L:S:T:NR:B:W:kPd:",
long_options, &option_index);
if (opt == EOF)
break;
strncpy(im->watermark, optarg, 100);
im->watermark[99] = '\0';
break;
+ case 'd':
+ {
+ int status;
+ if (im->use_rrdcached)
+ {
+ rrd_set_error ("You cannot specify --daemon "
+ "more than once.");
+ return;
+ }
+ status = rrdc_connect (optarg);
+ if (status != 0)
+ {
+ rrd_set_error ("rrdc_connect(%s) failed with status %i.",
+ optarg, status);
+ return;
+ }
+ im->use_rrdcached = 1;
+ break;
+ }
case '?':
if (optopt != 0)
rrd_set_error("unknown option '%c'", optopt);
rrd_set_error("unknown option '%s'", argv[optind - 1]);
return;
}
+ } /* while (1) */
+
+ if (im->use_rrdcached == 0)
+ {
+ char *temp;
+
+ temp = getenv (ENV_RRDCACHED_ADDRESS);
+ if (temp != NULL)
+ {
+ int status;
+
+ status = rrdc_connect (temp);
+ if (status != 0)
+ {
+ rrd_set_error ("rrdc_connect(%s) failed with status %i.",
+ temp, status);
+ return;
+ }
+ im->use_rrdcached = 1;
+ }
}
if (im->logarithmic && im->minval <= 0) {
src = &im->gdes[dst->vidx];
data = src->data + src->ds;
end =
- src->end_orig % src->step ==
- 0 ? src->end_orig : (src->end_orig + src->step -
- src->end_orig % src->step);
+ src->end_orig % (long)src->step ==
+ 0 ? src->end_orig : (src->end_orig + (long)src->step -
+ src->end_orig % (long)src->step);
steps = (end - src->start) / src->step;
#if 0
/*****************************************************************************
* RRDtool 1.3.0 Copyright by Tobi Oetiker, 1997-2008
+ * Copyright by Florian Forster, 2008
*****************************************************************************
* rrd_update.c RRD Update Function
*****************************************************************************
#include "rrd_is_thread_safe.h"
#include "unused.h"
+#include "rrd_client.h"
+
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
/*
* WIN32 does not have gettimeofday and struct timeval. This is a quick and dirty
{
struct option long_options[] = {
{"template", required_argument, 0, 't'},
+ {"daemon", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
int option_index = 0;
int opt;
char *tmplt = NULL;
int rc = -1;
+ char *daemon = NULL;
optind = 0;
opterr = 0; /* initialize getopt */
while (1) {
- opt = getopt_long(argc, argv, "t:", long_options, &option_index);
+ opt = getopt_long(argc, argv, "t:d:", long_options, &option_index);
if (opt == EOF)
break;
tmplt = strdup(optarg);
break;
+ case 'd':
+ if (daemon != NULL)
+ free (daemon);
+ daemon = strdup (optarg);
+ if (daemon == NULL)
+ {
+ rrd_set_error("strdup failed.");
+ goto out;
+ }
+ break;
+
case '?':
rrd_set_error("unknown option '%s'", argv[optind - 1]);
goto out;
goto out;
}
+ if ((tmplt != NULL) && (daemon != NULL))
+ {
+ rrd_set_error("The caching daemon cannot be used together with "
+ "templates yet.");
+ goto out;
+ }
+
+ if ((tmplt == NULL) && (daemon == NULL))
+ {
+ char *temp;
+
+ temp = getenv (ENV_RRDCACHED_ADDRESS);
+ if (temp != NULL)
+ {
+ daemon = strdup (temp);
+ if (daemon == NULL)
+ {
+ rrd_set_error("strdup failed.");
+ goto out;
+ }
+ }
+ }
+
+ if (daemon != NULL)
+ {
+ int status;
+
+ status = rrdc_connect (daemon);
+ if (status != 0)
+ {
+ rrd_set_error("Unable to connect to daemon: %s",
+ (status < 0)
+ ? "Internal error"
+ : rrd_strerror (status));
+ goto out;
+ }
+
+ status = rrdc_update (/* file = */ argv[optind],
+ /* values_num = */ argc - optind - 1,
+ /* values = */ (void *) (argv + optind + 1));
+ if (status != 0)
+ {
+ rrd_set_error("Failed sending the values to the daemon: %s",
+ (status < 0)
+ ? "Internal error"
+ : rrd_strerror (status));
+ }
+
+ rrdc_disconnect ();
+ goto out;
+ } /* if (daemon != NULL) */
+
rc = rrd_update_r(argv[optind], tmplt,
argc - optind - 1, (const char **) (argv + optind + 1));
out:
- free(tmplt);
+ if (tmplt != NULL)
+ {
+ free(tmplt);
+ tmplt = NULL;
+ }
+ if (daemon != NULL)
+ {
+ free (daemon);
+ daemon = NULL;
+ }
return rc;
}
rra_step_cnt, updvals, tmpl_idx, tmpl_cnt,
&pcdp_summary, version, skip_update,
&schedule_smooth) == -1) {
+ if (rrd_test_error()) { /* Should have error string always here */
+ char *save_error;
+
+ /* Prepend file name to error message */
+ if ((save_error = strdup(rrd_get_error())) != NULL) {
+ rrd_set_error("%s: %s", filename, save_error);
+ free(save_error);
+ }
+ }
free(arg_copy);
break;
}