Code

curl_json plugin: Use the "number" callback of libyajl.
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Tue, 13 Jul 2010 11:58:34 +0000 (13:58 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Tue, 13 Jul 2010 11:58:34 +0000 (13:58 +0200)
The "integer" callback only works with "long"s, which are 32bit on
x86 and other 32bit architectures. The "number" callback gets the raw
string for us to parse ourselves – honoring the data source type in the
process.

The "integer" and "double" callbacks have been removed, since they are not
used if the "number" callback is present.

src/curl_json.c

index 53e8abda1bfeeb4aafe8196c202215a6ce8fab71..e3660258e3320f6e3df3cf953f3a3a91f4e38aaa 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * collectd - src/curl_json.c
  * Copyright (C) 2009       Doug MacEachern
- * Copyright (C) 2006-2009  Florian octo Forster
+ * Copyright (C) 2006-2010  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
@@ -130,59 +130,57 @@ static int cj_get_type (cj_key_t *key)
 }
 
 /* yajl callbacks */
-static int cj_cb_integer (void *ctx, long val)
+#define CJ_CB_ABORT    0
+#define CJ_CB_CONTINUE 1
+
+/* "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)
 {
+  char buffer[number_len + 1];
+
   cj_t *db = (cj_t *)ctx;
   cj_key_t *key = db->state[db->depth].key;
+  char *endptr;
+  value_t vt;
+  int type;
 
-  if (key != NULL)
-  {
-    value_t vt;
-    int type;
+  if (key == NULL)
+    return (CJ_CB_CONTINUE);
 
-    type = cj_get_type (key);
-    if (type == DS_TYPE_COUNTER)
-      vt.counter = (counter_t) val;
-    else if (type == DS_TYPE_GAUGE)
-      vt.gauge = (gauge_t) val;
-    else if (type == DS_TYPE_DERIVE)
-      vt.derive = (derive_t) val;
-    else if (type == DS_TYPE_ABSOLUTE)
-      vt.absolute = (absolute_t) val;
-    else
-      return 0;
+  memcpy (buffer, number, number_len);
+  buffer[sizeof (buffer) - 1] = 0;
 
-    cj_submit (db, key, &vt);
-  }
-  return 1;
-}
+  type = cj_get_type (key);
 
-static int cj_cb_double (void *ctx, double val)
-{
-  cj_t *db = (cj_t *)ctx;
-  cj_key_t *key = db->state[db->depth].key;
+  endptr = NULL;
+  errno = 0;
 
-  if (key != NULL)
+  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
   {
-    value_t vt;
-    int type;
-
-    type = cj_get_type (key);
-    if (type == DS_TYPE_COUNTER)
-      vt.counter = (counter_t) val;
-    else if (type == DS_TYPE_GAUGE)
-      vt.gauge = (gauge_t) val;
-    else if (type == DS_TYPE_DERIVE)
-      vt.derive = (derive_t) val;
-    else if (type == DS_TYPE_ABSOLUTE)
-      vt.absolute = (absolute_t) val;
-    else
-      return 0;
+    ERROR ("curl_json plugin: Unknown data source type: \"%s\"", key->type);
+    return (CJ_CB_ABORT);
+  }
 
-    cj_submit (db, key, &vt);
+  if ((endptr == &buffer[0]) || (errno != 0))
+  {
+    NOTICE ("curl_json plugin: Overflow while parsing number. "
+        "Ignoring this value.");
+    return (CJ_CB_CONTINUE);
   }
-  return 1;
-}
+
+  cj_submit (db, key, &vt);
+  return (CJ_CB_CONTINUE);
+} /* int cj_cb_number */
 
 static int cj_cb_map_key (void *ctx, const unsigned char *val,
                             unsigned int len)
@@ -287,9 +285,9 @@ static int cj_cb_end_array (void * ctx)
 static yajl_callbacks ycallbacks = {
   NULL, /* null */
   NULL, /* boolean */
-  cj_cb_integer,
-  cj_cb_double,
-  NULL, /* number */
+  NULL, /* integer */
+  NULL, /* double */
+  cj_cb_number,
   cj_cb_string,
   cj_cb_start_map,
   cj_cb_map_key,