]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Add support for TUNE command in rrdcached
authorFrançois HORTA <fhorta@scaleway.com>
Mon, 8 Nov 2021 16:35:17 +0000 (17:35 +0100)
committerFrançois HORTA <fhorta@scaleway.com>
Mon, 8 Nov 2021 17:11:57 +0000 (18:11 +0100)
src/librrd.sym
src/rrd.h
src/rrd_client.c
src/rrd_client.h
src/rrd_daemon.c
src/rrd_tune.c

index ee726002951fcd66f1b6e1bf52e1ab73482c8fc0..86b9a6eaf6b9d3e00d24546bc0e4345a938c6ede 100644 (file)
@@ -16,6 +16,8 @@ rrd_dump_r
 rrd_fetch
 rrd_fetch_cb_register
 rrd_fetch_r
+rrd_tune
+rrd_tune_r
 rrd_first
 rrd_first_r
 rrd_flush
index 155cd65eeebb97b1445b17e19685dbd760b470f4..8439413c43432b6c5c28c0de0afeea280e177c5c 100644 (file)
--- a/src/rrd.h
+++ b/src/rrd.h
@@ -303,6 +303,10 @@ extern    "C" {
     unsigned long *ds_cnt,
     char ***ds_namv,
     rrd_value_t **data);
+    int       rrd_tune_r(
+    const char *filename,
+    int argc,
+    const char **argv);
     int       rrd_dump_opt_r(
     const char *filename,
     char *outname,
index f00a73c6abd5162106fb64abe997fd4a0540fa2c..faf462ae598e39ed5191f31ccd08bbab55808549 100644 (file)
@@ -2057,6 +2057,98 @@ int rrdc_fetch(
     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
  */
index fe8f954a35dbfc5d567c253f8d54480b16aa5eb2..1ccb7487b164b268adbc21d8c0353badfbf5f64c 100644 (file)
@@ -103,6 +103,10 @@ int rrd_client_fetch(rrd_client_t *client, const char *filename,
     char ***ret_ds_names,
     rrd_value_t **ret_data);
 
+int rrd_client_tune(rrd_client_t *client, const char *filename,
+    int argc,
+    const char **argv);
+
 int rrd_client_stats_get(rrd_client_t *client, rrdc_stats_t **ret_stats);
 
 /*
@@ -144,6 +148,10 @@ int rrdc_flush_if_daemon (const char *opt_daemon, const char *filename);
 int rrdc_flushall (void);
 int rrdc_flushall_if_daemon (const char *opt_daemon);
 
+int rrdc_tune (const char *filename,
+    int argc,
+    const char **argv);
+
 int rrdc_fetch (const char *filename,
     const char *cf,
     time_t *ret_start, time_t *ret_end,
index 9c36eb1e3b567ad755a149c14bffd6144f2bfe4d..3ad3a66f7f48074486aedcaa53c366198167b394 100644 (file)
@@ -1791,6 +1791,73 @@ static int handle_request_update(
     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;
@@ -2810,6 +2877,12 @@ static command_t list_of_commands[] = { /* {{{ */
      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,
index 10fc6468850a72b26fabdca0b2939faa2dffbb5a..3374dd1d692433a18bb2fe253ba88ae7435e375d 100644 (file)
@@ -73,21 +73,7 @@ int rrd_tune(
     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},
@@ -115,10 +101,9 @@ int rrd_tune(
     };
     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 */
@@ -173,6 +158,77 @@ int rrd_tune(
        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);
@@ -410,19 +466,6 @@ int rrd_tune(
     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);
     }