Code

Merge branch 'collectd-5.3'
authorFlorian Forster <octo@collectd.org>
Sat, 13 Jul 2013 09:24:27 +0000 (11:24 +0200)
committerFlorian Forster <octo@collectd.org>
Sat, 13 Jul 2013 09:24:27 +0000 (11:24 +0200)
Conflicts:
src/plugin.c

1  2 
src/plugin.c
src/write_graphite.c

diff --combined src/plugin.c
index 894b0e51d72731ba1f7faab5c032a122063e85be,d3767d1283b9678bec65e8665d5feb7b8c64bef7..2ad866e3bb2fbcb44012ff997b62932563bdd349
@@@ -61,7 -61,7 +61,7 @@@ struct read_func_
  #define rf_ctx rf_super.cf_ctx
        callback_func_t rf_super;
        char rf_group[DATA_MAX_NAME_LEN];
 -      char rf_name[DATA_MAX_NAME_LEN];
 +      char *rf_name;
        int rf_type;
        cdtime_t rf_interval;
        cdtime_t rf_effective_interval;
@@@ -81,8 -81,6 +81,8 @@@ struct write_queue_
  /*
   * Private variables
   */
 +static c_avl_tree_t *plugins_loaded = NULL;
 +
  static llist_t *list_init;
  static llist_t *list_write;
  static llist_t *list_flush;
@@@ -439,7 -437,6 +439,7 @@@ static void *plugin_read_thread (void _
                {
                        DEBUG ("plugin_read_thread: Destroying the `%s' "
                                        "callback.", rf->rf_name);
 +                      sfree (rf->rf_name);
                        destroy_callback ((callback_func_t *) rf);
                        rf = NULL;
                        continue;
@@@ -833,52 -830,8 +833,52 @@@ void plugin_set_dir (const char *dir
        }
  }
  
 +static _Bool plugin_is_loaded (char const *name)
 +{
 +      int status;
 +
 +      if (plugins_loaded == NULL)
 +              plugins_loaded = c_avl_create ((void *) strcasecmp);
 +      assert (plugins_loaded != NULL);
 +
 +      status = c_avl_get (plugins_loaded, name, /* ret_value = */ NULL);
 +      return (status == 0);
 +}
 +
 +static int plugin_mark_loaded (char const *name)
 +{
 +      char *name_copy;
 +      int status;
 +
 +      name_copy = strdup (name);
 +      if (name_copy == NULL)
 +              return (ENOMEM);
 +
 +      status = c_avl_insert (plugins_loaded,
 +                      /* key = */ name_copy, /* value = */ NULL);
 +      return (status);
 +}
 +
 +static void plugin_free_loaded ()
 +{
 +      void *key;
 +      void *value;
 +
 +      if (plugins_loaded == NULL)
 +              return;
 +
 +      while (c_avl_pick (plugins_loaded, &key, &value) == 0)
 +      {
 +              sfree (key);
 +              assert (value == NULL);
 +      }
 +
 +      c_avl_destroy (plugins_loaded);
 +      plugins_loaded = NULL;
 +}
 +
  #define BUFSIZE 512
 -int plugin_load (const char *type, uint32_t flags)
 +int plugin_load (char const *plugin_name, uint32_t flags)
  {
        DIR  *dh;
        const char *dir;
        struct dirent *de;
        int status;
  
 +      if (plugin_name == NULL)
 +              return (EINVAL);
 +
 +      /* Check if plugin is already loaded and don't do anything in this
 +       * case. */
 +      if (plugin_is_loaded (plugin_name))
 +              return (0);
 +
        dir = plugin_get_dir ();
        ret = 1;
  
 +      /*
 +       * XXX: Magic at work:
 +       *
 +       * Some of the language bindings, for example the Python and Perl
 +       * plugins, need to be able to export symbols to the scripts they run.
 +       * For this to happen, the "Globals" flag needs to be set.
 +       * Unfortunately, this technical detail is hard to explain to the
 +       * average user and she shouldn't have to worry about this, ideally.
 +       * So in order to save everyone's sanity use a different default for a
 +       * handful of special plugins. --octo
 +       */
 +      if ((strcasecmp ("perl", plugin_name) == 0)
 +                      || (strcasecmp ("python", plugin_name) == 0))
 +              flags |= PLUGIN_FLAGS_GLOBAL;
 +
        /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
         * type when matching the filename */
 -      status = ssnprintf (typename, sizeof (typename), "%s.so", type);
 +      status = ssnprintf (typename, sizeof (typename), "%s.so", plugin_name);
        if ((status < 0) || ((size_t) status >= sizeof (typename)))
        {
 -              WARNING ("plugin_load: Filename too long: \"%s.so\"", type);
 +              WARNING ("plugin_load: Filename too long: \"%s.so\"", plugin_name);
                return (-1);
        }
        typename_len = strlen (typename);
                if (status == 0)
                {
                        /* success */
 +                      plugin_mark_loaded (plugin_name);
                        ret = 0;
                        break;
                }
                else
                {
                        ERROR ("plugin_load: Load plugin \"%s\" failed with "
 -                                      "status %i.", type, status);
 +                                      "status %i.", plugin_name, status);
                }
        }
  
  
        if (filename[0] == 0)
                ERROR ("plugin_load: Could not find plugin \"%s\" in %s",
 -                              type, dir);
 +                              plugin_name, dir);
  
        return (ret);
  }
@@@ -1119,7 -1048,7 +1119,7 @@@ int plugin_register_read (const char *n
        rf->rf_udata.free_func = NULL;
        rf->rf_ctx = plugin_get_ctx ();
        rf->rf_group[0] = '\0';
 -      sstrncpy (rf->rf_name, name, sizeof (rf->rf_name));
 +      rf->rf_name = strdup (name);
        rf->rf_type = RF_SIMPLE;
        rf->rf_interval = plugin_get_interval ();
  
@@@ -1151,7 -1080,7 +1151,7 @@@ int plugin_register_complex_read (cons
                sstrncpy (rf->rf_group, group, sizeof (rf->rf_group));
        else
                rf->rf_group[0] = '\0';
 -      sstrncpy (rf->rf_name, name, sizeof (rf->rf_name));
 +      rf->rf_name = strdup (name);
        rf->rf_type = RF_COMPLEX;
        if (interval != NULL)
                rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval);
@@@ -1206,6 -1135,27 +1206,27 @@@ int plugin_register_shutdown (const cha
                                (void *) callback, /* user_data = */ NULL));
  } /* int plugin_register_shutdown */
  
+ static void plugin_free_data_sets (void)
+ {
+       void *key;
+       void *value;
+       if (data_sets == NULL)
+               return;
+       while (c_avl_pick (data_sets, &key, &value) == 0)
+       {
+               data_set_t *ds = value;
+               /* key is a pointer to ds->type */
+               sfree (ds->ds);
+               sfree (ds);
+       }
+       c_avl_destroy (data_sets);
+       data_sets = NULL;
+ } /* void plugin_free_data_sets */
  int plugin_register_data_set (const data_set_t *ds)
  {
        data_set_t *ds_copy;
@@@ -1729,7 -1679,7 +1750,8 @@@ void plugin_shutdown_all (void
        destroy_all_callbacks (&list_shutdown);
        destroy_all_callbacks (&list_log);
  
 +      plugin_free_loaded ();
+       plugin_free_data_sets ();
  } /* void plugin_shutdown_all */
  
  int plugin_dispatch_missing (const value_list_t *vl) /* {{{ */
diff --combined src/write_graphite.c
index c1a11df2d0911175b3b512fa21829c7d2139b68f,99c6f4d80a91a669ee0ac86f0bfe0620de6bb13f..6124d33edf5a07ae26f922b1cc7a151a959b6c28
@@@ -35,8 -35,6 +35,8 @@@
    *   <Carbon>
    *     Host "localhost"
    *     Port "2003"
 +  *     Protocol "udp"
 +  *     LogSendErrors true
    *     Prefix "collectd"
    *   </Carbon>
    * </Plugin>
  # define WG_DEFAULT_SERVICE "2003"
  #endif
  
 +#ifndef WG_DEFAULT_PROTOCOL
 +# define WG_DEFAULT_PROTOCOL "udp"
 +#endif
 +
 +#ifndef WG_DEFAULT_LOG_SEND_ERRORS
 +# define WG_DEFAULT_LOG_SEND_ERRORS 1
 +#endif
 +
  #ifndef WG_DEFAULT_ESCAPE
  # define WG_DEFAULT_ESCAPE '_'
  #endif
@@@ -94,8 -84,6 +94,8 @@@ struct wg_callbac
  
      char    *node;
      char    *service;
 +    char    *protocol;
 +    _Bool   log_send_errors;
      char    *prefix;
      char    *postfix;
      char     escape_char;
@@@ -128,11 -116,10 +128,11 @@@ static int wg_send_buffer (struct wg_ca
      ssize_t status = 0;
  
      status = swrite (cb->sock_fd, cb->send_buf, strlen (cb->send_buf));
 -    if (status < 0)
 +    if (cb->log_send_errors && status < 0)
      {
          char errbuf[1024];
 -        ERROR ("write_graphite plugin: send failed with status %zi (%s)",
 +        ERROR ("write_graphite plugin: send to %s:%s (%s) failed with status %zi (%s)",
 +                cb->node, cb->service, cb->protocol,
                  status, sstrerror (errno, errbuf, sizeof (errbuf)));
  
  
@@@ -186,7 -173,6 +186,7 @@@ static int wg_callback_init (struct wg_
  
      const char *node = cb->node ? cb->node : WG_DEFAULT_NODE;
      const char *service = cb->service ? cb->service : WG_DEFAULT_SERVICE;
 +    const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
  
      if (cb->sock_fd > 0)
          return (0);
      ai_hints.ai_flags |= AI_ADDRCONFIG;
  #endif
      ai_hints.ai_family = AF_UNSPEC;
 -    ai_hints.ai_socktype = SOCK_STREAM;
 +
 +    if (0 == strcasecmp ("tcp", protocol))
 +        ai_hints.ai_socktype = SOCK_STREAM;
 +    else
 +        ai_hints.ai_socktype = SOCK_DGRAM;
  
      ai_list = NULL;
  
      status = getaddrinfo (node, service, &ai_hints, &ai_list);
      if (status != 0)
      {
 -        ERROR ("write_graphite plugin: getaddrinfo (%s, %s) failed: %s",
 -                node, service, gai_strerror (status));
 +        ERROR ("write_graphite plugin: getaddrinfo (%s, %s, %s) failed: %s",
 +                node, service, protocol, gai_strerror (status));
          return (-1);
      }
  
      {
          char errbuf[1024];
          c_complain (LOG_ERR, &cb->init_complaint,
 -                "write_graphite plugin: Connecting to %s:%s failed. "
 -                "The last error was: %s", node, service,
 +                "write_graphite plugin: Connecting to %s:%s via %s failed. "
 +                "The last error was: %s", node, service, protocol,
                  sstrerror (errno, errbuf, sizeof (errbuf)));
-         close (cb->sock_fd);
          return (-1);
      }
      else
      {
          c_release (LOG_INFO, &cb->init_complaint,
 -                "write_graphite plugin: Successfully connected to %s:%s.",
 -                node, service);
 +                "write_graphite plugin: Successfully connected to %s:%s via %s.",
 +                node, service, protocol);
      }
  
      wg_reset_buffer (cb);
@@@ -268,12 -249,14 +267,15 @@@ static void wg_callback_free (void *dat
  
      wg_flush_nolock (/* timeout = */ 0, cb);
  
-     close(cb->sock_fd);
-     cb->sock_fd = -1;
+     if (cb->sock_fd >= 0)
+     {
+         close (cb->sock_fd);
+         cb->sock_fd = -1;
+     }
  
      sfree(cb->name);
      sfree(cb->node);
 +    sfree(cb->protocol);
      sfree(cb->service);
      sfree(cb->prefix);
      sfree(cb->postfix);
@@@ -354,10 -337,9 +356,10 @@@ static int wg_send_message (char const 
      cb->send_buf_fill += message_len;
      cb->send_buf_free -= message_len;
  
 -    DEBUG ("write_graphite plugin: [%s]:%s buf %zu/%zu (%.1f %%) \"%s\"",
 +    DEBUG ("write_graphite plugin: [%s]:%s (%s) buf %zu/%zu (%.1f %%) \"%s\"",
              cb->node,
              cb->service,
 +            cb->protocol,
              cb->send_buf_fill, sizeof (cb->send_buf),
              100.0 * ((double) cb->send_buf_fill) / ((double) sizeof (cb->send_buf)),
              message);
@@@ -387,12 -369,9 +389,9 @@@ static int wg_write_messages (const dat
          return (status);
  
      /* Send the message to graphite */
-     wg_send_message (buffer, cb);
-     if (status != 0)
-     {
-         /* An error message has already been printed. */
+     status = wg_send_message (buffer, cb);
+     if (status != 0) /* error message has been printed already. */
          return (status);
-     }
  
      return (0);
  } /* int wg_write_messages */
@@@ -450,7 -429,6 +449,7 @@@ static int wg_config_node (oconfig_item
      user_data_t user_data;
      char callback_name[DATA_MAX_NAME_LEN];
      int i;
 +    int status = 0;
  
      cb = malloc (sizeof (*cb));
      if (cb == NULL)
      cb->name = NULL;
      cb->node = NULL;
      cb->service = NULL;
 +    cb->protocol = NULL;
 +    cb->log_send_errors = WG_DEFAULT_LOG_SEND_ERRORS;
      cb->prefix = NULL;
      cb->postfix = NULL;
      cb->escape_char = WG_DEFAULT_ESCAPE;
      /* FIXME: Legacy configuration syntax. */
      if (strcasecmp ("Carbon", ci->key) != 0)
      {
 -        int status = cf_util_get_string (ci, &cb->name);
 +        status = cf_util_get_string (ci, &cb->name);
          if (status != 0)
          {
              wg_callback_free (cb);
              cf_util_get_string (child, &cb->node);
          else if (strcasecmp ("Port", child->key) == 0)
              cf_util_get_service (child, &cb->service);
 +        else if (strcasecmp ("Protocol", child->key) == 0)
 +        {
 +            cf_util_get_string (child, &cb->protocol);
 +
 +            if (strcasecmp ("UDP", cb->protocol) != 0 &&
 +                strcasecmp ("TCP", cb->protocol) != 0)
 +            {
 +                ERROR ("write_graphite plugin: Unknown protocol (%s)",
 +                        cb->protocol);
 +                status = -1;
 +            }
 +        }
 +        else if (strcasecmp ("LogSendErrors", child->key) == 0)
 +            cf_util_get_boolean (child, &cb->log_send_errors);
          else if (strcasecmp ("Prefix", child->key) == 0)
              cf_util_get_string (child, &cb->prefix);
          else if (strcasecmp ("Postfix", child->key) == 0)
          {
              ERROR ("write_graphite plugin: Invalid configuration "
                          "option: %s.", child->key);
 +            status = -1;
          }
 +
 +        if (status != 0)
 +            break;
 +    }
 +
 +    if (status != 0)
 +    {
 +        wg_callback_free (cb);
 +        return (status);
      }
  
      /* FIXME: Legacy configuration syntax. */
      if (cb->name == NULL)
 -        ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s/%s",
 +        ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s/%s/%s",
                  cb->node != NULL ? cb->node : WG_DEFAULT_NODE,
 -                cb->service != NULL ? cb->service : WG_DEFAULT_SERVICE);
 +                cb->service != NULL ? cb->service : WG_DEFAULT_SERVICE,
 +                cb->protocol != NULL ? cb->protocol : WG_DEFAULT_PROTOCOL);
      else
          ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s",
                  cb->name);