X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fcollectdctl.c;h=0b8d0c1e89ee1547f955c0795bf388d1568eb518;hb=3faf514fd9b869cadda0f895e14e5036313c7781;hp=af413cf38170ba85b8778541ce8197bf6565b909;hpb=d0d5d5fa42cd77042d4c3077bb67cfeb8c9cd701;p=collectd.git diff --git a/src/collectdctl.c b/src/collectdctl.c index af413cf3..0b8d0c1e 100644 --- a/src/collectdctl.c +++ b/src/collectdctl.c @@ -25,19 +25,47 @@ # include "config.h" #endif -#include "libcollectdclient/client.h" +#include +#include +#include +#include +#include #include - #include -#include - -#include -#include -#include - -#include +#if NAN_STATIC_DEFAULT +# include +/* #endif NAN_STATIC_DEFAULT*/ +#elif NAN_STATIC_ISOC +# ifndef __USE_ISOC99 +# define DISABLE_ISOC99 1 +# define __USE_ISOC99 1 +# endif /* !defined(__USE_ISOC99) */ +# include +# if DISABLE_ISOC99 +# undef DISABLE_ISOC99 +# undef __USE_ISOC99 +# endif /* DISABLE_ISOC99 */ +/* #endif NAN_STATIC_ISOC */ +#elif NAN_ZERO_ZERO +# include +# ifdef NAN +# undef NAN +# endif +# define NAN (0.0 / 0.0) +# ifndef isnan +# define isnan(f) ((f) != (f)) +# endif /* !defined(isnan) */ +# ifndef isfinite +# define isfinite(f) (((f) - (f)) == 0.0) +# endif +# ifndef isinf +# define isinf(f) (!isfinite(f) && !isnan(f)) +# endif +#endif /* NAN_ZERO_ZERO */ + +#include "libcollectdclient/collectd/client.h" #define DEFAULT_SOCK LOCALSTATEDIR"/run/"PACKAGE_NAME"-unixsock" @@ -59,6 +87,7 @@ static void exit_usage (const char *name, int status) { " * getval \n" " * flush [timeout=] [plugin=] [identifier=]\n" " * listval\n" + " * putval [interval=] \n" "\nIdentifiers:\n\n" @@ -69,13 +98,6 @@ static void exit_usage (const char *name, int status) { "Hostname defaults to the local hostname if omitted (e.g., uptime/uptime).\n" "No error is returned if the specified identifier does not exist.\n" - "\nExample:\n\n" - - " collectdctl flush plugin=rrdtool identifie=somehost/cpu-0/cpu-wait\n\n" - - "Flushes all CPU wait RRD values of the first CPU of the local host.\n" - "I.e., writes all pending RRD updates of that data-source to disk.\n" - "\n"PACKAGE" "VERSION", http://collectd.org/\n" "by Florian octo Forster \n" "for contributions see `AUTHORS'\n" @@ -245,7 +267,7 @@ static int flush (lcc_connection_t *c, int argc, char **argv) if (strcasecmp (key, "timeout") == 0) { char *endptr = NULL; - timeout = strtol (value, &endptr, 0); + timeout = (int) strtol (value, &endptr, 0); if (endptr == value) { fprintf (stderr, "ERROR: Failed to parse timeout as number: %s.\n", @@ -258,7 +280,7 @@ static int flush (lcc_connection_t *c, int argc, char **argv) } } else if (strcasecmp (key, "plugin") == 0) { - status = array_grow ((void **)&plugins, &plugins_num, + status = array_grow ((void *)&plugins, &plugins_num, sizeof (*plugins)); if (status != 0) BAIL_OUT (status); @@ -266,7 +288,7 @@ static int flush (lcc_connection_t *c, int argc, char **argv) plugins[plugins_num - 1] = value; } else if (strcasecmp (key, "identifier") == 0) { - status = array_grow ((void **)&identifiers, &identifiers_num, + status = array_grow ((void *)&identifiers, &identifiers_num, sizeof (*identifiers)); if (status != 0) BAIL_OUT (status); @@ -277,10 +299,14 @@ static int flush (lcc_connection_t *c, int argc, char **argv) if (status != 0) BAIL_OUT (status); } + else { + fprintf (stderr, "ERROR: flush: Unknown option `%s'.\n", key); + BAIL_OUT (-1); + } } if (plugins_num == 0) { - status = array_grow ((void **)&plugins, &plugins_num, sizeof (*plugins)); + status = array_grow ((void *)&plugins, &plugins_num, sizeof (*plugins)); if (status != 0) BAIL_OUT (status); @@ -362,6 +388,161 @@ static int listval (lcc_connection_t *c, int argc, char **argv) #undef BAIL_OUT } /* listval */ +static int putval (lcc_connection_t *c, int argc, char **argv) +{ + lcc_value_list_t vl = LCC_VALUE_LIST_INIT; + + /* 64 ought to be enough for anybody ;-) */ + value_t values[64]; + int values_types[64]; + size_t values_len = 0; + + int status; + int i; + + assert (strcasecmp (argv[0], "putval") == 0); + + if (argc < 3) { + fprintf (stderr, "ERROR: putval: Missing identifier " + "and/or value list.\n"); + return (-1); + } + + vl.values = values; + vl.values_types = values_types; + + status = parse_identifier (c, argv[1], &vl.identifier); + if (status != 0) + return (status); + + for (i = 2; i < argc; ++i) { + char *tmp; + + tmp = strchr (argv[i], (int)'='); + + if (tmp != NULL) { /* option */ + char *key = argv[i]; + char *value = tmp; + + *value = '\0'; + ++value; + + if (strcasecmp (key, "interval") == 0) { + char *endptr; + + vl.interval = strtol (value, &endptr, 0); + + if (endptr == value) { + fprintf (stderr, "ERROR: Failed to parse interval as number: %s.\n", + value); + return (-1); + } + else if ((endptr != NULL) && (*endptr != '\0')) { + fprintf (stderr, "WARNING: Ignoring trailing garbage after " + "interval: %s.\n", endptr); + } + } + else { + fprintf (stderr, "ERROR: putval: Unknown option `%s'.\n", key); + return (-1); + } + } + else { /* value list */ + char *value; + + tmp = strchr (argv[i], (int)':'); + + if (tmp == NULL) { + fprintf (stderr, "ERROR: putval: Invalid value list: %s.\n", + argv[i]); + return (-1); + } + + *tmp = '\0'; + ++tmp; + + if (strcasecmp (argv[i], "N") == 0) { + vl.time = 0; + } + else { + char *endptr; + + vl.time = strtol (argv[i], &endptr, 0); + + if (endptr == argv[i]) { + fprintf (stderr, "ERROR: Failed to parse time as number: %s.\n", + argv[i]); + return (-1); + } + else if ((endptr != NULL) && (*endptr != '\0')) { + fprintf (stderr, "ERROR: Garbage after time: %s.\n", endptr); + return (-1); + } + } + + values_len = 0; + value = tmp; + while (value != 0) { + char *dot, *endptr; + + tmp = strchr (value, (int)':'); + + if (tmp != NULL) { + *tmp = '\0'; + ++tmp; + } + + /* This is a bit of a hack, but parsing types.db just does not make + * much sense imho -- the server might have different types defined + * anyway. Also, lcc uses the type information for formatting the + * number only, so the real meaning does not matter. -tokkee */ + dot = strchr (value, (int)'.'); + endptr = NULL; + if (strcasecmp (value, "U") == 0) { + values[values_len].gauge = NAN; + values_types[values_len] = LCC_TYPE_GAUGE; + } + else if (dot) { /* floating point value */ + values[values_len].gauge = strtod (value, &endptr); + values_types[values_len] = LCC_TYPE_GAUGE; + } + else { /* integer */ + values[values_len].counter = strtol (value, &endptr, 0); + values_types[values_len] = LCC_TYPE_COUNTER; + } + ++values_len; + + if (endptr == value) { + fprintf (stderr, "ERROR: Failed to parse value as number: %s.\n", + argv[i]); + return (-1); + } + else if ((endptr != NULL) && (*endptr != '\0')) { + fprintf (stderr, "ERROR: Garbage after value: %s.\n", endptr); + return (-1); + } + + value = tmp; + } + + assert (values_len >= 1); + vl.values_len = values_len; + + status = lcc_putval (c, &vl); + if (status != 0) { + fprintf (stderr, "ERROR: %s\n", lcc_strerror (c)); + return (-1); + } + } + } + + if (values_len == 0) { + fprintf (stderr, "ERROR: putval: Missing value list(s).\n"); + return (-1); + } + return (0); +} /* putval */ + int main (int argc, char **argv) { char address[1024] = "unix:"DEFAULT_SOCK; @@ -409,6 +590,8 @@ int main (int argc, char **argv) { status = flush (c, argc - optind, argv + optind); else if (strcasecmp (argv[optind], "listval") == 0) status = listval (c, argc - optind, argv + optind); + else if (strcasecmp (argv[optind], "putval") == 0) + status = putval (c, argc - optind, argv + optind); else { fprintf (stderr, "%s: invalid command: %s\n", argv[0], argv[optind]); return (1);