/**
* collectd - src/ethstat.c
* Copyright (C) 2011 Cyril Feraudet
+ * Copyright (C) 2012 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
*
* Authors:
* Cyril Feraudet <cyril at feraudet.com>
+ * Florian "octo" Forster <octo@collectd.org>
**/
#include "collectd.h"
#include "plugin.h"
#include "configfile.h"
#include "utils_avltree.h"
+#include "utils_complain.h"
#if HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
static c_avl_tree_t *value_map = NULL;
+static _Bool collect_mapped_only = 0;
+
static int ethstat_add_interface (const oconfig_item_t *ci) /* {{{ */
{
char **tmp;
if (tmp == NULL)
return (-1);
interfaces = tmp;
+ interfaces[interfaces_num] = NULL;
status = cf_util_get_string (ci, interfaces + interfaces_num);
if (status != 0)
return (status);
interfaces_num++;
- INFO("ethstat plugin: Registred interface %s",
+ INFO("ethstat plugin: Registered interface %s",
interfaces[interfaces_num - 1]);
return (0);
{
value_map_t *map;
int status;
+ char *key;
if ((ci->values_num < 2)
|| (ci->values_num > 3)
return (-1);
}
+ key = strdup (ci->values[0].value.string);
+ if (key == NULL)
+ {
+ ERROR ("ethstat plugin: strdup(3) failed.");
+ return (ENOMEM);
+ }
+
map = malloc (sizeof (*map));
if (map == NULL)
{
+ sfree (key);
ERROR ("ethstat plugin: malloc(3) failed.");
return (ENOMEM);
}
memset (map, 0, sizeof (*map));
sstrncpy (map->type, ci->values[1].value.string, sizeof (map->type));
- if (ci->values_num == 2)
+ if (ci->values_num == 3)
sstrncpy (map->type_instance, ci->values[2].value.string,
sizeof (map->type_instance));
if (value_map == NULL)
{
sfree (map);
+ sfree (key);
ERROR ("ethstat plugin: c_avl_create() failed.");
return (-1);
}
}
status = c_avl_insert (value_map,
- /* key = */ ci->values[0].value.string,
+ /* key = */ key,
/* value = */ map);
if (status != 0)
{
- sfree (map);
if (status > 0)
- ERROR ("ethstat plugin: Multiple mappings for \"%s\".",
- ci->values[0].value.string);
+ ERROR ("ethstat plugin: Multiple mappings for \"%s\".", key);
else
- ERROR ("ethstat plugin: c_avl_insert(\"%s\") failed.",
- ci->values[0].value.string);
+ ERROR ("ethstat plugin: c_avl_insert(\"%s\") failed.", key);
+
+ sfree (map);
+ sfree (key);
return (-1);
}
ethstat_add_interface (child);
else if (strcasecmp ("Map", child->key) == 0)
ethstat_add_map (child);
+ else if (strcasecmp ("MappedOnly", child->key) == 0)
+ (void) cf_util_get_boolean (child, &collect_mapped_only);
else
WARNING ("ethstat plugin: The config option \"%s\" is unknown.",
child->key);
static void ethstat_submit_value (const char *device,
const char *type_instance, derive_t value)
{
+ static c_complain_t complain_no_map = C_COMPLAIN_INIT_STATIC;
+
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
value_map_t *map = NULL;
if (value_map != NULL)
c_avl_get (value_map, type_instance, (void *) &map);
+ /* If the "MappedOnly" option is specified, ignore unmapped values. */
+ if (collect_mapped_only && (map == NULL))
+ {
+ if (value_map == NULL)
+ c_complain (LOG_WARNING, &complain_no_map,
+ "ethstat plugin: The \"MappedOnly\" option has been set to true, "
+ "but no mapping has been configured. All values will be ignored!");
+ return;
+ }
+
values[0].derive = value;
vl.values = values;
vl.values_len = 1;
for (i = 0; i < n_stats; i++)
{
- const char *stat_name;
+ char *stat_name;
- stat_name = (void *) &strings->data[i * ETH_GSTRING_LEN],
- DEBUG("ethstat plugin: device = \"%s\": %s = %"PRIu64,
- device, stat_name,
- (uint64_t) stats->data[i]);
+ stat_name = (void *) &strings->data[i * ETH_GSTRING_LEN];
+ /* Remove leading spaces in key name */
+ while (isspace ((int) *stat_name))
+ stat_name++;
+
+ DEBUG("ethstat plugin: device = \"%s\": %s = %"PRIu64,
+ device, stat_name, (uint64_t) stats->data[i]);
ethstat_submit_value (device,
stat_name, (derive_t) stats->data[i]);
}
return 0;
}
+static int ethstat_shutdown (void)
+{
+ void *key = NULL;
+ void *value = NULL;
+
+ if (value_map == NULL)
+ return (0);
+
+ while (c_avl_pick (value_map, &key, &value) == 0)
+ {
+ sfree (key);
+ sfree (value);
+ }
+
+ c_avl_destroy (value_map);
+ value_map = NULL;
+
+ return (0);
+}
+
void module_register (void)
{
plugin_register_complex_config ("ethstat", ethstat_config);
plugin_register_read ("ethstat", ethstat_read);
+ plugin_register_shutdown ("ethstat", ethstat_shutdown);
}
/* vim: set sw=2 sts=2 et fdm=marker : */