Code

csv plugin: set datadir null when free
[collectd.git] / src / ethstat.c
index 7507bd97851cbbb12ee256a1e067fa1196b9343b..dec14f3d148962df3b1aaf41eb1f50f0a7a5f92c 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * 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
@@ -18,6 +19,7 @@
  *
  * Authors:
  *   Cyril Feraudet <cyril at feraudet.com>
+ *   Florian "octo" Forster <octo@collectd.org>
  **/
 
 #include "collectd.h"
@@ -25,6 +27,7 @@
 #include "plugin.h"
 #include "configfile.h"
 #include "utils_avltree.h"
+#include "utils_complain.h"
 
 #if HAVE_SYS_IOCTL_H
 # include <sys/ioctl.h>
@@ -51,6 +54,8 @@ static size_t interfaces_num = 0;
 
 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;
@@ -61,13 +66,14 @@ static int ethstat_add_interface (const oconfig_item_t *ci) /* {{{ */
   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);
@@ -77,6 +83,7 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
 {
   value_map_t *map;
   int status;
+  char *key;
 
   if ((ci->values_num < 2)
       || (ci->values_num > 3)
@@ -90,16 +97,24 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
     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));
 
@@ -109,23 +124,24 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
     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);
   }
 
@@ -144,6 +160,8 @@ static int ethstat_config (oconfig_item_t *ci) /* {{{ */
       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);
@@ -155,6 +173,8 @@ static int ethstat_config (oconfig_item_t *ci) /* {{{ */
 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;
@@ -162,6 +182,16 @@ static void ethstat_submit_value (const char *device,
   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;
@@ -284,10 +314,9 @@ static int ethstat_read_interface (char *device)
   {
     const 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];
+    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]);
   }
@@ -309,10 +338,31 @@ static int ethstat_read(void)
   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 : */