#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>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/poll.h>
#include <grp.h>
# define UNIX_PATH_MAX sizeof (((struct sockaddr_un *)0)->sun_path)
#endif
-#define US_DEFAULT_PATH PREFIX"/var/run/"PACKAGE_NAME"-unixsock"
+#define US_DEFAULT_PATH LOCALSTATEDIR"/run/"PACKAGE_NAME"-unixsock"
/*
* Private data structures
/*
* Functions
*/
-static int parse_identifier (char *str, char **ret_host,
- char **ret_plugin, char **ret_plugin_instance,
- char **ret_type, char **ret_type_instance)
-{
- char *hostname = NULL;
- char *plugin = NULL;
- char *plugin_instance = NULL;
- char *type = NULL;
- char *type_instance = NULL;
-
- hostname = str;
- if (hostname == NULL)
- return (-1);
-
- plugin = strchr (hostname, '/');
- if (plugin == NULL)
- return (-1);
- *plugin = '\0'; plugin++;
-
- type = strchr (plugin, '/');
- if (type == NULL)
- return (-1);
- *type = '\0'; type++;
-
- plugin_instance = strchr (plugin, '-');
- if (plugin_instance != NULL)
- {
- *plugin_instance = '\0';
- plugin_instance++;
- }
-
- type_instance = strchr (type, '-');
- if (type_instance != NULL)
- {
- *type_instance = '\0';
- type_instance++;
- }
-
- *ret_host = hostname;
- *ret_plugin = plugin;
- *ret_plugin_instance = plugin_instance;
- *ret_type = type;
- *ret_type_instance = type_instance;
- return (0);
-} /* int parse_identifier */
-
static value_cache_t *cache_search (const char *name)
{
value_cache_t *vc;
return (vc);
} /* value_cache_t *cache_search */
-static int cache_alloc_name (char *ret, int ret_len,
- const char *hostname,
- const char *plugin, const char *plugin_instance,
- const char *type, const char *type_instance)
-{
- int status;
-
- assert (plugin != NULL);
- assert (type != NULL);
-
- if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0))
- {
- if ((type_instance == NULL) || (strlen (type_instance) == 0))
- status = snprintf (ret, ret_len, "%s/%s/%s",
- hostname, plugin, type);
- else
- status = snprintf (ret, ret_len, "%s/%s/%s-%s",
- hostname, plugin, type, type_instance);
- }
- else
- {
- if ((type_instance == NULL) || (strlen (type_instance) == 0))
- status = snprintf (ret, ret_len, "%s/%s-%s/%s",
- hostname, plugin, plugin_instance, type);
- else
- status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s",
- hostname, plugin, plugin_instance, type, type_instance);
- }
-
- if ((status < 1) || (status >= ret_len))
- return (-1);
- return (0);
-} /* int cache_alloc_name */
-
static int cache_insert (const data_set_t *ds, const value_list_t *vl)
{
/* We're called from `cache_update' so we don't need to lock the mutex */
value_cache_t *vc;
int i;
- DEBUG ("ds->ds_num = %i; vl->values_len = %i;",
- ds->ds_num, vl->values_len);
+ DEBUG ("unixsock plugin: cache_insert: ds->type = %s; ds->ds_num = %i;"
+ " vl->values_len = %i;",
+ ds->type, ds->ds_num, vl->values_len);
+#if COLLECT_DEBUG
assert (ds->ds_num == vl->values_len);
+#else
+ if (ds->ds_num != vl->values_len)
+ {
+ ERROR ("unixsock plugin: ds->type = %s: (ds->ds_num = %i) != "
+ "(vl->values_len = %i)",
+ ds->type, ds->ds_num, vl->values_len);
+ return (-1);
+ }
+#endif
vc = (value_cache_t *) malloc (sizeof (value_cache_t));
if (vc == NULL)
return (-1);
}
- if (cache_alloc_name (vc->name, sizeof (vc->name),
- vl->host, vl->plugin, vl->plugin_instance,
- ds->type, vl->type_instance) != 0)
+ if (FORMAT_VL (vc->name, sizeof (vc->name), vl, ds))
{
pthread_mutex_unlock (&cache_lock);
- ERROR ("unixsock plugin: cache_alloc_name failed.");
+ ERROR ("unixsock plugin: FORMAT_VL failed.");
free (vc->counter);
free (vc->gauge);
free (vc);
value_cache_t *vc;
int i;
- if (cache_alloc_name (name, sizeof (name),
- vl->host,
- vl->plugin, vl->plugin_instance,
- ds->type, vl->type_instance) != 0)
+ if (FORMAT_VL (name, sizeof (name), vl, ds) != 0)
return (-1);
pthread_mutex_lock (&cache_lock);
vc = cache_search (name);
+ /* pthread_mutex_lock is called by cache_insert. */
if (vc == NULL)
return (cache_insert (ds, vl));
assert (vc->values_num == ds->ds_num);
assert (vc->values_num == vl->values_len);
+ /* Avoid floating-point exceptions due to division by zero. */
+ if (vc->time >= vl->time)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ ERROR ("unixsock plugin: vc->time >= vl->time. vc->time = %u; "
+ "vl->time = %u; vl = %s;",
+ (unsigned int) vc->time, (unsigned int) vl->time,
+ name);
+ return (-1);
+ } /* if (vc->time >= vl->time) */
+
/*
* Update the values. This is possibly a lot more that you'd expect
* because we honor min and max values and handle counter overflows here.
} /* while (this != NULL) */
pthread_mutex_unlock (&cache_lock);
-} /* int cache_flush */
+} /* void cache_flush */
static int us_open_socket (void)
{
return (-1);
}
- status = cache_alloc_name (name, sizeof (name),
+ status = format_name (name, sizeof (name),
hostname, plugin, plugin_instance, type, type_instance);
- /* FIXME: Send some response */
if (status != 0)
+ {
+ fprintf (fh, "-1 format_name failed.\n");
return (-1);
+ }
pthread_mutex_lock (&cache_lock);
return (0);
} /* int us_handle_getval */
-static int us_handle_putval (FILE *fh, char **fields, int fields_num)
+static int us_handle_listval (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;
+ char buffer[1024];
+ char **value_list = NULL;
+ int value_list_len = 0;
+ value_cache_t *entry;
+ int i;
- if (fields_num != 3)
+ if (fields_num != 1)
{
- DEBUG ("unixsock plugin: Wrong number of fields: %i", fields_num);
- fprintf (fh, "-1 Wrong number of fields: Got %i, expected 3.\n",
+ DEBUG ("unixsock plugin: us_handle_listval: "
+ "Wrong number of fields: %i", fields_num);
+ fprintf (fh, "-1 Wrong number of fields: Got %i, expected 1.\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);
- }
-
- /* FIXME: Send some response */
- 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))))
- 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)
- 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 *));
- /* FIXME: Send some response */
- if (value_ptr == NULL)
- 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);
- /* FIXME: Send some response */
- return (-1);
- }
- } /* done parsing the value-list */
+ pthread_mutex_lock (&cache_lock);
- vl.values_len = ds->ds_num;
- vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t));
- if (vl.values == NULL)
+ for (entry = cache_head; entry != NULL; entry = entry->next)
{
- sfree (value_ptr);
- return (-1);
- }
- DEBUG ("value_ptr = 0x%p; vl.values = 0x%p;", (void *) value_ptr, (void *) vl.values);
+ char **tmp;
- 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) */
+ snprintf (buffer, sizeof (buffer), "%u %s\n",
+ (unsigned int) entry->time, entry->name);
+ buffer[sizeof (buffer) - 1] = '\0';
+
+ tmp = realloc (value_list, sizeof (char *) * (value_list_len + 1));
+ if (tmp == NULL)
+ continue;
+ value_list = tmp;
- plugin_dispatch_values (type, &vl);
+ value_list[value_list_len] = strdup (buffer);
- DEBUG ("value_ptr = 0x%p; vl.values = 0x%p;", (void *) value_ptr, (void *) vl.values);
+ if (value_list[value_list_len] != NULL)
+ value_list_len++;
+ } /* for (entry) */
- sfree (value_ptr);
- sfree (vl.values);
+ pthread_mutex_unlock (&cache_lock);
- fprintf (fh, "0 Success\n");
+ DEBUG ("unixsock plugin: us_handle_listval: value_list_len = %i", value_list_len);
+ fprintf (fh, "%i Values found\n", value_list_len);
+ for (i = 0; i < value_list_len; i++)
+ fputs (value_list[i], fh);
fflush (fh);
return (0);
-} /* int us_handle_putval */
+} /* int us_handle_listval */
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)
+ {
+ us_handle_listval (fh, fields, fields_num);
}
else
{
- fprintf (fh, "Unknown command: %s\n", fields[0]);
+ fprintf (fh, "-1 Unknown command: %s\n", fields[0]);
fflush (fh);
}
} /* while (fgets) */
close (sock_fd);
sock_fd = -1;
+ status = unlink ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ NOTICE ("unixsock plugin: unlink (%s) failed: %s",
+ (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
+
return ((void *) 0);
} /* void *us_server_thread */
if (listen_thread != (pthread_t) 0)
{
- DEBUG ("unixsock plugin: Sending SIGTERM to listening thread");
pthread_kill (listen_thread, SIGTERM);
- DEBUG ("unixsock plugin: Waiting for thread to terminate");
pthread_join (listen_thread, &ret);
listen_thread = (pthread_t) 0;
}