Hello list,
As advice me Kevin, I post you my code to add the CREATE method to
RRDcached.
As I am a well experimented coder, I would be really grateful if I could
get some advices to improve this code (and I hope it will be commited when
clean).
You'll find enclosed the path to get this new feature. (It was down on the
yesterday svn snapshot.)
Yann
On Wed, 7 Jan 2009 20:59:22 -0600, kevin brintnall <[email protected]>
wrote:
> On Mon, Jan 05, 2009 at 11:13:47AM -0600, kevin brintnall wrote:
>> Syntax-checking the CREATE check would probably require separating out
>> some of the code from rrd_update_r.
>
> Sorry, just noticed... I meant "... code from rrd_create_r".
>
> --
> kevin brintnall =~ /[email protected]/
--- ./src/rrd_client.c 2008-10-17 07:50:22.000000000 +0200
+++ ../rrdtool-1.3.99909021600working/src/rrd_client.c 2009-02-17 17:15:45.000000000 +0100
@@ -508,6 +508,70 @@
return (0);
} /* }}} int rrdc_disconnect */
+int rrdc_create (const char *filename, unsigned long pdp_step, time_t last_up, int values_num, /* {{{ */
+ const char * const *values)
+{
+ char buffer[4096];
+ char *buffer_ptr;
+ char str_tmp[32];
+ size_t buffer_free;
+ size_t buffer_size;
+ rrdc_response_t *res;
+ int status;
+ int i;
+
+ char file_path[PATH_MAX];
+
+ memset (buffer, 0, sizeof (buffer));
+ buffer_ptr = &buffer[0];
+ buffer_free = sizeof (buffer);
+
+ status = buffer_add_string ("create", &buffer_ptr, &buffer_free);
+ if (status != 0)
+ return (ENOBUFS);
+
+ /* change to absolute path for rrdcached */
+ if (*filename != '/' && realpath(filename, file_path) != NULL)
+ filename = file_path;
+
+ status = buffer_add_string (filename, &buffer_ptr, &buffer_free);
+ if (status != 0)
+ return (ENOBUFS);
+ snprintf(str_tmp, 32, "b:%lu", last_up);
+ status = buffer_add_string (str_tmp, &buffer_ptr, &buffer_free);
+ if (status != 0)
+ return (ENOBUFS);
+ snprintf(str_tmp, 32, "s:%lu", pdp_step);
+ status = buffer_add_string (str_tmp, &buffer_ptr, &buffer_free);
+ if (status != 0)
+ return (ENOBUFS);
+
+
+
+ for (i = 0; i < values_num; i++)
+ {
+ status = buffer_add_value (values[i], &buffer_ptr, &buffer_free);
+ if (status != 0)
+ return (ENOBUFS);
+ }
+
+ assert (buffer_free < sizeof (buffer));
+ buffer_size = sizeof (buffer) - buffer_free;
+ assert (buffer[buffer_size - 1] == ' ');
+ buffer[buffer_size - 1] = '\n';
+
+ res = NULL;
+ status = request (buffer, buffer_size, &res);
+ if (status != 0)
+ return (status);
+
+ status = res->status;
+ response_free (res);
+
+ return (status);
+} /* }}} int rrdc_create */
+
+
int rrdc_update (const char *filename, int values_num, /* {{{ */
const char * const *values)
{
--- ./src/rrd_create.c 2008-11-18 18:19:17.000000000 +0100
+++ ../rrdtool-1.3.99909021600working/src/rrd_create.c 2009-02-17 17:19:21.000000000 +0100
@@ -11,6 +11,8 @@
#include "rrd_tool.h"
#include "rrd_rpncalc.h"
#include "rrd_hw.h"
+#include "rrd_client.h"
+
#include "rrd_is_thread_safe.h"
@@ -39,6 +41,7 @@
struct option long_options[] = {
{"start", required_argument, 0, 'b'},
{"step", required_argument, 0, 's'},
+ {"daemon", required_argument, 0, 'd'},
{0, 0, 0, 0}
};
int option_index = 0;
@@ -49,12 +52,14 @@
char *parsetime_error = NULL;
long long_tmp;
int rc;
+ char *opt_daemon = NULL;
+
optind = 0;
opterr = 0; /* initialize getopt */
while (1) {
- opt = getopt_long(argc, argv, "b:s:", long_options, &option_index);
+ opt = getopt_long(argc, argv, "b:s:d:", long_options, &option_index);
if (opt == EOF)
break;
@@ -81,7 +86,18 @@
}
break;
- case 's':
+ case 'd':
+ if (opt_daemon != NULL)
+ free (opt_daemon);
+ opt_daemon = strdup (optarg);
+ if (opt_daemon == NULL)
+ {
+ rrd_set_error("strdup failed.");
+ goto out;
+ }
+ break;
+
+ case 's':
long_tmp = atol(optarg);
if (long_tmp < 1) {
rrd_set_error("step size should be no less than one second");
@@ -102,9 +118,36 @@
rrd_set_error("need name of an rrd file to create");
return -1;
}
- rc = rrd_create_r(argv[optind],
+
+ { /* try to connect to rrdcached */
+ int status = rrdc_connect(opt_daemon);
+ if (status != 0) return status;
+ }
+
+ if ( !rrdc_is_connected(opt_daemon))
+ {
+ rc = rrd_create_r(argv[optind],
pdp_step, last_up,
argc - optind - 1, (const char **) (argv + optind + 1));
+ }
+ else /* we are connected */
+ {
+ rc = rrdc_create(argv[optind], /*file name*/
+ pdp_step, last_up,
+ argc - optind - 1, /*values number*/
+ (const char **) (argv + optind + 1)); /*values*/
+
+ if (rc > 0)
+ rrd_set_error("Failed sending the values to rrdcached: %s",
+ rrd_strerror (rc));
+ }
+
+ out:
+ if (opt_daemon != NULL)
+ {
+ free (opt_daemon);
+ opt_daemon = NULL;
+ }
return rc;
}
--- ./src/rrd_daemon.c 2008-11-18 18:19:17.000000000 +0100
+++ ../rrdtool-1.3.99909021600working/src/rrd_daemon.c 2009-02-17 15:03:54.000000000 +0100
@@ -971,7 +971,7 @@
*field_ret = field;
return (0);
-} /* }}} int buffer_get_field */
+} /* }}} int //buffer_get_field */
/* if we're restricting writes to the base directory,
* check whether the file falls within the dir
@@ -1140,6 +1140,13 @@
"<num_vals> <filename>\n"
"\n"
};
+
+ char *help_create[2] =
+ {
+ "Help for CREATE\n"
+ ,
+ "Usage: CREATE <filename> <create definition>\n"
+ };
char *help_update[2] =
{
@@ -1202,6 +1209,8 @@
{
if (strcasecmp (command, "update") == 0)
help_text = help_update;
+ else if (strcasecmp (command, "create") == 0)
+ help_text = help_create;
else if (strcasecmp (command, "flush") == 0)
help_text = help_flush;
else if (strcasecmp (command, "flushall") == 0)
@@ -1423,6 +1432,59 @@
return send_response(sock, RESP_OK, "in queue.\n");
} /* }}} int handle_request_queue */
+static int handle_request_create (listen_socket_t *sock,
+ time_t now,
+ char *buffer, size_t buffer_size)
+{
+ int status;
+ char *file;
+ char file_tmp[PATH_MAX];
+ time_t starttime=now-10;
+ unsigned long step = 300;
+ char *argvalues[32];
+ int argc=0;
+
+
+ status = has_privilege(sock, PRIV_HIGH);
+ if (status <= 0)
+ return status;
+ status = buffer_get_field (&buffer, &buffer_size, &file);
+ get_abs_path(&file, file_tmp);
+ if (!check_file_access(file, sock)) return 0;
+
+ if (status != 0)
+ return send_response(sock, RESP_ERR,
+ "Usage: CREATE <filename> [b:starttime] [s:step] <create definition>\n");
+
+ while (buffer_size > 0)
+ {
+ char *value;
+
+ status = buffer_get_field (&buffer, &buffer_size, &value);
+ if (status != 0)
+ {
+ RRDD_LOG (LOG_INFO, "handle_request_create: Error reading field.");
+ break;
+ }
+ if (!strncmp(value, "b:", 2)) {
+ sscanf(value, "b:%d", (int *) &starttime);
+ continue;
+ }
+ if (!strncmp(value, "s:", 2)) {
+ sscanf(value, "s:%lu", &step);
+ continue;
+ }
+ argvalues[argc] = value;
+ argc++;
+ }
+
+ status = rrd_create_r( (const char*) file, step, starttime, argc, (const char **) argvalues);
+ if (status)
+ return send_response(sock, RESP_ERR, "Error while creating rrd (%s)\n",rrd_get_error());
+ else
+ return send_response(sock, RESP_OK, "RRD created successfully (%s)\n", file);
+}
+
static int handle_request_update (listen_socket_t *sock, /* {{{ */
time_t now,
char *buffer, size_t buffer_size)
@@ -1669,6 +1731,8 @@
if (strcasecmp (command, "update") == 0)
return (handle_request_update (sock, now, buffer_ptr, buffer_size));
+ else if (strcasecmp (command, "create") == 0)
+ return (handle_request_create (sock, now, buffer_ptr, buffer_size));
else if (strcasecmp (command, "wrote") == 0 && sock == NULL)
{
/* this is only valid in replay mode */
_______________________________________________
rrd-developers mailing list
[email protected]
https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers