exec and unixsock plugin: Move the shared `PUTVAL' code into src/utils_cmd_putval...
authorFlorian Forster <octo@crystal.wlan.home.verplant.org>
Thu, 23 Aug 2007 06:05:09 +0000 (08:05 +0200)
committerFlorian Forster <octo@crystal.wlan.home.verplant.org>
Thu, 23 Aug 2007 06:05:09 +0000 (08:05 +0200)
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.

src/Makefile.am
src/collectd-exec.pod
src/collectd-unixsock.pod
src/exec.c
src/plugin.c
src/unixsock.c
src/utils_cmd_putval.c [new file with mode: 0644]
src/utils_cmd_putval.h [new file with mode: 0644]

index 32d1a58..234ad6d 100644 (file)
@@ -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
index 0baf2eb..eaa4f8b 100644 (file)
@@ -36,25 +36,48 @@ Each line beginning with a C<#> (hash mark) is ignored.
 
 =item
 
-Other lines must consist of an I<Identifier> and a I<Value-List>, separated by
-a space. A description of these two parts follows:
+Other lines must consist of an I<Identifier>, an optional I<Option-List> and a
+I<Value-List>, separated by a spaces. A description of these two parts follows:
 
 An I<Identifier> is of the form
 C<I<host>B</>I<plugin>B<->I<instance>B</>I<type>B<->I<instance>> with both
 I<instance>-parts being optional. If they're omitted the hyphen must be
 omitted, too.
 
-A I<Value-List> is a colon-separated list of values, prepended by the time
-stamp in epoch, i.E<nbsp>e. the same format RRDTool uses, see L<rrdupdate(1)>.
-As with the argument passed to RRDTool you can use B<N> as the current time and
-B<U> for undefined values. However, undefined values can only passed for
-B<GAUGE> values. When setting B<U> for a B<COUNTER> data source the behavior is
-undefined.
+The I<OptionList> is an optional list of I<Options>, 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<Valuelist> 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<U>. When
+submitting B<U> to a counter the behavior is undefined. The time is given as
+epoch (i.E<nbsp>e. 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<all> following values, so you don't need
+to re-set an option over and over again.
+
+The currently defined B<Options> are:
+
+=over 4
+
+=item B<interval=>I<seconds>
+
+Gives the interval in which the data identified by I<Identifier> is being
+collected.
+
+=back
+
+Please note that this is the same format as used in the B<unixsock plugin>, see
+L<collectd-unixsock(5)>. 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
 
index da4f2b2..b787646 100644 (file)
@@ -69,18 +69,47 @@ Example:
   <- | 1182204284 leeloo/cpu-0/cpu-user
   ...
 
-=item B<PUTVAL> I<Identifier> I<Valuelist>
+=item B<PUTVAL> I<Identifier> [I<OptionList>] I<Valuelist>
 
-Submits a value (identified by I<Identifier>, see below) to the daemon which
-will dispatch it to all it's write-plugins. The I<Valuelist> 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<U>. When submitting B<U> to
-a counter the behavior is undefined. The time is given as epoch (i.E<nbsp>e.
-standard UNIX time).
+Submits one or more values (identified by I<Identifier>, see below) to the
+daemon which will dispatch it to all it's write-plugins.
+
+An I<Identifier> is of the form
+C<I<host>B</>I<plugin>B<->I<instance>B</>I<type>B<->I<instance>> with both
+I<instance>-parts being optional. If they're omitted the hyphen must be
+omitted, too.
+
+The I<OptionList> is an optional list of I<Options>, 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<Valuelist> 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<U>. When
+submitting B<U> to a counter the behavior is undefined. The time is given as
+epoch (i.E<nbsp>e. 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<all> following values, so you don't need
+to re-set an option over and over again.
+
+The currently defined B<Options> are:
+
+=over 4
+
+=item B<interval=>I<seconds>
+
+Gives the interval in which the data identified by I<Identifier> is being
+collected.
+
+=back
+
+Please note that this is the same format as used in the B<exec plugin>, see
+L<collectd-exec(5)>.
 
 Example:
-  -> | PUTVAL testhost/interface/if_octets-test0 1179574444:123:456
+  -> | PUTVAL testhost/interface/if_octets-test0 interval=10 1179574444:123:456
   <- | 0 Success
 
 =back
index d726f70..058e7c4 100644 (file)
@@ -22,6 +22,7 @@
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
+#include "utils_cmd_putval.h"
 
 #include <sys/types.h>
 #include <pwd.h>
@@ -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)
index 6272581..bed26f0 100644 (file)
@@ -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
index 82c15a8..ddb3a52 100644 (file)
@@ -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 <pthread.h>
@@ -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 (file)
index 0000000..7b8c70f
--- /dev/null
@@ -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 <octo at verplant.org>
+ **/
+
+#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 (file)
index 0000000..609efcb
--- /dev/null
@@ -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 <octo at verplant.org>
+ **/
+
+#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 */