return status;
} /* }}} int rrdc_fetch */
+int rrd_client_tune(
+ rrd_client_t *client,
+ const char *filename, /* {{{ */
+ int argc,
+ const char **argv)
+{
+ char buffer[RRD_CMD_MAX];
+ char *buffer_ptr;
+ size_t buffer_free;
+ size_t buffer_size;
+ rrdc_response_t *res;
+ int status;
+ char *file_path;
+ int i;
+
+ if (client == NULL)
+ return -1;
+ if (filename == NULL) {
+ rrd_set_error("rrdc_tune: no filename specified");
+ return (-1);
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ buffer_ptr = &buffer[0];
+ buffer_free = sizeof(buffer);
+
+ status = buffer_add_string("tune", &buffer_ptr, &buffer_free);
+ if (status != 0) {
+ rrd_set_error("rrdc_tune: out of memory");
+ return (-1);
+ }
+
+ file_path = get_path(client, filename);
+ if (file_path == NULL) {
+ return (-1);
+ }
+
+ status = buffer_add_string(file_path, &buffer_ptr, &buffer_free);
+ free(file_path);
+
+ if (status != 0) {
+ rrd_set_error("rrdc_tune: out of memory");
+ return (-1);
+ }
+
+ status = buffer_add_ulong(argc, &buffer_ptr, &buffer_free);
+ if (status != 0) {
+ rrd_set_error("rrdc_tune: out of memory");
+ return (-1);
+ }
+
+ for (i = 0; i < argc; i++) {
+ if (argv[i]) {
+ status = buffer_add_string(argv[i], &buffer_ptr, &buffer_free);
+ if (status != 0) {
+ rrd_set_error("rrdc_tune: out of memory");
+ return (-1);
+ }
+ }
+ }
+
+ /* buffer ready to send? */
+ 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(client, buffer, buffer_size, &res);
+
+ if (status != 0)
+ return (-1);
+
+ status = res->status;
+ response_free(res);
+ return (status);
+} /* }}} int rrd_client_tune */
+
+int rrdc_tune(
+ const char *filename, /* {{{ */
+ int argc,
+ const char **argv)
+{
+ int status;
+
+ mutex_lock(&lock);
+ status =
+ rrd_client_tune(&default_client, filename, argc, argv);
+ mutex_unlock(&lock);
+ return status;
+} /* }}} int rrdc_tune */
+
/* convenience function; if there is a daemon specified, or if we can
* detect one from the environment, then flush the file. Otherwise, no-op
*/
return rc;
} /* }}} int handle_request_update */
+
+static int handle_request_tune(
+ HANDLER_PROTO)
+{ /* {{{ */
+ int status;
+ char** argv = NULL;
+ int argc, argc_tmp;
+ char* i;
+ int rc;
+ char *file = NULL, *pbuffile;
+ char *tok;
+
+ /* obtain filename */
+ status = buffer_get_field(&buffer, &buffer_size, &pbuffile);
+ if (status != 0) {
+ rc = syntax_error(sock, cmd);
+ goto done;
+ }
+ /* get full pathname */
+ file = get_abs_path(pbuffile);
+ if (file == NULL) {
+ rc = send_response(sock, RESP_ERR, "%s\n", rrd_strerror(ENOMEM));
+ goto done;
+ }
+
+ if (!check_file_access(file, sock)) {
+ rc = send_response(sock, RESP_ERR, "%s: %s\n", file,
+ rrd_strerror(EACCES));
+ goto done;
+ }
+ RRDD_LOG(LOG_INFO, "rrdtune request for %s", file);
+
+ status = buffer_get_field(&buffer, &buffer_size, &i);
+ if (status != 0) {
+ rc = syntax_error(sock, cmd);
+ goto done;
+ }
+ argc = atoi(i);
+ if (argc < 0) {
+ rc = send_response(sock, RESP_ERR, "Invalid argument count specified (%d)\n",
+ argc);
+ goto done;
+ }
+
+ if ((argv = (char **) malloc(argc * sizeof(char*))) == NULL) {
+ rc = send_response(sock, RESP_ERR, "%s\n", rrd_strerror(ENOMEM));
+ goto done;
+ }
+ argc_tmp = 0;
+ while ((status = buffer_get_field(&buffer, &buffer_size, &tok)) == 0
+ && tok) {
+ argv[argc_tmp] = tok;
+ argc_tmp += 1;
+ }
+
+ status = rrd_tune_r(file, argc, (const char **)argv);
+ if (status != 0) {
+ rc = send_response(sock, RESP_ERR, "Got error %s\n", rrd_get_error());
+ goto done;
+ }
+ rc = send_response(sock, RESP_OK, "Success\n");
+ done:
+ free(file);
+ free(argv);
+ return rc;
+}
+
struct fetch_parsed {
char *file;
char *cf;
CMD_CONTEXT_JOURNAL,
NULL,
NULL},
+ {
+ "TUNE",
+ handle_request_tune,
+ CMD_CONTEXT_CLIENT,
+ "TUNE <filename> [options]",
+ "Tunes the given file, takes the parameters as defined in rrdtool"},
{
"FLUSH",
handle_request_flush,
int argc,
char **argv)
{
- rrd_t rrd;
- int matches;
- int optcnt = 0;
- long ds;
- char ds_nam[DS_NAM_SIZE];
- char ds_new[DS_NAM_SIZE];
- long heartbeat;
- double min = 0;
- double max = 0;
- char dst[DST_SIZE];
- int rc = -1;
- int opt_newstep = -1;
- rrd_file_t *rrd_file = NULL;
char *opt_daemon = NULL;
- char double_str[ 41 ] = {0};
const char *in_filename = NULL;
struct optparse_long longopts[] = {
{"heartbeat", 'h', OPTPARSE_REQUIRED},
};
struct optparse options;
int opt;
+ int status = -1;
rrd_thread_init();
- /* Fix CWE-457 */
- memset(&rrd, 0, sizeof(rrd_t));
/* before we open the input RRD, we should flush it from any caching
daemon, because we might totally rewrite it later on */
rrd_clear_error();
}
+ if (rrdc_is_any_connected ())
+ status = rrdc_tune (in_filename, argc, (const char **) argv);
+
+ else
+ status = rrd_tune_r(in_filename, argc, (const char **) argv);
+
+done:
+ if (in_filename && rrdc_is_any_connected()) {
+ // save any errors....
+ char *e = strdup(rrd_get_error());
+ // is it a good idea to just ignore the error ????
+ rrdc_forget(in_filename);
+ rrd_clear_error();
+
+ if (e) {
+ rrd_set_error(e);
+ free(e);
+ } else
+ rrd_set_error("error message was lost (out of memory)");
+ }
+ return status;
+}
+
+int rrd_tune_r(
+ const char* in_filename,
+ int argc,
+ const char **argv)
+{
+ rrd_t rrd;
+ int matches;
+ int optcnt = 0;
+ long ds;
+ char ds_nam[DS_NAM_SIZE];
+ char ds_new[DS_NAM_SIZE];
+ long heartbeat;
+ double min = 0;
+ double max = 0;
+ char dst[DST_SIZE];
+ int rc = -1;
+ int opt_newstep = -1;
+ rrd_file_t *rrd_file = NULL;
+ char double_str[ 41 ] = {0};
+ struct optparse_long longopts[] = {
+ {"heartbeat", 'h', OPTPARSE_REQUIRED},
+ {"minimum", 'i', OPTPARSE_REQUIRED},
+ {"maximum", 'a', OPTPARSE_REQUIRED},
+ {"data-source-type", 'd', OPTPARSE_REQUIRED},
+ {"data-source-rename", 'r', OPTPARSE_REQUIRED},
+ /* added parameter tuning options for aberrant behavior detection */
+ {"deltapos", 'p', OPTPARSE_REQUIRED},
+ {"deltaneg", 'n', OPTPARSE_REQUIRED},
+ {"window-length", 'w', OPTPARSE_REQUIRED},
+ {"failure-threshold", 'f', OPTPARSE_REQUIRED},
+ {"alpha", 'x', OPTPARSE_REQUIRED},
+ {"beta", 'y', OPTPARSE_REQUIRED},
+ {"gamma", 'z', OPTPARSE_REQUIRED},
+ {"gamma-deviation", 'v', OPTPARSE_REQUIRED},
+ {"smoothing-window", 's', OPTPARSE_REQUIRED},
+ {"smoothing-window-deviation", 'S', OPTPARSE_REQUIRED},
+ {"aberrant-reset", 'b', OPTPARSE_REQUIRED},
+ // integration of rrd_modify functionality.
+ {"step", 't', OPTPARSE_REQUIRED},
+ /* unfortunately, '-d' is already taken */
+ {"daemon", 'D', OPTPARSE_REQUIRED},
+ {0}
+ };
+ struct optparse options;
+ int opt;
+
+ /* Fix CWE-457 */
+ memset(&rrd, 0, sizeof(rrd_t));
rrd_init(&rrd);
rrd_file = rrd_open(in_filename, &rrd, RRD_READWRITE | RRD_LOCK |
RRD_READAHEAD | RRD_READVALUES);
options.optind = handle_modify(&rrd, in_filename, options.argc, options.argv, options.optind + 1, opt_newstep);
rc = 0;
done:
- if (in_filename && rrdc_is_any_connected()) {
- // save any errors....
- char *e = strdup(rrd_get_error());
- // is it a good idea to just ignore the error ????
- rrdc_forget(in_filename);
- rrd_clear_error();
-
- if (e) {
- rrd_set_error(e);
- free(e);
- } else
- rrd_set_error("error message was lost (out of memory)");
- }
if (rrd_file) {
rrd_close(rrd_file);
}