Tree wide: Use compound literals when dealing with value_t.
[collectd.git] / src / ethstat.c
index 08381a8..f0b8d9f 100644 (file)
@@ -23,9 +23,9 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
-#include "configfile.h"
 #include "utils_avltree.h"
 #include "utils_complain.h"
 
@@ -73,7 +73,7 @@ static int ethstat_add_interface (const oconfig_item_t *ci) /* {{{ */
     return (status);
 
   interfaces_num++;
-  INFO("ethstat plugin: Registred interface %s",
+  INFO("ethstat plugin: Registered interface %s",
       interfaces[interfaces_num - 1]);
 
   return (0);
@@ -83,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)
@@ -96,13 +97,20 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
     return (-1);
   }
 
-  map = malloc (sizeof (*map));
+  key = strdup (ci->values[0].value.string);
+  if (key == NULL)
+  {
+    ERROR ("ethstat plugin: strdup(3) failed.");
+    return (ENOMEM);
+  }
+
+  map = calloc (1, sizeof (*map));
   if (map == NULL)
   {
-    ERROR ("ethstat plugin: malloc(3) failed.");
+    sfree (key);
+    ERROR ("ethstat plugin: calloc failed.");
     return (ENOMEM);
   }
-  memset (map, 0, sizeof (*map));
 
   sstrncpy (map->type, ci->values[1].value.string, sizeof (map->type));
   if (ci->values_num == 3)
@@ -111,27 +119,28 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
 
   if (value_map == NULL)
   {
-    value_map = c_avl_create ((void *) strcmp);
+    value_map = c_avl_create ((int (*) (const void *, const void *)) strcmp);
     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);
   }
 
@@ -140,9 +149,7 @@ static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
 
 static int ethstat_config (oconfig_item_t *ci) /* {{{ */
 {
-  int i;
-
-  for (i = 0; i < ci->children_num; i++)
+  for (int i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
 
@@ -165,7 +172,6 @@ static void ethstat_submit_value (const char *device,
 {
   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;
 
@@ -182,8 +188,7 @@ static void ethstat_submit_value (const char *device,
     return;
   }
 
-  values[0].derive = value;
-  vl.values = values;
+  vl.values = &(value_t) { .derive = value };
   vl.values_len = 1;
 
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -207,19 +212,13 @@ static void ethstat_submit_value (const char *device,
 static int ethstat_read_interface (char *device)
 {
   int fd;
-  struct ifreq req;
-  struct ethtool_drvinfo drvinfo;
   struct ethtool_gstrings *strings;
   struct ethtool_stats *stats;
   size_t n_stats;
   size_t strings_size;
   size_t stats_size;
-  size_t i;
   int status;
 
-  memset (&req, 0, sizeof (req));
-  sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
-
   fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0);
   if (fd < 0)
   {
@@ -229,9 +228,16 @@ static int ethstat_read_interface (char *device)
     return 1;
   }
 
-  memset (&drvinfo, 0, sizeof (drvinfo));
-  drvinfo.cmd = ETHTOOL_GDRVINFO;
-  req.ifr_data = (void *) &drvinfo;
+  struct ethtool_drvinfo drvinfo = {
+    .cmd = ETHTOOL_GDRVINFO
+  };
+
+  struct ifreq req = {
+    .ifr_data = (void *) &drvinfo
+  };
+
+  sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
+
   status = ioctl (fd, SIOCETHTOOL, &req);
   if (status < 0)
   {
@@ -263,7 +269,7 @@ static int ethstat_read_interface (char *device)
     close (fd);
     sfree (strings);
     sfree (stats);
-    ERROR("ethstat plugin: malloc(3) failed.");
+    ERROR("ethstat plugin: malloc failed.");
     return (-1);
   }
 
@@ -300,11 +306,15 @@ static int ethstat_read_interface (char *device)
     return (-1);
   }
 
-  for (i = 0; i < n_stats; i++)
+  for (size_t i = 0; i < n_stats; i++)
   {
-    const char *stat_name;
+    char *stat_name;
 
     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,
@@ -320,18 +330,37 @@ static int ethstat_read_interface (char *device)
 
 static int ethstat_read(void)
 {
-  size_t i;
-
-  for (i = 0; i < interfaces_num; i++)
+  for (size_t i = 0; i < interfaces_num; i++)
     ethstat_read_interface (interfaces[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 : */