From: Florian Forster Date: Thu, 23 Aug 2007 06:05:09 +0000 (+0200) Subject: exec and unixsock plugin: Move the shared `PUTVAL' code into src/utils_cmd_putval... X-Git-Tag: collectd-4.1.0~29 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=6e779261c08a8996ed476d23638fc62ad867fa5f;p=collectd.git exec and unixsock plugin: Move the shared `PUTVAL' code into src/utils_cmd_putval.[ch]. The putval code itself has been extended to allow `options' which can currently be used to set the interval of the value-list(s) being submitted. Also, submiting multiple value-lists in one command has been implemented. The manpages should be up to date. --- diff --git a/src/Makefile.am b/src/Makefile.am index 32d1a580..234ad6d3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -495,7 +495,7 @@ endif if BUILD_PLUGIN_UNIXSOCK pkglib_LTLIBRARIES += unixsock.la -unixsock_la_SOURCES = unixsock.c +unixsock_la_SOURCES = unixsock.c utils_cmd_putval.h utils_cmd_putval.c unixsock_la_CPPFLAGS = -DLOCALSTATEDIR='"${localstatedir}"' unixsock_la_LDFLAGS = -module -avoid-version -lpthread collectd_LDADD += "-dlopen" unixsock.la diff --git a/src/collectd-exec.pod b/src/collectd-exec.pod index 0baf2ebe..eaa4f8b4 100644 --- a/src/collectd-exec.pod +++ b/src/collectd-exec.pod @@ -36,25 +36,48 @@ Each line beginning with a C<#> (hash mark) is ignored. =item -Other lines must consist of an I and a I, separated by -a space. A description of these two parts follows: +Other lines must consist of an I, an optional I and a +I, separated by a spaces. A description of these two parts follows: An I is of the form CBIB<->IBIB<->I> with both I-parts being optional. If they're omitted the hyphen must be omitted, too. -A I is a colon-separated list of values, prepended by the time -stamp in epoch, i.Ee. the same format RRDTool uses, see L. -As with the argument passed to RRDTool you can use B as the current time and -B for undefined values. However, undefined values can only passed for -B values. When setting B for a B data source the behavior is -undefined. +The I is an optional list of I, where each option if a +key-value-pair. A list of currently understood options can be found below, all +other options will be ignored. + +I is a colon-seperated list of the time and the values, each either +an integer if the data-source is a counter, of a double if the data-source if +of type "gauge". You can submit an undefined gauge-value by using B. When +submitting B to a counter the behavior is undefined. The time is given as +epoch (i.Ee. standard UNIX time). + +You can mix options and values, but the order is important: Options only +effect following values, so specifying an option as last field is allowed, but +useless. Also, an option applies to B following values, so you don't need +to re-set an option over and over again. + +The currently defined B are: + +=over 4 + +=item BI + +Gives the interval in which the data identified by I is being +collected. + +=back + +Please note that this is the same format as used in the B, see +L. There's also a bit more information on identifiers in +case you're confused. Since examples usually let one understand a lot better, here are some: leeloo/cpu-0/cpu-idle N:2299366 - alice/interface/if_octets-eth0 1180647081:421465:479194 + alice/interface/if_octets-eth0 interval=10 1180647081:421465:479194 =back diff --git a/src/collectd-unixsock.pod b/src/collectd-unixsock.pod index da4f2b22..b787646c 100644 --- a/src/collectd-unixsock.pod +++ b/src/collectd-unixsock.pod @@ -69,18 +69,47 @@ Example: <- | 1182204284 leeloo/cpu-0/cpu-user ... -=item B I I +=item B I [I] I -Submits a value (identified by I, see below) to the daemon which -will dispatch it to all it's write-plugins. The I is a -colon-seperated list of the time and the values, each either an integer if the -data-source is a counter, of a double if the data-source if of type "gauge". -You can submit an undefined gauge-value by using B. When submitting B to -a counter the behavior is undefined. The time is given as epoch (i.Ee. -standard UNIX time). +Submits one or more values (identified by I, see below) to the +daemon which will dispatch it to all it's write-plugins. + +An I is of the form +CBIB<->IBIB<->I> with both +I-parts being optional. If they're omitted the hyphen must be +omitted, too. + +The I is an optional list of I, where each option if a +key-value-pair. A list of currently understood options can be found below, all +other options will be ignored. + +I is a colon-seperated list of the time and the values, each either +an integer if the data-source is a counter, of a double if the data-source if +of type "gauge". You can submit an undefined gauge-value by using B. When +submitting B to a counter the behavior is undefined. The time is given as +epoch (i.Ee. standard UNIX time). + +You can mix options and values, but the order is important: Options only +effect following values, so specifying an option as last field is allowed, but +useless. Also, an option applies to B following values, so you don't need +to re-set an option over and over again. + +The currently defined B are: + +=over 4 + +=item BI + +Gives the interval in which the data identified by I is being +collected. + +=back + +Please note that this is the same format as used in the B, see +L. Example: - -> | PUTVAL testhost/interface/if_octets-test0 1179574444:123:456 + -> | PUTVAL testhost/interface/if_octets-test0 interval=10 1179574444:123:456 <- | 0 Success =back diff --git a/src/exec.c b/src/exec.c index d726f708..058e7c4d 100644 --- a/src/exec.c +++ b/src/exec.c @@ -22,6 +22,7 @@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_cmd_putval.h" #include #include @@ -204,80 +205,13 @@ static int fork_child (program_list_t *pl) static int parse_line (char *buffer) { - char *fields[4]; + char *fields[256]; int fields_num; - char *hostname; - char *plugin; - char *plugin_instance; - char *type; - char *type_instance; + fields[0] = "PUTVAL"; + fields_num = strsplit (buffer, &fields[1], STATIC_ARRAY_SIZE(fields) - 1); - const data_set_t *ds; - value_list_t vl = VALUE_LIST_INIT; - - int status; - - fields_num = strsplit (buffer, fields, 4); - if (fields_num != 2) - { - WARNING ("exec plugin: Number of fields is not 2."); - return (-1); - } - - status = parse_identifier (fields[0], &hostname, - &plugin, &plugin_instance, - &type, &type_instance); - if (status != 0) - { - WARNING ("exec plugin: Cannot parse `%s'", fields[0]); - return (-1); - } - - if ((strlen (hostname) >= sizeof (vl.host)) - || (strlen (plugin) >= sizeof (vl.plugin)) - || ((plugin_instance != NULL) - && (strlen (plugin_instance) >= sizeof (vl.plugin_instance))) - || ((type_instance != NULL) - && (strlen (type_instance) >= sizeof (vl.type_instance)))) - { - WARNING ("exec plugin: An identifier is too long."); - return (-1); - } - - strcpy (vl.host, hostname); - strcpy (vl.plugin, plugin); - if (plugin_instance != NULL) - strcpy (vl.plugin_instance, plugin_instance); - if (type_instance != NULL) - strcpy (vl.type_instance, type_instance); - - ds = plugin_get_ds (type); - if (ds == NULL) - { - WARNING ("exec plugin: No such type: `%s'", type); - return (-1); - } - - vl.values_len = ds->ds_num; - vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len); - if (vl.values == NULL) - return (-1); - - /* Sets vl.values and vl.time */ - status = parse_values (fields[1], &vl, ds); - if (status != 0) - { - WARNING ("exec plugin: Cannot parse `%s'", fields[1]); - sfree (vl.values); - return (-1); - } - - plugin_dispatch_values (type, &vl); - - sfree (vl.values); - - return (0); + handle_putval (stdout, fields, fields_num + 1); } /* int parse_line */ static void *exec_read_one (void *arg) diff --git a/src/plugin.c b/src/plugin.c index 6272581f..bed26f0f 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -194,7 +194,7 @@ static void *plugin_read_thread (void *args) rf->wait_time = 86400; NOTICE ("read-function of plugin `%s' " - "failed. Will syspend it for %i " + "failed. Will suspend it for %i " "seconds.", le->key, rf->wait_left); } else diff --git a/src/unixsock.c b/src/unixsock.c index 82c15a82..ddb3a52f 100644 --- a/src/unixsock.c +++ b/src/unixsock.c @@ -23,6 +23,7 @@ #include "common.h" #include "plugin.h" #include "configfile.h" +#include "utils_cmd_putval.h" /* Folks without pthread will need to disable this plugin. */ #include @@ -487,149 +488,6 @@ static int us_handle_getval (FILE *fh, char **fields, int fields_num) return (0); } /* int us_handle_getval */ -static int us_handle_putval (FILE *fh, char **fields, int fields_num) -{ - char *hostname; - char *plugin; - char *plugin_instance; - char *type; - char *type_instance; - int status; - int i; - - const data_set_t *ds; - value_list_t vl = VALUE_LIST_INIT; - - char **value_ptr; - - if (fields_num != 3) - { - DEBUG ("unixsock plugin: Wrong number of fields: %i", fields_num); - fprintf (fh, "-1 Wrong number of fields: Got %i, expected 3.\n", - fields_num); - fflush (fh); - return (-1); - } - - status = parse_identifier (fields[1], &hostname, - &plugin, &plugin_instance, - &type, &type_instance); - if (status != 0) - { - DEBUG ("unixsock plugin: Cannot parse `%s'", fields[1]); - fprintf (fh, "-1 Cannot parse identifier.\n"); - fflush (fh); - return (-1); - } - - if ((strlen (hostname) >= sizeof (vl.host)) - || (strlen (plugin) >= sizeof (vl.plugin)) - || ((plugin_instance != NULL) - && (strlen (plugin_instance) >= sizeof (vl.plugin_instance))) - || ((type_instance != NULL) - && (strlen (type_instance) >= sizeof (vl.type_instance)))) - { - fprintf (fh, "-1 Identifier too long."); - return (-1); - } - - strcpy (vl.host, hostname); - strcpy (vl.plugin, plugin); - if (plugin_instance != NULL) - strcpy (vl.plugin_instance, plugin_instance); - if (type_instance != NULL) - strcpy (vl.type_instance, type_instance); - - { /* parse the time */ - char *t = fields[2]; - char *v = strchr (t, ':'); - if (v == NULL) - { - fprintf (fh, "-1 No time found."); - return (-1); - } - *v = '\0'; v++; - - vl.time = (time_t) atoi (t); - if (vl.time == 0) - vl.time = time (NULL); - - fields[2] = v; - } - - ds = plugin_get_ds (type); - if (ds == NULL) - return (-1); - - value_ptr = (char **) calloc (ds->ds_num, sizeof (char *)); - if (value_ptr == NULL) - { - fprintf (fh, "-1 calloc failed."); - return (-1); - } - - { /* parse the value-list. It's colon-separated. */ - char *dummy; - char *ptr; - char *saveptr; - - i = 0; - dummy = fields[2]; - saveptr = NULL; - while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL) - { - dummy = NULL; - if (i >= ds->ds_num) - { - i = ds->ds_num + 1; - break; - } - value_ptr[i] = ptr; - i++; - } - - if (i != ds->ds_num) - { - sfree (value_ptr); - fprintf (fh, "-1 Number of values incorrect: Got %i, " - "expected %i.", i, ds->ds_num); - return (-1); - } - } /* done parsing the value-list */ - - vl.values_len = ds->ds_num; - vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t)); - if (vl.values == NULL) - { - sfree (value_ptr); - fprintf (fh, "-1 malloc failed."); - return (-1); - } - DEBUG ("value_ptr = 0x%p; vl.values = 0x%p;", (void *) value_ptr, (void *) vl.values); - - for (i = 0; i < ds->ds_num; i++) - { - if (strcmp (value_ptr[i], "U") == 0) - vl.values[i].gauge = NAN; - else if (ds->ds[i].type == DS_TYPE_COUNTER) - vl.values[i].counter = atoll (value_ptr[i]); - else if (ds->ds[i].type == DS_TYPE_GAUGE) - vl.values[i].gauge = atof (value_ptr[i]); - } /* for (i = 2 .. fields_num) */ - - plugin_dispatch_values (type, &vl); - - DEBUG ("value_ptr = 0x%p; vl.values = 0x%p;", (void *) value_ptr, (void *) vl.values); - - sfree (value_ptr); - sfree (vl.values); - - fprintf (fh, "0 Success\n"); - fflush (fh); - - return (0); -} /* int us_handle_putval */ - static int us_handle_listval (FILE *fh, char **fields, int fields_num) { char buffer[1024]; @@ -733,7 +591,7 @@ static void *us_handle_client (void *arg) } else if (strcasecmp (fields[0], "putval") == 0) { - us_handle_putval (fh, fields, fields_num); + handle_putval (fh, fields, fields_num); } else if (strcasecmp (fields[0], "listval") == 0) { diff --git a/src/utils_cmd_putval.c b/src/utils_cmd_putval.c new file mode 100644 index 00000000..7b8c70f8 --- /dev/null +++ b/src/utils_cmd_putval.c @@ -0,0 +1,217 @@ +/** + * collectd - src/utils_cms_putval.c + * Copyright (C) 2007 Florian octo Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Florian octo Forster + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" + +static int parse_value (const data_set_t *ds, value_list_t *vl, + const char *type, + FILE *fh, char *buffer) +{ + char *dummy; + char *ptr; + char *saveptr; + int i; + + char *time_str = buffer; + char *value_str = strchr (time_str, ':'); + if (value_str == NULL) + { + fprintf (fh, "-1 No time found."); + return (-1); + } + *value_str = '\0'; value_str++; + + vl->time = (time_t) atoi (time_str); + if (vl->time == 0) + vl->time = time (NULL); + + i = 0; + dummy = value_str; + saveptr = NULL; + while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL) + { + dummy = NULL; + + if (i >= vl->values_len) + { + i = vl->values_len + 1; + break; + } + + if (strcmp (ptr, "U") == 0) + vl->values[i].gauge = NAN; + else if (ds->ds[i].type == DS_TYPE_COUNTER) + vl->values[i].counter = atoll (ptr); + else if (ds->ds[i].type == DS_TYPE_GAUGE) + vl->values[i].gauge = atof (ptr); + + i++; + } /* while (strtok_r) */ + + if (i != vl->values_len) + { + char identifier[128]; + FORMAT_VL (identifier, sizeof (identifier), vl, ds); + ERROR ("cmd putval: parse_value: " + "Number of values incorrect: " + "Got %i, expected %i. Identifier is `%s'.", + i, vl->values_len, identifier); + fprintf (fh, "-1 Number of values incorrect: " + "Got %i, expected %i.\n", + i, vl->values_len); + return (-1); + } + + plugin_dispatch_values (type, vl); + return (0); +} /* int parse_value */ + +static int parse_option (value_list_t *vl, char *buffer) +{ + char *option = buffer; + char *value; + + if ((vl == NULL) || (option == NULL)) + return (-1); + + value = strchr (option, '='); + if (value == NULL) + return (-1); + *value = '\0'; value++; + + if (strcasecmp ("interval", option) == 0) + { + vl->interval = atoi (value); + if (vl->interval <= 0) + vl->interval = interval_g; + } + else + return (1); + + return (0); +} /* int parse_option */ + +int handle_putval (FILE *fh, char **fields, int fields_num) +{ + char *hostname; + char *plugin; + char *plugin_instance; + char *type; + char *type_instance; + int status; + int i; + + const data_set_t *ds; + value_list_t vl = VALUE_LIST_INIT; + + if (fields_num < 3) + { + DEBUG ("unixsock plugin: Wrong number of fields: %i", + fields_num); + fprintf (fh, "-1 Wrong number of fields: Got %i, " + "expected at least 3.\n", + fields_num); + fflush (fh); + return (-1); + } + + status = parse_identifier (fields[1], &hostname, + &plugin, &plugin_instance, + &type, &type_instance); + if (status != 0) + { + DEBUG ("unixsock plugin: Cannot parse `%s'", fields[1]); + fprintf (fh, "-1 Cannot parse identifier.\n"); + fflush (fh); + return (-1); + } + + if ((strlen (hostname) >= sizeof (vl.host)) + || (strlen (plugin) >= sizeof (vl.plugin)) + || ((plugin_instance != NULL) + && (strlen (plugin_instance) >= sizeof (vl.plugin_instance))) + || ((type_instance != NULL) + && (strlen (type_instance) >= sizeof (vl.type_instance)))) + { + fprintf (fh, "-1 Identifier too long."); + return (-1); + } + + strcpy (vl.host, hostname); + strcpy (vl.plugin, plugin); + if (plugin_instance != NULL) + strcpy (vl.plugin_instance, plugin_instance); + if (type_instance != NULL) + strcpy (vl.type_instance, type_instance); + + ds = plugin_get_ds (type); + if (ds == NULL) + return (-1); + + vl.values_len = ds->ds_num; + vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t)); + if (vl.values == NULL) + { + fprintf (fh, "-1 malloc failed."); + return (-1); + } + + /* All the remaining fields are part of the optionlist. */ + for (i = 2; i < fields_num; i++) + { + if (strchr (fields[i], ':') != NULL) + { + /* It's parse_value's job to write an error to `fh'. + * This is not the case with `parse_option below. + * Neither will write an success message. */ + if (parse_value (ds, &vl, type, fh, fields[i]) != 0) + break; + } + else if (strchr (fields[i], '=') != NULL) + { + if (parse_option (&vl, fields[i]) != 0) + { + fprintf (fh, "-1 Error parsing option `%s'", + fields[i]); + break; + } + } + else + { + WARNING ("cmd putval: handle_putval: " + "Cannot parse field #%i `%s'; " + "Ignoring it.\n", + i, fields[i]); + } + } + /* Done parsing the options. */ + + if (i == fields_num) + fprintf (fh, "0 Success\n"); + fflush (fh); + + sfree (vl.values); + + return (0); +} /* int handle_putval */ + diff --git a/src/utils_cmd_putval.h b/src/utils_cmd_putval.h new file mode 100644 index 00000000..609efcbd --- /dev/null +++ b/src/utils_cmd_putval.h @@ -0,0 +1,29 @@ +/** + * collectd - src/utils_cms_putval.h + * Copyright (C) 2007 Florian octo Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Florian octo Forster + **/ + +#ifndef UTILS_CMD_PUTVAL_H +#define UTILS_CMD_PUTVAL_H 1 + +#include "plugin.h" + +int handle_putval (FILE *fh, char **fields, int fields_num); + +#endif /* UTILS_CMD_PUTVAL_H */