Merge branch 'collectd-4.10' into collectd-5.1
authorFlorian Forster <octo@collectd.org>
Sat, 16 Mar 2013 12:40:14 +0000 (13:40 +0100)
committerFlorian Forster <octo@collectd.org>
Sat, 16 Mar 2013 12:41:34 +0000 (13:41 +0100)
Conflicts:
src/curl_json.c

1  2 
src/apache.c
src/bind.c
src/curl.c
src/curl_json.c
src/exec.c
src/mysql.c
src/nginx.c
src/write_http.c

diff --combined src/apache.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/apache.c
 - * Copyright (C) 2006-2009  Florian octo Forster
 + * Copyright (C) 2006-2010  Florian octo Forster
   * Copyright (C) 2007       Florent EppO Monbillard
   * Copyright (C) 2009       Amit Gupta
   *
@@@ -144,8 -144,6 +144,8 @@@ static size_t apache_header_callback (v
                st->server_type = APACHE;
        else if (strstr (buf, "lighttpd") != NULL)
                st->server_type = LIGHTTPD;
 +      else if (strstr (buf, "IBM_HTTP_Server") != NULL)
 +              st->server_type = APACHE;
        else
        {
                const char *hdr = buf;
@@@ -335,22 -333,57 +335,22 @@@ static int config (oconfig_item_t *ci
  {
        int status = 0;
        int i;
 -      oconfig_item_t *lci = NULL; /* legacy config */
  
        for (i = 0; i < ci->children_num; i++)
        {
                oconfig_item_t *child = ci->children + i;
  
 -              if (strcasecmp ("Instance", child->key) == 0 && child->children_num > 0)
 +              if (strcasecmp ("Instance", child->key) == 0)
                        config_add (child);
                else
 -              {
 -                      /* legacy mode - convert to <Instance ...> config */
 -                      if (lci == NULL)
 -                      {
 -                              lci = malloc (sizeof(*lci));
 -                              if (lci == NULL)
 -                              {
 -                                      ERROR ("apache plugin: malloc failed.");
 -                                      return (-1);
 -                              }
 -                              memset (lci, '\0', sizeof (*lci));
 -                      }
 -
 -                      lci->children_num++;
 -                      lci->children =
 -                              realloc (lci->children,
 -                                       lci->children_num * sizeof (*child));
 -                      if (lci->children == NULL)
 -                      {
 -                              ERROR ("apache plugin: realloc failed.");
 -                              return (-1);
 -                      }
 -                      memcpy (&lci->children[lci->children_num-1], child, sizeof (*child));
 -              }
 +                      WARNING ("apache plugin: The configuration option "
 +                                      "\"%s\" is not allowed here. Did you "
 +                                      "forget to add an <Instance /> block "
 +                                      "around the configuration?",
 +                                      child->key);
        } /* for (ci->children) */
  
 -      if (lci)
 -      {
 -              /* create a <Instance ""> entry */
 -              lci->key = "Instance";
 -              lci->values_num = 1;
 -              lci->values = (oconfig_value_t *) malloc (lci->values_num * sizeof (oconfig_value_t));
 -              lci->values[0].type = OCONFIG_TYPE_STRING;
 -              lci->values[0].value.string = "";
 -
 -              status = config_add (lci);
 -              sfree (lci->values);
 -              sfree (lci->children);
 -              sfree (lci);
 -      }
 -
 -      return status;
 +      return (status);
  } /* int config */
  
  /* initialize curl for each host */
@@@ -388,8 -421,6 +388,8 @@@ static int init_host (apache_t *st) /* 
                        st->server_type = APACHE;
                else if (strcasecmp(st->server, "lighttpd") == 0)
                        st->server_type = LIGHTTPD;
 +              else if (strcasecmp(st->server, "ibm_http_server") == 0)
 +                      st->server_type = APACHE;
                else
                        WARNING ("apache plugin: Unknown `Server' setting: %s",
                                        st->server);
  
        curl_easy_setopt (st->curl, CURLOPT_URL, st->url);
        curl_easy_setopt (st->curl, CURLOPT_FOLLOWLOCATION, 1L);
+       curl_easy_setopt (st->curl, CURLOPT_MAXREDIRS, 50L);
  
        if (st->verify_peer != 0)
        {
@@@ -477,13 -509,13 +478,13 @@@ static void submit_value (const char *t
        plugin_dispatch_values (&vl);
  } /* void submit_value */
  
 -static void submit_counter (const char *type, const char *type_instance,
 -              counter_t c, apache_t *st)
 +static void submit_derive (const char *type, const char *type_instance,
 +              derive_t c, apache_t *st)
  {
        value_t v;
 -      v.counter = c;
 +      v.derive = c;
        submit_value (type, type_instance, v, st);
 -} /* void submit_counter */
 +} /* void submit_derive */
  
  static void submit_gauge (const char *type, const char *type_instance,
                gauge_t g, apache_t *st)
@@@ -611,7 -643,7 +612,7 @@@ static int apache_read_host (user_data_
        assert (st->curl != NULL);
  
        st->apache_buffer_fill = 0;
-       if (curl_easy_perform (st->curl) != 0)
+       if (curl_easy_perform (st->curl) != CURLE_OK)
        {
                ERROR ("apache: curl_easy_perform failed: %s",
                                st->apache_curl_error);
                {
                        if ((strcmp (fields[0], "Total") == 0)
                                        && (strcmp (fields[1], "Accesses:") == 0))
 -                              submit_counter ("apache_requests", "",
 +                              submit_derive ("apache_requests", "",
                                                atoll (fields[2]), st);
                        else if ((strcmp (fields[0], "Total") == 0)
                                        && (strcmp (fields[1], "kBytes:") == 0))
 -                              submit_counter ("apache_bytes", "",
 +                              submit_derive ("apache_bytes", "",
                                                1024LL * atoll (fields[2]), st);
                }
                else if (fields_num == 2)
diff --combined src/bind.c
@@@ -1,7 -1,7 +1,7 @@@
  /**
   * collectd - src/bind.c
 - * Copyright (C) 2009  Bruno Prémont
 - * Copyright (C) 2009  Florian Forster
 + * Copyright (C) 2009       Bruno Prémont
 + * Copyright (C) 2009,2010  Florian 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:
   *   Bruno Prémont <bonbons at linux-vserver.org>
 - *   Florian Forster <octo at verplant.org>
 + *   Florian Forster <octo at collectd.org>
   **/
  
  #include "config.h"
  
 -#ifndef _XOPEN_SOURCE
 -# define _XOPEN_SOURCE 600 /* glibc2 needs this for strptime */
 -#endif
 +#if STRPTIME_NEEDS_STANDARDS
 +# ifndef _ISOC99_SOURCE
 +#  define _ISOC99_SOURCE 1
 +# endif
 +# ifndef _POSIX_C_SOURCE
 +#  define _POSIX_C_SOURCE 200112L
 +# endif
 +# ifndef _XOPEN_SOURCE
 +#  define _XOPEN_SOURCE 500
 +# endif
 +#endif /* STRPTIME_NEEDS_STANDARDS */
  
  #include "collectd.h"
  #include "common.h"
@@@ -98,10 -90,6 +98,10 @@@ struct list_info_ptr_
  };
  typedef struct list_info_ptr_s list_info_ptr_t;
  
 +/* FIXME: Enabled by default for backwards compatibility. */
 +/* TODO: Remove time parsing code. */
 +static _Bool config_parse_time = 1;
 +
  static char *url                   = NULL;
  static int global_opcodes          = 1;
  static int global_qtypes           = 1;
@@@ -253,8 -241,7 +253,8 @@@ static void submit (time_t ts, const ch
  
    vl.values = values;
    vl.values_len = 1;
 -  vl.time = ts;
 +  if (config_parse_time)
 +    vl.time = TIME_T_TO_CDTIME_T (ts);
    sstrncpy(vl.host, hostname_g, sizeof(vl.host));
    sstrncpy(vl.plugin, "bind", sizeof(vl.plugin));
    if (plugin_instance) {
@@@ -350,31 -337,36 +350,31 @@@ static int bind_xml_list_callback (cons
    return (0);
  } /* }}} int bind_xml_list_callback */
  
 -static int bind_xml_read_counter (xmlDoc *doc, xmlNode *node, /* {{{ */
 -    counter_t *ret_value)
 +static int bind_xml_read_derive (xmlDoc *doc, xmlNode *node, /* {{{ */
 +    derive_t *ret_value)
  {
 -  char *str_ptr, *end_ptr;
 -  long long int value;
 +  char *str_ptr;
 +  value_t value;
 +  int status;
  
    str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
    if (str_ptr == NULL)
    {
 -    ERROR ("bind plugin: bind_xml_read_counter: xmlNodeListGetString failed.");
 +    ERROR ("bind plugin: bind_xml_read_derive: xmlNodeListGetString failed.");
      return (-1);
    }
  
 -  errno = 0;
 -  value = strtoll (str_ptr, &end_ptr, 10);
 -  xmlFree(str_ptr);
 -  if (str_ptr == end_ptr || errno)
 +  status = parse_value (str_ptr, &value, DS_TYPE_DERIVE);
 +  if (status != 0)
    {
 -    if (errno && (value < 0))
 -      ERROR ("bind plugin: bind_xml_read_counter: strtoll failed with underflow.");
 -    else if (errno && (value > 0))
 -      ERROR ("bind plugin: bind_xml_read_counter: strtoll failed with overflow.");
 -    else
 -      ERROR ("bind plugin: bind_xml_read_counter: strtoll failed.");
 +    ERROR ("bind plugin: Parsing string \"%s\" to derive value failed.",
 +        str_ptr);
      return (-1);
    }
  
 -  *ret_value = value;
 +  *ret_value = value.derive;
    return (0);
 -} /* }}} int bind_xml_read_counter */
 +} /* }}} int bind_xml_read_derive */
  
  static int bind_xml_read_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */
      gauge_t *ret_value)
@@@ -535,7 -527,7 +535,7 @@@ static int bind_parse_generic_name_valu
        if (ds_type == DS_TYPE_GAUGE)
          status = bind_xml_read_gauge (doc, counter, &value.gauge);
        else
 -        status = bind_xml_read_counter (doc, counter, &value.counter);
 +        status = bind_xml_read_derive (doc, counter, &value.derive);
        if (status != 0)
          continue;
  
@@@ -608,7 -600,7 +608,7 @@@ static int bind_parse_generic_value_lis
        if (ds_type == DS_TYPE_GAUGE)
          status = bind_xml_read_gauge (doc, child, &value.gauge);
        else
 -        status = bind_xml_read_counter (doc, child, &value.counter);
 +        status = bind_xml_read_derive (doc, child, &value.derive);
        if (status != 0)
          continue;
  
@@@ -1369,8 -1361,6 +1369,8 @@@ static int bind_config (oconfig_item_t 
        bind_config_set_bool ("MemoryStats", &global_memory_stats, child);
      else if (strcasecmp ("View", child->key) == 0)
        bind_config_add_view (child);
 +    else if (strcasecmp ("ParseTime", child->key) == 0)
 +      cf_util_get_boolean (child, &config_parse_time);
      else
      {
        WARNING ("bind plugin: Unknown configuration option "
@@@ -1399,6 -1389,7 +1399,7 @@@ static int bind_init (void) /* {{{ *
    curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, bind_curl_error);
    curl_easy_setopt (curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL);
    curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
+   curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
  
    return (0);
  } /* }}} int bind_init */
@@@ -1414,7 -1405,7 +1415,7 @@@ static int bind_read (void) /* {{{ *
    }
  
    bind_buffer_fill = 0;
-   if (curl_easy_perform (curl) != 0)
+   if (curl_easy_perform (curl) != CURLE_OK)
    {
      ERROR ("bind plugin: curl_easy_perform failed: %s",
          bind_curl_error);
diff --combined src/curl.c
@@@ -378,6 -378,7 +378,7 @@@ static int cc_page_init_curl (web_page_
    curl_easy_setopt (wp->curl, CURLOPT_ERRORBUFFER, wp->curl_errbuf);
    curl_easy_setopt (wp->curl, CURLOPT_URL, wp->url);
    curl_easy_setopt (wp->curl, CURLOPT_FOLLOWLOCATION, 1L);
+   curl_easy_setopt (wp->curl, CURLOPT_MAXREDIRS, 50L);
  
    if (wp->user != NULL)
    {
@@@ -578,6 -579,7 +579,6 @@@ static void cc_submit (const web_page_
  
    vl.values = values;
    vl.values_len = 1;
 -  vl.time = time (NULL);
    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
    sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
    sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
@@@ -596,6 -598,7 +597,6 @@@ static void cc_submit_response_time (co
  
    vl.values = values;
    vl.values_len = 1;
 -  vl.time = time (NULL);
    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
    sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
    sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
@@@ -615,7 -618,7 +616,7 @@@ static int cc_read_page (web_page_t *wp
  
    wp->buffer_fill = 0;
    status = curl_easy_perform (wp->curl);
-   if (status != 0)
+   if (status != CURLE_OK)
    {
      ERROR ("curl plugin: curl_easy_perform failed with staus %i: %s",
          status, wp->curl_errbuf);
diff --combined src/curl_json.c
@@@ -40,7 -40,7 +40,7 @@@
  
  #define CJ_DEFAULT_HOST "localhost"
  #define CJ_KEY_MAGIC 0x43484b59UL /* CHKY */
 -#define CJ_IS_KEY(key) (key)->magic == CJ_KEY_MAGIC
 +#define CJ_IS_KEY(key) ((key)->magic == CJ_KEY_MAGIC)
  #define CJ_ANY "*"
  #define COUCH_MIN(x,y) ((x) < (y) ? (x) : (y))
  
@@@ -64,8 -64,8 +64,8 @@@ struct cj_s /* {{{ *
    char *user;
    char *pass;
    char *credentials;
 -  int   verify_peer;
 -  int   verify_host;
 +  _Bool verify_peer;
 +  _Bool verify_host;
    char *cacert;
  
    CURL *curl;
@@@ -111,16 -111,9 +111,9 @@@ static size_t cj_curl_callback (void *b
    if (db == NULL)
      return (0);
  
-   status = yajl_parse(db->yajl, (unsigned char *) buf, len);
+   status = yajl_parse(db->yajl, (unsigned char *)buf, len);
    if (status == yajl_status_ok)
-   {
- #if HAVE_YAJL_V2
-     status = yajl_complete_parse(db->yajl);
- #else
-     status = yajl_parse_complete(db->yajl);
- #endif
      return (len);
-   }
  #if !HAVE_YAJL_V2
    else if (status == yajl_status_insufficient_data)
      return (len);
    if (status != yajl_status_ok)
    {
      unsigned char *msg =
 -      yajl_get_error(db->yajl, 1, (unsigned char *)buf, len);
 +      yajl_get_error(db->yajl, /* verbose = */ 1,
 +          /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
      ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
      yajl_free_error(db->yajl, msg);
      return (0); /* abort write callback */
@@@ -185,21 -177,41 +178,21 @@@ static int cj_cb_number (void *ctx
  
    cj_t *db = (cj_t *)ctx;
    cj_key_t *key = db->state[db->depth].key;
 -  char *endptr;
    value_t vt;
    int type;
 +  int status;
  
 -  if (key == NULL)
 +  if ((key == NULL) || !CJ_IS_KEY (key))
      return (CJ_CB_CONTINUE);
  
    memcpy (buffer, number, number_len);
    buffer[sizeof (buffer) - 1] = 0;
  
    type = cj_get_type (key);
 -  if (type < 0)
 -    return (CJ_CB_CONTINUE);
 -
 -  endptr = NULL;
 -  errno = 0;
 -
 -  if (type == DS_TYPE_COUNTER)
 -    vt.counter = (counter_t) strtoull (buffer, &endptr, /* base = */ 0);
 -  else if (type == DS_TYPE_GAUGE)
 -    vt.gauge = (gauge_t) strtod (buffer, &endptr);
 -  else if (type == DS_TYPE_DERIVE)
 -    vt.derive = (derive_t) strtoll (buffer, &endptr, /* base = */ 0);
 -  else if (type == DS_TYPE_ABSOLUTE)
 -    vt.absolute = (absolute_t) strtoull (buffer, &endptr, /* base = */ 0);
 -  else
 -  {
 -    ERROR ("curl_json plugin: Unknown data source type: \"%s\"", key->type);
 -    return (CJ_CB_ABORT);
 -  }
 -
 -  if ((endptr == &buffer[0]) || (errno != 0))
 +  status = parse_value (buffer, &vt, type);
 +  if (status != 0)
    {
 -    NOTICE ("curl_json plugin: Overflow while parsing number. "
 -        "Ignoring this value.");
 +    NOTICE ("curl_json plugin: Unable to parse number: \"%s\"", buffer);
      return (CJ_CB_CONTINUE);
    }
  
@@@ -239,26 -251,34 +232,26 @@@ static int cj_cb_string (void *ctx, con
      yajl_len_t len)
  {
    cj_t *db = (cj_t *)ctx;
 -  c_avl_tree_t *tree;
 -  char *ptr;
 -
 -  if (db->depth != 1) /* e.g. _all_dbs */
 -    return (CJ_CB_CONTINUE);
 +  char str[len + 1];
  
 -  cj_cb_map_key (ctx, val, len); /* same logic */
 +  /* Create a null-terminated version of the string. */
 +  memcpy (str, val, len);
 +  str[len] = 0;
  
 -  tree = db->state[db->depth].tree;
 +  /* No configuration for this string -> simply return. */
 +  if (db->state[db->depth].key == NULL)
 +    return (CJ_CB_CONTINUE);
  
 -  if ((tree != NULL) && (ptr = rindex (db->url, '/')))
 +  if (!CJ_IS_KEY (db->state[db->depth].key))
    {
 -    char url[PATH_MAX];
 -    CURL *curl;
 -
 -    /* url =~ s,[^/]+$,$name, */
 -    len = (ptr - db->url) + 1;
 -    ptr = url;
 -    sstrncpy (ptr, db->url, sizeof (url));
 -    sstrncpy (ptr + len, db->state[db->depth].name, sizeof (url) - len);
 -
 -    curl = curl_easy_duphandle (db->curl);
 -    curl_easy_setopt (curl, CURLOPT_URL, url);
 -    cj_curl_perform (db, curl);
 -    curl_easy_cleanup (curl);
 +    NOTICE ("curl_json plugin: Found string \"%s\", but the configuration "
 +        "expects a map here.", str);
 +    return (CJ_CB_CONTINUE);
    }
 -  return (CJ_CB_CONTINUE);
 -}
 +
 +  /* Handle the string as if it was a number. */
 +  return (cj_cb_number (ctx, (const char *) val, len));
 +} /* int cj_cb_string */
  
  static int cj_cb_start (void *ctx)
  {
@@@ -380,6 -400,37 +373,6 @@@ static void cj_free (void *arg) /* {{{ 
  
  /* Configuration handling functions {{{ */
  
 -static int cj_config_add_string (const char *name, char **dest, /* {{{ */
 -                                      oconfig_item_t *ci)
 -{
 -  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
 -  {
 -    WARNING ("curl_json plugin: `%s' needs exactly one string argument.", name);
 -    return (-1);
 -  }
 -
 -  sfree (*dest);
 -  *dest = strdup (ci->values[0].value.string);
 -  if (*dest == NULL)
 -    return (-1);
 -
 -  return (0);
 -} /* }}} int cj_config_add_string */
 -
 -static int cj_config_set_boolean (const char *name, int *dest, /* {{{ */
 -                                       oconfig_item_t *ci)
 -{
 -  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
 -  {
 -    WARNING ("curl_json plugin: `%s' needs exactly one boolean argument.", name);
 -    return (-1);
 -  }
 -
 -  *dest = ci->values[0].value.boolean ? 1 : 0;
 -
 -  return (0);
 -} /* }}} int cj_config_set_boolean */
 -
  static c_avl_tree_t *cj_avl_create(void)
  {
    return c_avl_create ((int (*) (const void *, const void *)) strcmp);
@@@ -411,7 -462,7 +404,7 @@@ static int cj_config_add_key (cj_t *db
  
    if (strcasecmp ("Key", ci->key) == 0)
    {
 -    status = cj_config_add_string ("Key", &key->path, ci);
 +    status = cf_util_get_string (ci, &key->path);
      if (status != 0)
      {
        sfree (key);
      oconfig_item_t *child = ci->children + i;
  
      if (strcasecmp ("Type", child->key) == 0)
 -      status = cj_config_add_string ("Type", &key->type, child);
 +      status = cf_util_get_string (child, &key->type);
      else if (strcasecmp ("Instance", child->key) == 0)
 -      status = cj_config_add_string ("Instance", &key->instance, child);
 +      status = cf_util_get_string (child, &key->instance);
      else
      {
        WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
@@@ -582,7 -633,7 +575,7 @@@ static int cj_config_add_url (oconfig_i
  
    if (strcasecmp ("URL", ci->key) == 0)
    {
 -    status = cj_config_add_string ("URL", &db->url, ci);
 +    status = cf_util_get_string (ci, &db->url);
      if (status != 0)
      {
        sfree (db);
      oconfig_item_t *child = ci->children + i;
  
      if (strcasecmp ("Instance", child->key) == 0)
 -      status = cj_config_add_string ("Instance", &db->instance, child);
 +      status = cf_util_get_string (child, &db->instance);
      else if (strcasecmp ("Host", child->key) == 0)
 -      status = cj_config_add_string ("Host", &db->host, child);
 +      status = cf_util_get_string (child, &db->host);
      else if (strcasecmp ("User", child->key) == 0)
 -      status = cj_config_add_string ("User", &db->user, child);
 +      status = cf_util_get_string (child, &db->user);
      else if (strcasecmp ("Password", child->key) == 0)
 -      status = cj_config_add_string ("Password", &db->pass, child);
 +      status = cf_util_get_string (child, &db->pass);
      else if (strcasecmp ("VerifyPeer", child->key) == 0)
 -      status = cj_config_set_boolean ("VerifyPeer", &db->verify_peer, child);
 +      status = cf_util_get_boolean (child, &db->verify_peer);
      else if (strcasecmp ("VerifyHost", child->key) == 0)
 -      status = cj_config_set_boolean ("VerifyHost", &db->verify_host, child);
 +      status = cf_util_get_boolean (child, &db->verify_host);
      else if (strcasecmp ("CACert", child->key) == 0)
 -      status = cj_config_add_string ("CACert", &db->cacert, child);
 +      status = cf_util_get_string (child, &db->cacert);
      else if (strcasecmp ("Key", child->key) == 0)
        status = cj_config_add_key (db, child);
      else
@@@ -766,52 -817,48 +759,52 @@@ static int cj_curl_perform (cj_t *db, C
      return (-1);
    }
  
 +  url = NULL;
 +  curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
 +
    status = curl_easy_perform (curl);
-   if (status != 0)
+   if (status != CURLE_OK)
    {
      ERROR ("curl_json plugin: curl_easy_perform failed with status %i: %s (%s)",
 -           status, db->curl_errbuf, url);
 +           status, db->curl_errbuf, (url != NULL) ? url : "<null>");
      yajl_free (db->yajl);
      db->yajl = yprev;
      return (-1);
    }
  
 -  curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
  
    /* The response code is zero if a non-HTTP transport was used. */
    if ((rc != 0) && (rc != 200))
    {
 -    ERROR ("curl_json plugin: curl_easy_perform failed with response code %ld (%s)",
 -           rc, url);
 +    ERROR ("curl_json plugin: curl_easy_perform failed with "
 +        "response code %ld (%s)", rc, url);
      yajl_free (db->yajl);
      db->yajl = yprev;
      return (-1);
    }
  
  #if HAVE_YAJL_V2
 -  status = yajl_complete_parse(db->yajl);
 +    status = yajl_complete_parse(db->yajl);
  #else
 -  status = yajl_parse_complete(db->yajl);
 +    status = yajl_parse_complete(db->yajl);
  #endif
    if (status != yajl_status_ok)
    {
 -    ERROR ("curl_json plugin: %s failed with status %i.",
 -#if HAVE_YAJL_V2
 -        "yajl_complete_parse",
 -#else
 -        "yajl_parse_complete",
 -#endif
 -        status);
 +    unsigned char *errmsg;
 +
 +    errmsg = yajl_get_error (db->yajl, /* verbose = */ 0,
 +        /* jsonText = */ NULL, /* jsonTextLen = */ 0);
 +    ERROR ("curl_json plugin: yajl_parse_complete failed: %s",
 +        (char *) errmsg);
 +    yajl_free_error (db->yajl, errmsg);
 +    yajl_free (db->yajl);
 +    db->yajl = yprev;
 +    return (-1);
    }
  
    yajl_free (db->yajl);
    db->yajl = yprev;
 -
    return (0);
  } /* }}} int cj_curl_perform */
  
diff --combined src/exec.c
@@@ -270,14 -270,13 +270,14 @@@ static void set_environment (void) /* {
    char buffer[1024];
  
  #ifdef HAVE_SETENV
 -  ssnprintf (buffer, sizeof (buffer), "%i", interval_g);
 +  ssnprintf (buffer, sizeof (buffer), "%.3f", CDTIME_T_TO_DOUBLE (interval_g));
    setenv ("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1);
  
    ssnprintf (buffer, sizeof (buffer), "%s", hostname_g);
    setenv ("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1);
  #else
 -  ssnprintf (buffer, sizeof (buffer), "COLLECTD_INTERVAL=%i", interval_g);
 +  ssnprintf (buffer, sizeof (buffer), "COLLECTD_INTERVAL=%.3f",
 +      CDTIME_T_TO_DOUBLE (interval_g));
    putenv (buffer);
  
    ssnprintf (buffer, sizeof (buffer), "COLLECTD_HOSTNAME=%s", hostname_g);
@@@ -492,7 -491,7 +492,7 @@@ static int fork_child (program_list_t *
        close (fd_pipe_out[1]);
      }
  
-     /* Now connect the `out' pipe to STDOUT */
+     /* Now connect the `err' pipe to STDERR */
      if (fd_pipe_err[1] != STDERR_FILENO)
      {
        dup2 (fd_pipe_err[1], STDERR_FILENO);
@@@ -538,9 -537,12 +538,9 @@@ static int parse_line (char *buffer) /
      return (handle_putnotif (stdout, buffer));
    else
    {
 -    /* For backwards compatibility */
 -    char tmp[1220];
 -    /* Let's annoy the user a bit.. */
 -    INFO ("exec plugin: Prepending `PUTVAL' to this line: %s", buffer);
 -    ssnprintf (tmp, sizeof (tmp), "PUTVAL %s", buffer);
 -    return (handle_putval (stdout, tmp));
 +    ERROR ("exec plugin: Unable to parse command, ignoring line: \"%s\"",
 +      buffer);
 +    return (-1);
    }
  } /* int parse_line }}} */
  
@@@ -742,8 -744,8 +742,8 @@@ static void *exec_notification_one (voi
  
    fprintf (fh,
        "Severity: %s\n"
 -      "Time: %u\n",
 -      severity, (unsigned int) n->time);
 +      "Time: %.3f\n",
 +      severity, CDTIME_T_TO_DOUBLE (n->time));
  
    /* Print the optional fields */
    if (strlen (n->host) > 0)
diff --combined src/mysql.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/mysql.c
 - * Copyright (C) 2006-2009  Florian octo Forster
 + * Copyright (C) 2006-2010  Florian octo Forster
   * Copyright (C) 2008       Mirko Buffoni
   * Copyright (C) 2009       Doug MacEachern
   * Copyright (C) 2009       Sebastian tokkee Harl
@@@ -20,7 -20,7 +20,7 @@@
   * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
   *
   * Authors:
 - *   Florian octo Forster <octo at verplant.org>
 + *   Florian octo Forster <octo at collectd.org>
   *   Mirko Buffoni <briareos at eswat.org>
   *   Doug MacEachern <dougm at hyperic.com>
   *   Sebastian tokkee Harl <sh at tokkee.org>
@@@ -42,6 -42,7 +42,6 @@@
  
  struct mysql_database_s /* {{{ */
  {
 -      /* instance == NULL  =>  legacy mode */
        char *instance;
        char *host;
        char *user;
        char *socket;
        int   port;
  
 -      int   master_stats;
 -      int   slave_stats;
 +      _Bool master_stats;
 +      _Bool slave_stats;
  
 -      int   slave_notif;
 -      int   slave_io_running;
 -      int   slave_sql_running;
 +      _Bool slave_notif;
 +      _Bool slave_io_running;
 +      _Bool slave_sql_running;
  
        MYSQL *con;
        int    state;
@@@ -97,9 -98,88 +97,9 @@@ static void mysql_database_free (void *
   *   </Database>
   * </Plugin>
   */
 -
 -static int mysql_config_set_string (char **ret_string, /* {{{ */
 -                                  oconfig_item_t *ci)
 -{
 -      char *string;
 -
 -      if ((ci->values_num != 1)
 -          || (ci->values[0].type != OCONFIG_TYPE_STRING))
 -      {
 -              WARNING ("mysql plugin: The `%s' config option "
 -                       "needs exactly one string argument.", ci->key);
 -              return (-1);
 -      }
 -
 -      string = strdup (ci->values[0].value.string);
 -      if (string == NULL)
 -      {
 -              ERROR ("mysql plugin: strdup failed.");
 -              return (-1);
 -      }
 -
 -      if (*ret_string != NULL)
 -              free (*ret_string);
 -      *ret_string = string;
 -
 -      return (0);
 -} /* }}} int mysql_config_set_string */
 -
 -static int mysql_config_set_int (int *ret_int, /* {{{ */
 -                               oconfig_item_t *ci)
 -{
 -      if ((ci->values_num != 1)
 -          || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
 -      {
 -              WARNING ("mysql plugin: The `%s' config option "
 -                       "needs exactly one string argument.", ci->key);
 -              return (-1);
 -      }
 -
 -      *ret_int = ci->values[0].value.number;
 -
 -      return (0);
 -} /* }}} int mysql_config_set_int */
 -
 -static int mysql_config_set_boolean (int *ret_boolean, /* {{{ */
 -                              oconfig_item_t *ci)
 -{
 -      int status = 0;
 -
 -      if (ci->values_num != 1)
 -              status = -1;
 -
 -      if (status == 0)
 -      {
 -              if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
 -                      *ret_boolean = ci->values[0].value.boolean;
 -              else if (ci->values[0].type == OCONFIG_TYPE_STRING)
 -              {
 -                      if (IS_TRUE (ci->values[0].value.string))
 -                              *ret_boolean = 1;
 -                      else if (IS_FALSE (ci->values[0].value.string))
 -                              *ret_boolean = 0;
 -                      else
 -                              status = -1;
 -              }
 -              else
 -                      status = -1;
 -      }
 -
 -      if (status != 0)
 -      {
 -              WARNING ("mysql plugin: The `%s' config option "
 -                      "needs exactly one boolean argument.", ci->key);
 -              return (-1);
 -      }
 -      return (0);
 -} /* }}} mysql_config_set_boolean */
 -
 -static int mysql_config (oconfig_item_t *ci) /* {{{ */
 +static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
  {
        mysql_database_t *db;
 -      int plugin_block;
        int status = 0;
        int i;
  
        db->slave_io_running  = 1;
        db->slave_sql_running = 1;
  
 -      plugin_block = 1;
 -      if (strcasecmp ("Plugin", ci->key) == 0)
 -      {
 -              db->instance = NULL;
 -      }
 -      else if (strcasecmp ("Database", ci->key) == 0)
 -      {
 -              plugin_block = 0;
 -              status = mysql_config_set_string (&db->instance, ci);
 -              if (status != 0)
 -              {
 -                      sfree (db);
 -                      return (status);
 -              }
 -              assert (db->instance != NULL);
 -      }
 -      else
 +      status = cf_util_get_string (ci, &db->instance);
 +      if (status != 0)
        {
 -              ERROR ("mysql plugin: mysql_config: "
 -                              "Invalid key: %s", ci->key);
 -              return (-1);
 +              sfree (db);
 +              return (status);
        }
 +      assert (db->instance != NULL);
  
        /* Fill the `mysql_database_t' structure.. */
        for (i = 0; i < ci->children_num; i++)
                oconfig_item_t *child = ci->children + i;
  
                if (strcasecmp ("Host", child->key) == 0)
 -                      status = mysql_config_set_string (&db->host, child);
 +                      status = cf_util_get_string (child, &db->host);
                else if (strcasecmp ("User", child->key) == 0)
 -                      status = mysql_config_set_string (&db->user, child);
 +                      status = cf_util_get_string (child, &db->user);
                else if (strcasecmp ("Password", child->key) == 0)
 -                      status = mysql_config_set_string (&db->pass, child);
 +                      status = cf_util_get_string (child, &db->pass);
                else if (strcasecmp ("Port", child->key) == 0)
 -                      status = mysql_config_set_int (&db->port, child);
 -              else if (strcasecmp ("Socket", child->key) == 0)
 -                      status = mysql_config_set_string (&db->socket, child);
 -              /* Check if we're currently handling the `Plugin' block. If so,
 -               * handle `Database' _blocks_, too. */
 -              else if ((plugin_block != 0)
 -                              && (strcasecmp ("Database", child->key) == 0)
 -                              && (child->children != NULL))
                {
 -                      /* If `plugin_block > 1', there has been at least one
 -                       * `Database' block */
 -                      plugin_block++;
 -                      status = mysql_config (child);
 +                      status = cf_util_get_port_number (child);
 +                      if (status > 0)
 +                      {
 +                              db->port = status;
 +                              status = 0;
 +                      }
                }
 -              /* Now handle ordinary `Database' options (without children) */
 -              else if ((strcasecmp ("Database", child->key) == 0)
 -                              && (child->children == NULL))
 -                      status = mysql_config_set_string (&db->database, child);
 +              else if (strcasecmp ("Socket", child->key) == 0)
 +                      status = cf_util_get_string (child, &db->socket);
 +              else if (strcasecmp ("Database", child->key) == 0)
 +                      status = cf_util_get_string (child, &db->database);
                else if (strcasecmp ("MasterStats", child->key) == 0)
 -                      status = mysql_config_set_boolean (&db->master_stats, child);
 +                      status = cf_util_get_boolean (child, &db->master_stats);
                else if (strcasecmp ("SlaveStats", child->key) == 0)
 -                      status = mysql_config_set_boolean (&db->slave_stats, child);
 +                      status = cf_util_get_boolean (child, &db->slave_stats);
                else if (strcasecmp ("SlaveNotifications", child->key) == 0)
 -                      status = mysql_config_set_boolean (&db->slave_notif, child);
 +                      status = cf_util_get_boolean (child, &db->slave_notif);
                else
                {
                        WARNING ("mysql plugin: Option `%s' not allowed here.", child->key);
                        break;
        }
  
 -      /* Check if there were any `Database' blocks. */
 -      if (plugin_block > 1)
 -      {
 -              /* There were connection blocks. Don't use any legacy stuff. */
 -              if ((db->host != NULL)
 -                      || (db->user != NULL)
 -                      || (db->pass != NULL)
 -                      || (db->database != NULL)
 -                      || (db->socket != NULL)
 -                      || (db->port != 0))
 -              {
 -                      WARNING ("mysql plugin: At least one <Database> "
 -                                      "block has been found. The legacy "
 -                                      "configuration will be ignored.");
 -              }
 -              mysql_database_free (db);
 -              return (0);
 -      }
 -      else if (plugin_block != 0)
 -      {
 -              WARNING ("mysql plugin: You're using the legacy "
 -                              "configuration options. Please consider "
 -                              "updating your configuration!");
 -      }
 -
 -      /* Check that all necessary options have been given. */
 -      while (status == 0)
 -      {
 -              /* Zero is allowed and automatically handled by
 -               * `mysql_real_connect'. */
 -              if ((db->port < 0) || (db->port > 65535))
 -              {
 -                      ERROR ("mysql plugin: Database %s: Port number out "
 -                                      "of range: %i",
 -                                      (db->instance != NULL)
 -                                      ? db->instance
 -                                      : "<legacy>",
 -                                      db->port);
 -                      status = -1;
 -              }
 -              break;
 -      } /* while (status == 0) */
 -
        /* If all went well, register this database for reading */
        if (status == 0)
        {
                ud.data = (void *) db;
                ud.free_func = mysql_database_free;
  
 -              if (db->database != NULL)
 +              if (db->instance != NULL)
                        ssnprintf (cb_name, sizeof (cb_name), "mysql-%s",
 -                                      db->database);
 +                                      db->instance);
                else
                        sstrncpy (cb_name, "mysql", sizeof (cb_name));
  
        }
  
        return (0);
 +} /* }}} int mysql_config_database */
 +
 +static int mysql_config (oconfig_item_t *ci) /* {{{ */
 +{
 +      int i;
 +
 +      if (ci == NULL)
 +              return (EINVAL);
 +
 +      /* Fill the `mysql_database_t' structure.. */
 +      for (i = 0; i < ci->children_num; i++)
 +      {
 +              oconfig_item_t *child = ci->children + i;
 +
 +              if (strcasecmp ("Database", child->key) == 0)
 +                      mysql_config_database (child);
 +              else
 +                      WARNING ("mysql plugin: Option \"%s\" not allowed here.",
 +                                      child->key);
 +      }
 +
 +      return (0);
  } /* }}} int mysql_config */
  
  /* }}} End of configuration handling functions */
@@@ -242,10 -364,10 +242,10 @@@ static MYSQL *getconnection (mysql_data
                int err;
                if ((err = mysql_ping (db->con)) != 0)
                {
 -                      WARNING ("mysql_ping failed for %s: %s",
 -                                      (db->instance != NULL)
 -                                      ? db->instance
 -                                      : "<legacy>",
 +                      /* Assured by "mysql_config_database" */
 +                      assert (db->instance != NULL);
 +                      WARNING ("mysql_ping failed for instance \"%s\": %s",
 +                                      db->instance,
                                        mysql_error (db->con));
                        db->state = 0;
                }
  
  static void set_host (mysql_database_t *db, char *buf, size_t buflen)
  {
 -      /* XXX legacy mode - use hostname_g */
 -      if (db->instance == NULL)
 +      if ((db->host == NULL)
 +                      || (strcmp ("", db->host) == 0)
 +                      || (strcmp ("localhost", db->host) == 0))
                sstrncpy (buf, hostname_g, buflen);
        else
 -      {
 -              if ((db->host == NULL)
 -                              || (strcmp ("", db->host) == 0)
 -                              || (strcmp ("localhost", db->host) == 0))
 -                      sstrncpy (buf, hostname_g, buflen);
 -              else
 -                      sstrncpy (buf, db->host, buflen);
 -      }
 -}
 -
 -static void set_plugin_instance (mysql_database_t *db,
 -              char *buf, size_t buflen)
 -{
 -      /* XXX legacy mode - no plugin_instance */
 -      if (db->instance == NULL)
 -              sstrncpy (buf, "", buflen);
 -      else
 -              sstrncpy (buf, db->instance, buflen);
 -}
 +              sstrncpy (buf, db->host, buflen);
 +} /* void set_host */
  
  static void submit (const char *type, const char *type_instance,
                value_t *values, size_t values_len, mysql_database_t *db)
        set_host (db, vl.host, sizeof (vl.host));
  
        sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
 -      set_plugin_instance (db, vl.plugin_instance, sizeof (vl.plugin_instance));
 +
 +      /* Assured by "mysql_config_database" */
 +      assert (db->instance != NULL);
 +      sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
  
        sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_instance != NULL)
  } /* submit */
  
  static void counter_submit (const char *type, const char *type_instance,
 -              counter_t value, mysql_database_t *db)
 +              derive_t value, mysql_database_t *db)
  {
        value_t values[1];
  
 -      values[0].counter = value;
 +      values[0].derive = value;
        submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
  } /* void counter_submit */
  
@@@ -338,21 -473,40 +338,21 @@@ static void gauge_submit (const char *t
        submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
  } /* void gauge_submit */
  
 -static void qcache_submit (counter_t hits, counter_t inserts,
 -              counter_t not_cached, counter_t lowmem_prunes,
 -              gauge_t queries_in_cache, mysql_database_t *db)
 +static void derive_submit (const char *type, const char *type_instance,
 +              derive_t value, mysql_database_t *db)
  {
 -      value_t values[5];
 -
 -      values[0].counter = hits;
 -      values[1].counter = inserts;
 -      values[2].counter = not_cached;
 -      values[3].counter = lowmem_prunes;
 -      values[4].gauge   = queries_in_cache;
 -
 -      submit ("mysql_qcache", NULL, values, STATIC_ARRAY_SIZE (values), db);
 -} /* void qcache_submit */
 -
 -static void threads_submit (gauge_t running, gauge_t connected, gauge_t cached,
 -              counter_t created, mysql_database_t *db)
 -{
 -      value_t values[4];
 -
 -      values[0].gauge   = running;
 -      values[1].gauge   = connected;
 -      values[2].gauge   = cached;
 -      values[3].counter = created;
 +      value_t values[1];
  
 -      submit ("mysql_threads", NULL, values, STATIC_ARRAY_SIZE (values), db);
 -} /* void threads_submit */
 +      values[0].derive = value;
 +      submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
 +} /* void derive_submit */
  
 -static void traffic_submit (counter_t rx, counter_t tx, mysql_database_t *db)
 +static void traffic_submit (derive_t rx, derive_t tx, mysql_database_t *db)
  {
        value_t values[2];
  
 -      values[0].counter = rx;
 -      values[1].counter = tx;
 +      values[0].derive = rx;
 +      values[1].derive = tx;
  
        submit ("mysql_octets", NULL, values, STATIC_ARRAY_SIZE (values), db);
  } /* void traffic_submit */
@@@ -403,6 -557,7 +403,7 @@@ static int mysql_read_master_stats (mys
        {
                ERROR ("mysql plugin: Failed to get master statistics: "
                                "`%s' did not return any rows.", query);
+               mysql_free_result (res);
                return (-1);
        }
  
        {
                ERROR ("mysql plugin: Failed to get master statistics: "
                                "`%s' returned less than two columns.", query);
+               mysql_free_result (res);
                return (-1);
        }
  
@@@ -454,6 -610,7 +456,7 @@@ static int mysql_read_slave_stats (mysq
        {
                ERROR ("mysql plugin: Failed to get slave statistics: "
                                "`%s' did not return any rows.", query);
+               mysql_free_result (res);
                return (-1);
        }
  
        {
                ERROR ("mysql plugin: Failed to get slave statistics: "
                                "`%s' returned less than 33 columns.", query);
+               mysql_free_result (res);
                return (-1);
        }
  
  
        if (db->slave_notif)
        {
 -              notification_t n = { 0, time (NULL), "", "",
 +              notification_t n = { 0, cdtime (), "", "",
                        "mysql", "", "time_offset", "", NULL };
  
                char *io, *sql;
                sql = row[SLAVE_SQL_RUNNING_IDX];
  
                set_host (db, n.host, sizeof (n.host));
 -              set_plugin_instance (db,
 -                              n.plugin_instance, sizeof (n.plugin_instance));
 +
 +              /* Assured by "mysql_config_database" */
 +              assert (db->instance != NULL);
 +              sstrncpy (n.plugin_instance, db->instance, sizeof (n.plugin_instance));
  
                if (((io == NULL) || (strcasecmp (io, "yes") != 0))
                                && (db->slave_io_running))
@@@ -556,16 -712,16 +560,16 @@@ static int mysql_read (user_data_t *ud
        MYSQL_ROW  row;
        char      *query;
  
 -      unsigned long long qcache_hits          = 0ULL;
 -      unsigned long long qcache_inserts       = 0ULL;
 -      unsigned long long qcache_not_cached    = 0ULL;
 -      unsigned long long qcache_lowmem_prunes = 0ULL;
 -      int qcache_queries_in_cache = -1;
 +      derive_t qcache_hits          = 0;
 +      derive_t qcache_inserts       = 0;
 +      derive_t qcache_not_cached    = 0;
 +      derive_t qcache_lowmem_prunes = 0;
 +      gauge_t qcache_queries_in_cache = NAN;
  
 -      int threads_running   = -1;
 -      int threads_connected = -1;
 -      int threads_cached    = -1;
 -      unsigned long long threads_created = 0ULL;
 +      gauge_t threads_running   = NAN;
 +      gauge_t threads_connected = NAN;
 +      gauge_t threads_cached    = NAN;
 +      derive_t threads_created = 0;
  
        unsigned long long traffic_incoming = 0ULL;
        unsigned long long traffic_outgoing = 0ULL;
                                                strlen ("Qcache_")) == 0)
                {
                        if (strcmp (key, "Qcache_hits") == 0)
 -                              qcache_hits = val;
 +                              qcache_hits = (derive_t) val;
                        else if (strcmp (key, "Qcache_inserts") == 0)
 -                              qcache_inserts = val;
 +                              qcache_inserts = (derive_t) val;
                        else if (strcmp (key, "Qcache_not_cached") == 0)
 -                              qcache_not_cached = val;
 +                              qcache_not_cached = (derive_t) val;
                        else if (strcmp (key, "Qcache_lowmem_prunes") == 0)
 -                              qcache_lowmem_prunes = val;
 +                              qcache_lowmem_prunes = (derive_t) val;
                        else if (strcmp (key, "Qcache_queries_in_cache") == 0)
 -                              qcache_queries_in_cache = (int) val;
 +                              qcache_queries_in_cache = (gauge_t) val;
                }
                else if (strncmp (key, "Bytes_", 
                                        strlen ("Bytes_")) == 0)
                                                strlen ("Threads_")) == 0)
                {
                        if (strcmp (key, "Threads_running") == 0)
 -                              threads_running = (int) val;
 +                              threads_running = (gauge_t) val;
                        else if (strcmp (key, "Threads_connected") == 0)
 -                              threads_connected = (int) val;
 +                              threads_connected = (gauge_t) val;
                        else if (strcmp (key, "Threads_cached") == 0)
 -                              threads_cached = (int) val;
 +                              threads_cached = (gauge_t) val;
                        else if (strcmp (key, "Threads_created") == 0)
 -                              threads_created = val;
 +                              threads_created = (derive_t) val;
                }
                else if (strncmp (key, "Table_locks_",
                                        strlen ("Table_locks_")) == 0)
        }
        mysql_free_result (res); res = NULL;
  
 -      if ((qcache_hits != 0ULL)
 -                      || (qcache_inserts != 0ULL)
 -                      || (qcache_not_cached != 0ULL)
 -                      || (qcache_lowmem_prunes != 0ULL))
 -              qcache_submit (qcache_hits, qcache_inserts, qcache_not_cached,
 -                             qcache_lowmem_prunes, qcache_queries_in_cache, db);
 +      if ((qcache_hits != 0)
 +                      || (qcache_inserts != 0)
 +                      || (qcache_not_cached != 0)
 +                      || (qcache_lowmem_prunes != 0))
 +      {
 +              derive_submit ("cache_result", "qcache-hits",
 +                              qcache_hits, db);
 +              derive_submit ("cache_result", "qcache-inserts",
 +                              qcache_inserts, db);
 +              derive_submit ("cache_result", "qcache-not_cached",
 +                              qcache_not_cached, db);
 +              derive_submit ("cache_result", "qcache-prunes",
 +                              qcache_lowmem_prunes, db);
 +
 +              gauge_submit ("cache_size", "qcache",
 +                              qcache_queries_in_cache, db);
 +      }
  
 -      if (threads_created != 0ULL)
 -              threads_submit (threads_running, threads_connected,
 -                              threads_cached, threads_created, db);
 +      if (threads_created != 0)
 +      {
 +              gauge_submit ("threads", "running",
 +                              threads_running, db);
 +              gauge_submit ("threads", "connected",
 +                              threads_connected, db);
 +              gauge_submit ("threads", "cached",
 +                              threads_cached, db);
 +
 +              derive_submit ("total_threads", "created",
 +                              threads_created, db);
 +      }
  
        traffic_submit  (traffic_incoming, traffic_outgoing, db);
  
diff --combined src/nginx.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/nginx.c
 - * Copyright (C) 2006,2007  Florian octo Forster
 + * Copyright (C) 2006-2010  Florian octo Forster
   * Copyright (C) 2008       Sebastian Harl
   *
   * This program is free software; you can redistribute it and/or modify it
@@@ -18,7 -18,7 +18,7 @@@
   * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
   *
   * Authors:
 - *   Florian octo Forster <octo at verplant.org>
 + *   Florian octo Forster <octo at collectd.org>
   *   Sebastian Harl <sh at tokkee.org>
   **/
  
@@@ -38,9 -38,10 +38,9 @@@ static char *cacert      = NULL
  
  static CURL *curl = NULL;
  
 -#define ABUFFER_SIZE 16384
 -static char nginx_buffer[ABUFFER_SIZE];
 -static int  nginx_buffer_len = 0;
 -static char nginx_curl_error[CURL_ERROR_SIZE];
 +static char   nginx_buffer[16384];
 +static size_t nginx_buffer_len = 0;
 +static char   nginx_curl_error[CURL_ERROR_SIZE];
  
  static const char *config_keys[] =
  {
@@@ -58,19 -59,17 +58,19 @@@ static size_t nginx_curl_callback (voi
  {
    size_t len = size * nmemb;
  
 -  if ((nginx_buffer_len + len) >= ABUFFER_SIZE)
 +  /* Check if the data fits into the memory. If not, truncate it. */
 +  if ((nginx_buffer_len + len) >= sizeof (nginx_buffer))
    {
 -    len = (ABUFFER_SIZE - 1) - nginx_buffer_len;
 +    assert (sizeof (nginx_buffer) > nginx_buffer_len);
 +    len = (sizeof (nginx_buffer) - 1) - nginx_buffer_len;
    }
  
    if (len <= 0)
      return (len);
  
 -  memcpy (nginx_buffer + nginx_buffer_len, (char *) buf, len);
 +  memcpy (&nginx_buffer[nginx_buffer_len], buf, len);
    nginx_buffer_len += len;
 -  nginx_buffer[nginx_buffer_len] = '\0';
 +  nginx_buffer[nginx_buffer_len] = 0;
  
    return (len);
  }
@@@ -144,6 -143,7 +144,7 @@@ static int init (void
    }
  
    curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
+   curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
  
    if ((verify_peer == NULL) || IS_TRUE (verify_peer))
    {
@@@ -179,7 -179,7 +180,7 @@@ static void submit (char *type, char *i
    if (strcmp (type, "nginx_connections") == 0)
      values[0].gauge = value;
    else if (strcmp (type, "nginx_requests") == 0)
 -    values[0].counter = value;
 +    values[0].derive = value;
    else
      return;
  
@@@ -214,7 -214,7 +215,7 @@@ static int nginx_read (void
      return (-1);
  
    nginx_buffer_len = 0;
-   if (curl_easy_perform (curl) != 0)
+   if (curl_easy_perform (curl) != CURLE_OK)
    {
      WARNING ("nginx plugin: curl_easy_perform failed: %s", nginx_curl_error);
      return (-1);
diff --combined src/write_http.c
@@@ -61,7 -61,7 +61,7 @@@ struct wh_callback_
          char   send_buffer[4096];
          size_t send_buffer_free;
          size_t send_buffer_fill;
 -        time_t send_buffer_init_time;
 +        cdtime_t send_buffer_init_time;
  
          pthread_mutex_t send_lock;
  };
@@@ -72,7 -72,7 +72,7 @@@ static void wh_reset_buffer (wh_callbac
          memset (cb->send_buffer, 0, sizeof (cb->send_buffer));
          cb->send_buffer_free = sizeof (cb->send_buffer);
          cb->send_buffer_fill = 0;
 -        cb->send_buffer_init_time = time (NULL);
 +        cb->send_buffer_init_time = cdtime ();
  
          if (cb->format == WH_FORMAT_JSON)
          {
@@@ -88,7 -88,7 +88,7 @@@ static int wh_send_buffer (wh_callback_
  
          curl_easy_setopt (cb->curl, CURLOPT_POSTFIELDS, cb->send_buffer);
          status = curl_easy_perform (cb->curl);
-         if (status != 0)
+         if (status != CURLE_OK)
          {
                  ERROR ("write_http plugin: curl_easy_perform failed with "
                                  "status %i: %s",
@@@ -158,21 -158,19 +158,21 @@@ static int wh_callback_init (wh_callbac
          return (0);
  } /* }}} int wh_callback_init */
  
 -static int wh_flush_nolock (int timeout, wh_callback_t *cb) /* {{{ */
 +static int wh_flush_nolock (cdtime_t timeout, wh_callback_t *cb) /* {{{ */
  {
          int status;
  
 -        DEBUG ("write_http plugin: wh_flush_nolock: timeout = %i; "
 +        DEBUG ("write_http plugin: wh_flush_nolock: timeout = %.3f; "
                          "send_buffer_fill = %zu;",
 -                        timeout, cb->send_buffer_fill);
 +                        CDTIME_T_TO_DOUBLE (timeout),
 +                        cb->send_buffer_fill);
  
 +        /* timeout == 0  => flush unconditionally */
          if (timeout > 0)
          {
 -                time_t now;
 +                cdtime_t now;
  
 -                now = time (NULL);
 +                now = cdtime ();
                  if ((cb->send_buffer_init_time + timeout) > now)
                          return (0);
          }
          {
                  if (cb->send_buffer_fill <= 0)
                  {
 -                        cb->send_buffer_init_time = time (NULL);
 +                        cb->send_buffer_init_time = cdtime ();
                          return (0);
                  }
  
          {
                  if (cb->send_buffer_fill <= 2)
                  {
 -                        cb->send_buffer_init_time = time (NULL);
 +                        cb->send_buffer_init_time = cdtime ();
                          return (0);
                  }
  
          return (status);
  } /* }}} wh_flush_nolock */
  
 -static int wh_flush (int timeout, /* {{{ */
 +static int wh_flush (cdtime_t timeout, /* {{{ */
                  const char *identifier __attribute__((unused)),
                  user_data_t *user_data)
  {
@@@ -261,7 -259,7 +261,7 @@@ static void wh_callback_free (void *dat
  
          cb = data;
  
 -        wh_flush_nolock (/* timeout = */ -1, cb);
 +        wh_flush_nolock (/* timeout = */ 0, cb);
  
          curl_easy_cleanup (cb->curl);
          sfree (cb->location);
          sfree (cb);
  } /* }}} void wh_callback_free */
  
 -static int wh_value_list_to_string (char *buffer, /* {{{ */
 -                size_t buffer_size,
 -                const data_set_t *ds, const value_list_t *vl,
 -                wh_callback_t *cb)
 -{
 -        size_t offset = 0;
 -        int status;
 -        int i;
 -        gauge_t *rates = NULL;
 -
 -        assert (0 == strcmp (ds->type, vl->type));
 -
 -        memset (buffer, 0, buffer_size);
 -
 -#define BUFFER_ADD(...) do { \
 -        status = ssnprintf (buffer + offset, buffer_size - offset, \
 -                        __VA_ARGS__); \
 -        if (status < 1) \
 -        { \
 -                sfree (rates); \
 -                return (-1); \
 -        } \
 -        else if (((size_t) status) >= (buffer_size - offset)) \
 -        { \
 -                sfree (rates); \
 -                return (-1); \
 -        } \
 -        else \
 -                offset += ((size_t) status); \
 -} while (0)
 -
 -        BUFFER_ADD ("%lu", (unsigned long) vl->time);
 -
 -        for (i = 0; i < ds->ds_num; i++)
 -        {
 -                if (ds->ds[i].type == DS_TYPE_GAUGE)
 -                        BUFFER_ADD (":%f", vl->values[i].gauge);
 -                else if (cb->store_rates)
 -                {
 -                        if (rates == NULL)
 -                                rates = uc_get_rate (ds, vl);
 -                        if (rates == NULL)
 -                        {
 -                                WARNING ("write_http plugin: "
 -                                                "uc_get_rate failed.");
 -                                return (-1);
 -                        }
 -                        BUFFER_ADD (":%g", rates[i]);
 -                }
 -                else if (ds->ds[i].type == DS_TYPE_COUNTER)
 -                        BUFFER_ADD (":%llu", vl->values[i].counter);
 -                else if (ds->ds[i].type == DS_TYPE_DERIVE)
 -                        BUFFER_ADD (":%"PRIi64, vl->values[i].derive);
 -                else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
 -                        BUFFER_ADD (":%"PRIu64, vl->values[i].absolute);
 -                else
 -                {
 -                        ERROR ("write_http plugin: Unknown data source type: %i",
 -                                        ds->ds[i].type);
 -                        sfree (rates);
 -                        return (-1);
 -                }
 -        } /* for ds->ds_num */
 -
 -#undef BUFFER_ADD
 -
 -        sfree (rates);
 -        return (0);
 -} /* }}} int wh_value_list_to_string */
 -
  static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{{ */
                  wh_callback_t *cb)
  {
  
          /* Convert the values to an ASCII representation and put that into
           * `values'. */
 -        status = wh_value_list_to_string (values, sizeof (values), ds, vl, cb);
 +        status = format_values (values, sizeof (values), ds, vl, cb->store_rates);
          if (status != 0) {
                  ERROR ("write_http plugin: error with "
                                  "wh_value_list_to_string");
          }
  
          command_len = (size_t) ssnprintf (command, sizeof (command),
 -                        "PUTVAL %s interval=%i %s\r\n",
 -                        key, vl->interval, values);
 +                        "PUTVAL %s interval=%.3f %s\r\n",
 +                        key,
 +                        CDTIME_T_TO_DOUBLE (vl->interval),
 +                        values);
          if (command_len >= sizeof (command)) {
                  ERROR ("write_http plugin: Command buffer too small: "
                                  "Need %zu bytes.", command_len + 1);
  
          if (command_len >= cb->send_buffer_free)
          {
 -                status = wh_flush_nolock (/* timeout = */ -1, cb);
 +                status = wh_flush_nolock (/* timeout = */ 0, cb);
                  if (status != 0)
                  {
                          pthread_mutex_unlock (&cb->send_lock);
@@@ -384,7 -450,7 +384,7 @@@ static int wh_write_json (const data_se
                          ds, vl, cb->store_rates);
          if (status == (-ENOMEM))
          {
 -                status = wh_flush_nolock (/* timeout = */ -1, cb);
 +                status = wh_flush_nolock (/* timeout = */ 0, cb);
                  if (status != 0)
                  {
                          wh_reset_buffer (cb);