Merge branch 'collectd-4.10' into collectd-5.0
authorFlorian Forster <octo@collectd.org>
Fri, 7 Oct 2011 15:27:06 +0000 (17:27 +0200)
committerFlorian Forster <octo@collectd.org>
Fri, 7 Oct 2011 15:27:06 +0000 (17:27 +0200)
Conflicts:
ChangeLog
src/collectd.conf.in
src/curl_json.c
version-gen.sh

Change-Id: I313c0d3c73d47481baa0a3b38bcdf508f1d4f8d8

1  2 
ChangeLog
src/collectd.conf.in
src/curl_json.c

diff --combined ChangeLog
+++ b/ChangeLog
@@@ -1,73 -1,27 +1,97 @@@
 +2011-03-28, Version 5.0.0
 +      * collectd: The "FQDNLookup" option is now enabled by default.
 +      * collectd: The internal representation of time has been changed to
 +        allow a higher accuracy than one second.
 +      * collectdcmd: This new command line utility can send various commands
 +        to collectd using the UnixSock plugin. Thanks to Håkon Dugstad
 +        Johnsen and Sebastian Harl for their code.
 +      * collectd-nagios: The "-m" option has been implemented (treat NaNs as
 +        critical).
 +      * collectd-tg: Traffic generator creating bogus network traffic
 +        compatible to the Network plugin. This utility can be used to
 +        stress-test new write plugins and collectd in general.
 +      * libcollectdclient: Creating and sending network packets has been
 +        added to the collectd client library.
 +      * All data sets: The data source name of all data sets with exactly
 +        one data source has been changed to "value".
 +      * All plugins: All "counter" data sources have been converted to
 +        "derive" data sources. All plugins now use "derive" by default, but
 +        plugins such as the network plugin can still handle "counter", of
 +        course. The minimum value of all derive data sources is zero, the
 +        maximum value is unspecified.
 +      * amqp plugin: The new AMQP plugin can send data to and receive data
 +        from an AMQP broker. Thanks to Sebastien Pahl for his code.
 +      * apache plugin: Backwards compatibility code has been removed.
 +        Support for the IBM HTTP Server has been added. Thanks to Manuel
 +        Luis Sanmartín Rozada for his patch.
 +      * contextswitch plugin: Support for sysctlbyname(3) has been added.
 +        Thanks to Kimo Rosenbaum for his patch.
 +      * df plugin: The default behavior has been changed to be equivalent to
 +        the "ReportReserved" behavior of v4.
 +      * dns plugin: Improved RFC 1035 name parsing has been imported from
 +        "dnstop".
 +      * exec plugin: Backwards compatibility code has been removed.
 +      * GenericJMX plugin: The "InstancePrefix" option has been added to
 +        "Connection" blocks.
 +      * hddtemp plugin: The "TranslateDevicename" config option has been
 +        removed.
 +      * interface plugin: Use the "plugin instance" to store the interface
 +        value.
 +      * libvirt plugin: The "InterfaceFormat" option has been added. Thanks
 +        to Ruben Kerkhof for his patch.
 +      * lpar plugin: New plugins for "logical partitions", a virtualization
 +        technique of POWER CPUs. Thanks to Aurélien Reynaud for his code and
 +        patience.
 +      * modbus plugin: Support for libmodbus 2.9.2 has been added and the
 +        license has been changes to LGPLv2.1.
 +      * mysql plugin: Backwards compatibility code has been removed. The
 +        data sets used have been improved.
 +      * network plugin: The default buffer size has been increased to
 +        1452 bytes.
 +      * perl plugin: Backwards compatibility code has been removed.
 +      * postgresql plugin: Backwards compatibility code has been removed.
 +      * redis plugin: Plugin for collecting statistics from Redis, a key-
 +        value store, has been added. Thanks to Andres J. Diaz for his code.
 +      * swap plugin: Implement collection of physical and virtual memory
 +        statistics under Solaris. The new default is collecting physical
 +        memory. Thanks to Aurélien Reynaud for his patches.
 +      * threshold plugin: The threshold configuration has been moved into
 +        this separate plugin.
 +      * unixsock plugin: The "DeleteSocket" option has been added.
 +      * varnish plugin: The new Varnish plugin reads statistics from
 +        Varnish, a web accelerator. Thanks to Jérôme Renard and Marc
 +        Fournier for their contributions.
 +      * write_redis: New plugin for writing data to Redis, a key-value
 +        store.
 +      * zfs_arc plugin: The data sets have been replaced by more elegant
 +        alternatives.
 +      * v5upgrade target: Target for converting v4 data sets to the v5
 +        schema.
 +
+ 2011-10-07, Version 4.10.4
+       * collectd: A mutex leak has been fixed in the meta data code. Thanks
+         to Rafal Lesniak for his patch.
+       * collectd: Compatibility fixes for GCC 4.6 have been applied.
+       * csv plugin: The line buffer size has been increased. Thanks to Colin
+         McCabe for the patch.
+       * curl_json plugin: Don't use the "parent" node to build the type
+         instance, if it is empty. Compatibility with libyajl 2 has been
+         added. Thanks to "spupykin" of the Arch Linux project for the initial
+         code.
+       * iptables plugin: Fix linking with some versions of libiptc.
+       * irq plugin: Fix support for interrupts under Linux. The old code
+         assumed that interrupts have a numeric value -- this is no longer
+         true for Linux. Thanks to Bostjan Skufca for implementing this.
+       * notify_desktop plugin: Compatibility with libnotify 0.7 has been
+         added. Thanks to Samuli Suominen for his patch.
+       * processes plugin: Fix handling of regular expressions containing
+         spaces. Thanks for Sebastian Harl for fixing this.
+       * rrdtool, rrdcached plugins: Improve precision of the XFF parameter.
+         Previously, values like 0.999 would have been rounded to 1.0. Thanks
+         to Francois-Xavier Bourlet for fixing this.
+       * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike
+         Flisher for the fix.
  2011-03-26, Version 4.10.3
        * Documentation: Several updates and additions. Thanks to Sebastian Harl.
        * collectd: Build issues (compiler warnings) have been fixed. Thanks to
diff --combined src/collectd.conf.in
@@@ -11,7 -11,7 +11,7 @@@
  ##############################################################################
  
  #Hostname    "localhost"
 -FQDNLookup   true
 +#FQDNLookup   true
  #BaseDir     "@prefix@/var/lib/@PACKAGE_NAME@"
  #PIDFile     "@prefix@/var/run/@PACKAGE_NAME@.pid"
  #PluginDir   "@prefix@/lib/@PACKAGE_NAME@"
@@@ -52,7 -52,6 +52,7 @@@
  # to missing dependencies or because they have been deactivated explicitly.  #
  ##############################################################################
  
 +#@BUILD_PLUGIN_AMQP_TRUE@LoadPlugin amqp
  #@BUILD_PLUGIN_APACHE_TRUE@LoadPlugin apache
  #@BUILD_PLUGIN_APCUPS_TRUE@LoadPlugin apcups
  #@BUILD_PLUGIN_APPLE_SENSORS_TRUE@LoadPlugin apple_sensors
@@@ -86,7 -85,6 +86,7 @@@
  #@BUILD_PLUGIN_JAVA_TRUE@LoadPlugin java
  #@BUILD_PLUGIN_LIBVIRT_TRUE@LoadPlugin libvirt
  @BUILD_PLUGIN_LOAD_TRUE@@BUILD_PLUGIN_LOAD_TRUE@LoadPlugin load
 +#@BUILD_PLUGIN_LPAR_TRUE@LoadPlugin lpar
  #@BUILD_PLUGIN_MADWIFI_TRUE@LoadPlugin madwifi
  #@BUILD_PLUGIN_MBMON_TRUE@LoadPlugin mbmon
  #@BUILD_PLUGIN_MEMCACHEC_TRUE@LoadPlugin memcachec
  #@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
  #@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
  #@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
- #@BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl
+ #@BUILD_PLUGIN_PERL_TRUE@<LoadPlugin perl>
+ #@BUILD_PLUGIN_PERL_TRUE@  Globals true
+ #@BUILD_PLUGIN_PERL_TRUE@</LoadPlugin>
  #@BUILD_PLUGIN_PINBA_TRUE@LoadPlugin pinba
  #@BUILD_PLUGIN_PING_TRUE@LoadPlugin ping
  #@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql
  #@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
  #@BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
  #@BUILD_PLUGIN_PROTOCOLS_TRUE@LoadPlugin protocols
- #@BUILD_PLUGIN_PYTHON_TRUE@LoadPlugin python
+ #@BUILD_PLUGIN_PYTHON_TRUE@<LoadPlugin python>
+ #@BUILD_PLUGIN_PYTHON_TRUE@  Globals true
+ #@BUILD_PLUGIN_PYTHON_TRUE@</LoadPlugin>
 +#@BUILD_PLUGIN_REDIS_TRUE@LoadPlugin redis
  #@BUILD_PLUGIN_ROUTEROS_TRUE@LoadPlugin routeros
  #@BUILD_PLUGIN_RRDCACHED_TRUE@LoadPlugin rrdcached
  @LOAD_PLUGIN_RRDTOOL@LoadPlugin rrdtool
  #@BUILD_PLUGIN_UPTIME_TRUE@LoadPlugin uptime
  #@BUILD_PLUGIN_USERS_TRUE@LoadPlugin users
  #@BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid
 +#@BUILD_PLUGIN_VARNISH_TRUE@LoadPlugin varnish
  #@BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem
  #@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
  #@BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless
  #@BUILD_PLUGIN_WRITE_HTTP_TRUE@LoadPlugin write_http
 +#@BUILD_PLUGIN_WRITE_REDIS_TRUE@LoadPlugin write_redis
  #@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
  #@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
  
  # ription of those options is available in the collectd.conf(5) manual page. #
  ##############################################################################
  
 +#<Plugin "amqp">
 +#  <Publish "name">
 +#    Host "localhost"
 +#    Port "5672"
 +#    VHost "/"
 +#    User "guest"
 +#    Password "guest"
 +#    Exchange "amq.fanout"
 +#    RoutingKey "collectd"
 +#    Persistent false
 +#    StoreRates false
 +#  </Publish>
 +#</Plugin>
 +
  #<Plugin apache>
 -#     URL "http://localhost/status?auto"
 -#     User "www-user"
 -#     Password "secret"
 -#     CACert "/etc/ssl/ca.crt"
 +#  <Instance "local">
 +#    URL "http://localhost/status?auto"
 +#    User "www-user"
 +#    Password "secret"
 +#    CACert "/etc/ssl/ca.crt"
 +#  </Instance>
  #</Plugin>
  
  #<Plugin apcups>
  #<Plugin hddtemp>
  #  Host "127.0.0.1"
  #  Port "7634"
 -#
 -#  #----------------------------------------------------------------#
 -#  # `TranslateDevicename' enables backwards compatibility behavior #
 -#  # and is enabled by default. Setting this option to `false' is   #
 -#  # highly recommended.                                            #
 -#  #----------------------------------------------------------------#
 -#  TranslateDevicename false
  #</Plugin>
  
  #<Plugin interface>
  #     InterfaceDevice "name:device"
  #     IgnoreSelected false
  #     HostnameFormat name
 +#     InterfaceFormat name
 +#</Plugin>
 +
 +#<Plugin lpar>
 +#     CpuPoolStats   false
 +#     ReportBySerial false
  #</Plugin>
  
  #<Plugin madwifi>
  #     </Module>
  #</Plugin>
  
 +#<Plugin redis>
 +#   <Node example>
 +#      Host "redis.example.com"
 +#      Port "6379"
 +#      Timeout 2000
 +#   </Node>
 +#</Plugin>
 +
  #<Plugin routeros>
  #     <Router>
  #             Host "router.example.com"
  #     SocketFile "@prefix@/var/run/@PACKAGE_NAME@-unixsock"
  #     SocketGroup "collectd"
  #     SocketPerms "0660"
 +#     DeleteSocket false
  #</Plugin>
  
  #<Plugin uuid>
  #     UUIDFile "/etc/uuid"
  #</Plugin>
  
 +#<Plugin varnish>
 +#   This tag support an argument if you want to
 +#   monitor the local instance just use </Instance>
 +#   If you prefer defining another instance you can do
 +#   so by using <Instance "myinstance">
 +#   <Instance>
 +#      CollectCache true
 +#      CollectBackend true
 +#      CollectConnections true
 +#      CollectSHM true
 +#      CollectESI false
 +#      CollectFetch false
 +#      CollectHCB false
 +#      CollectSMA false
 +#      CollectSMS false
 +#      CollectSM false
 +#      CollectTotals false
 +#      CollectWorkers false
 +#   </Instance>
 +#</Plugin>
 +
  #<Plugin vmem>
  #     Verbose false
  #</Plugin>
  #     </URL>
  #</Plugin>
  
 +#<Plugin write_redis>
 +#     <Node "example">
 +#             Host "localhost"
 +#             Port "6379"
 +#             Timeout 1000
 +#     </Node>
 +#</Plugin>
 +
  ##############################################################################
  # Filter configuration                                                       #
  #----------------------------------------------------------------------------#
  #<Chain "PostCache">
  #  Target "write"
  #</Chain>
 +
 +##############################################################################
 +# Threshold configuration                                                    #
 +#----------------------------------------------------------------------------#
 +# The following outlines how to configure collectd's threshold checking      #
 +# plugin. The plugin and possible configuration options are documented in    #
 +# the collectd-threshold(5) manual page.                                     #
 +##############################################################################
 +
 +#@BUILD_PLUGIN_THRESHOLD_TRUE@LoadPlugin "threshold"
 +#<Plugin "threshold">
 +#  <Type "foo">
 +#    WarningMin    0.00
 +#    WarningMax 1000.00
 +#    FailureMin    0.00
 +#    FailureMax 1200.00
 +#    Invert false
 +#    Instance "bar"
 +#  </Type>
 +#
 +#  <Plugin "interface">
 +#    Instance "eth0"
 +#    <Type "if_octets">
 +#      FailureMax 10000000
 +#      DataSource "rx"
 +#    </Type>
 +#  </Plugin>
 +#
 +#  <Host "hostname">
 +#    <Type "cpu">
 +#      Instance "idle"
 +#      FailureMin 10
 +#    </Type>
 +#
 +#    <Plugin "memory">
 +#      <Type "memory">
 +#        Instance "cached"
 +#        WarningMin 100000000
 +#      </Type>
 +#    </Plugin>
 +#
 +#    <Type "load">
 +#     DataSource "midterm"
 +#     FailureMax 4
 +#     Hits 3
 +#     Hysteresis 3
 +#    </Type>
 +#  </Host>
 +#</Plugin>
diff --combined src/curl_json.c
@@@ -26,6 -26,7 +26,7 @@@
  #include "plugin.h"
  #include "configfile.h"
  #include "utils_avltree.h"
+ #include "utils_complain.h"
  
  #include <curl/curl.h>
  #include <yajl/yajl_parse.h>
@@@ -39,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))
  
@@@ -63,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;
@@@ -110,7 -111,7 +111,7 @@@ 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
    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 */
@@@ -144,9 -144,31 +145,31 @@@ static int cj_get_type (cj_key_t *key
  
    ds = plugin_get_ds (key->type);
    if (ds == NULL)
-     return -1; /* let plugin_write do the complaining */
-   else
-     return ds->ds[0].type; /* XXX support ds->ds_len > 1 */
+   {
+     static char type[DATA_MAX_NAME_LEN] = "!!!invalid!!!";
+     assert (key->type != NULL);
+     if (strcmp (type, key->type) != 0)
+     {
+       ERROR ("curl_json plugin: Unable to look up DS type \"%s\".",
+           key->type);
+       sstrncpy (type, key->type, sizeof (type));
+     }
+     return -1;
+   }
+   else if (ds->ds_num > 1)
+   {
+     static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
+     c_complain_once (LOG_WARNING, &complaint,
+         "curl_json plugin: The type \"%s\" has more than one data source. "
+         "This is currently not supported. I will return the type of the "
+         "first data source, but this will likely lead to problems later on.",
+         key->type);
+   }
+   return ds->ds[0].type;
  }
  
  /* yajl callbacks */
@@@ -162,21 -184,41 +185,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);
    }
  
@@@ -216,26 -258,34 +239,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)
  {
@@@ -357,6 -407,37 +380,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);
@@@ -388,7 -469,7 +411,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);
@@@ -526,9 -607,9 +549,9 @@@ static int cj_init_curl (cj_t *db) /* {
      curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials);
    }
  
 -  curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, db->verify_peer);
 +  curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, (int) db->verify_peer);
    curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYHOST,
 -                    db->verify_host ? 2 : 0);
 +                    (int) (db->verify_host ? 2 : 0));
    if (db->cacert != NULL)
      curl_easy_setopt (db->curl, CURLOPT_CAINFO, db->cacert);
  
@@@ -559,7 -640,7 +582,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
@@@ -704,8 -785,13 +727,13 @@@ static void cj_submit (cj_t *db, cj_key
      host = db->host;
  
    if (key->instance == NULL)
-     ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
-                db->state[db->depth-1].name, db->state[db->depth].name);
+   {
+     if ((db->depth == 0) || (strcmp ("", db->state[db->depth-1].name) == 0))
+       sstrncpy (vl.type_instance, db->state[db->depth].name, sizeof (vl.type_instance));
+     else
+       ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
+           db->state[db->depth-1].name, db->state[db->depth].name);
+   }
    else
      sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
  
@@@ -738,52 -824,29 +766,52 @@@ static int cj_curl_perform (cj_t *db, C
      return (-1);
    }
  
 -  status = curl_easy_perform (curl);
 +  url = NULL;
 +  curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
  
 -  yajl_free (db->yajl);
 -  db->yajl = yprev;
 +  status = curl_easy_perform (curl);
 +  if (status != 0)
 +  {
 +    ERROR ("curl_json plugin: curl_easy_perform failed with status %i: %s (%s)",
 +           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 (status != 0)
 +#if HAVE_YAJL_V2
 +    status = yajl_complete_parse(db->yajl);
 +#else
 +    status = yajl_parse_complete(db->yajl);
 +#endif
 +  if (status != yajl_status_ok)
    {
 -    ERROR ("curl_json plugin: curl_easy_perform failed with status %i: %s (%s)",
 -           status, db->curl_errbuf, url);
 +    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 */