curl_json plugin: Add compatibility code for libyajl v2.
[collectd.git] / src / curl_json.c
index a7acc81..5552728 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * collectd - src/curl_json.c
  * Copyright (C) 2009       Doug MacEachern
- * Copyright (C) 2006-2010  Florian octo Forster
+ * Copyright (C) 2006-2011  Florian octo Forster
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -18,7 +18,7 @@
  *
  * Authors:
  *   Doug MacEachern <dougm at hyperic.com>
- *   Florian octo Forster <octo at verplant.org>
+ *   Florian octo Forster <octo at collectd.org>
  **/
 
 #include "collectd.h"
 
 #include <curl/curl.h>
 #include <yajl/yajl_parse.h>
+#if HAVE_YAJL_YAJL_VERSION_H
+# include <yajl/yajl_version.h>
+#endif
+
+#if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+# define HAVE_YAJL_V2 1
+#endif
 
 #define CJ_DEFAULT_HOST "localhost"
 #define CJ_KEY_MAGIC 0x43484b59UL /* CHKY */
@@ -77,6 +84,12 @@ struct cj_s /* {{{ */
 };
 typedef struct cj_s cj_t; /* }}} */
 
+#if HAVE_YAJL_V2
+typedef size_t yajl_len_t;
+#else
+typedef unsigned int yajl_len_t;
+#endif
+
 static int cj_read (user_data_t *ud);
 static int cj_curl_perform (cj_t *db, CURL *curl);
 static void cj_submit (cj_t *db, cj_key_t *key, value_t *value);
@@ -100,11 +113,17 @@ static size_t cj_curl_callback (void *buf, /* {{{ */
   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);
+#endif
 
   if (status != yajl_status_ok)
   {
@@ -136,7 +155,7 @@ static int cj_get_type (cj_key_t *key)
 /* "number" may not be null terminated, so copy it into a buffer before
  * parsing. */
 static int cj_cb_number (void *ctx,
-    const char *number, unsigned int number_len)
+    const char *number, yajl_len_t number_len)
 {
   char buffer[number_len + 1];
 
@@ -183,7 +202,7 @@ static int cj_cb_number (void *ctx,
 } /* int cj_cb_number */
 
 static int cj_cb_map_key (void *ctx, const unsigned char *val,
-                            unsigned int len)
+    yajl_len_t len)
 {
   cj_t *db = (cj_t *)ctx;
   c_avl_tree_t *tree;
@@ -211,7 +230,7 @@ static int cj_cb_map_key (void *ctx, const unsigned char *val,
 }
 
 static int cj_cb_string (void *ctx, const unsigned char *val,
-                           unsigned int len)
+    yajl_len_t len)
 {
   cj_t *db = (cj_t *)ctx;
   c_avl_tree_t *tree;
@@ -279,7 +298,7 @@ static int cj_cb_start_array (void * ctx)
 
 static int cj_cb_end_array (void * ctx)
 {
-  return cj_cb_start (ctx);
+  return cj_cb_end (ctx);
 }
 
 static yajl_callbacks ycallbacks = {
@@ -535,6 +554,7 @@ static int cj_init_curl (cj_t *db) /* {{{ */
     return (-1);
   }
 
+  curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1);
   curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cj_curl_callback);
   curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
   curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
@@ -671,7 +691,7 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
     ssnprintf (cb_name, sizeof (cb_name), "curl_json-%s-%s",
                db->instance, db->url);
 
-    plugin_register_complex_read (cb_name, cj_read,
+    plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
                                   /* interval = */ NULL, &ud);
   }
   else
@@ -760,10 +780,17 @@ static int cj_curl_perform (cj_t *db, CURL *curl) /* {{{ */
   char *url;
   yajl_handle yprev = db->yajl;
 
-  db->yajl = yajl_alloc (&ycallbacks, NULL, NULL, (void *)db);
+  db->yajl = yajl_alloc (&ycallbacks,
+#if HAVE_YAJL_V2
+      /* alloc funcs = */ NULL,
+#else
+      /* alloc funcs = */ NULL, NULL,
+#endif
+      /* context = */ (void *)db);
   if (db->yajl == NULL)
   {
     ERROR ("curl_json plugin: yajl_alloc failed.");
+    db->yajl = yprev;
     return (-1);
   }
 
@@ -775,7 +802,8 @@ static int cj_curl_perform (cj_t *db, CURL *curl) /* {{{ */
   curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
   curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
 
-  if (rc != 200)
+  /* 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);