memcached plugin: Pass `ai_hints' to `getaddrinfo'.
[collectd.git] / src / memcached.c
index 39c599c..2d999ce 100644 (file)
@@ -1,6 +1,8 @@
 /**
- * collectd - src/memcached.c
- * Copyright (C) 2007  Antony Dovgal, heavily based on hddtemp.c
+ * collectd - src/memcached.c, based on src/hddtemp.c
+ * Copyright (C) 2007       Antony Dovgal
+ * Copyright (C) 2007-2009  Florian Forster
+ * Copyright (C) 2009       Doug MacEachern
  *
  * 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 +20,8 @@
  *
  * Authors:
  *   Antony Dovgal <tony at daylessday dot org>
- *
+ *   Florian octo Forster <octo at verplant.org>
+ *   Doug MacEachern <dougm at hyperic.com>
  **/
 
 #include "collectd.h"
 # include <sys/socket.h>
 # include <netinet/in.h>
 # include <netinet/tcp.h>
-# include <libgen.h> /* for basename */
-
-#if HAVE_LINUX_MAJOR_H
-# include <linux/major.h>
-#endif
 
 #define MEMCACHED_DEF_HOST "127.0.0.1"
 #define MEMCACHED_DEF_PORT "11211"
 static const char *config_keys[] =
 {
        "Host",
-       "Port",
-       NULL
+       "Port"
 };
-static int config_keys_num = 2;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
 static char *memcached_host = NULL;
 static char memcached_port[16];
@@ -85,7 +82,7 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */
                port = MEMCACHED_DEF_PORT;
        }
 
-       if ((ai_return = getaddrinfo (host, port, NULL, &ai_list)) != 0) {
+       if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0) {
                char errbuf[1024];
                ERROR ("memcached: getaddrinfo (%s, %s): %s",
                                host, port,
@@ -131,17 +128,29 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */
 
        {
                struct pollfd p;
-               int n;
+               int status;
 
+               memset (&p, 0, sizeof (p));
                p.fd = fd;
-               p.events = POLLIN|POLLERR|POLLHUP;
+               p.events = POLLIN | POLLERR | POLLHUP;
                p.revents = 0;
 
-               n = poll(&p, 1, 3);
-
-               if (n <= 0) {
-                       ERROR ("memcached: poll() failed or timed out");
-                       return -1;
+               status = poll (&p, /* nfds = */ 1, /* timeout = */ 1000 * interval_g);
+               if (status <= 0)
+               {
+                       if (status == 0)
+                       {
+                               ERROR ("memcached: poll(2) timed out after %i seconds.", interval_g);
+                       }
+                       else
+                       {
+                               char errbuf[1024];
+                               ERROR ("memcached: poll(2) failed: %s",
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                       }
+                       shutdown (fd, SHUT_RDWR);
+                       close (fd);
+                       return (-1);
                }
        }
 
@@ -204,11 +213,10 @@ static int memcached_config (const char *key, const char *value) /* {{{ */
        } else if (strcasecmp (key, "Port") == 0) {
                int port = (int) (atof (value));
                if ((port > 0) && (port <= 65535)) {
-                       snprintf (memcached_port, sizeof (memcached_port), "%i", port);
+                       ssnprintf (memcached_port, sizeof (memcached_port), "%i", port);
                } else {
-                       strncpy (memcached_port, value, sizeof (memcached_port));
+                       sstrncpy (memcached_port, value, sizeof (memcached_port));
                }
-               memcached_port[sizeof (memcached_port) - 1] = '\0';
        } else {
                return -1;
        }
@@ -227,16 +235,13 @@ static void submit_counter (const char *type, const char *type_inst,
 
        vl.values = values;
        vl.values_len = 1;
-       vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memcached");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_inst != NULL)
-       {
-               strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
-               vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
-       }
+               sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 
-       plugin_dispatch_values (type, &vl);
+       plugin_dispatch_values (&vl);
 } /* void memcached_submit_cmd */
 /* }}} */
 
@@ -252,15 +257,13 @@ static void submit_counter2 (const char *type, const char *type_inst,
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memcached");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_inst != NULL)
-       {
-               strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
-               vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
-       }
+               sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 
-       plugin_dispatch_values (type, &vl);
+       plugin_dispatch_values (&vl);
 } /* void memcached_submit_cmd */
 /* }}} */
 
@@ -275,15 +278,13 @@ static void submit_gauge (const char *type, const char *type_inst,
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memcached");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_inst != NULL)
-       {
-               strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
-               vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
-       }
+               sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 
-       plugin_dispatch_values (type, &vl);
+       plugin_dispatch_values (&vl);
 }
 /* }}} */
 
@@ -299,15 +300,13 @@ static void submit_gauge2 (const char *type, const char *type_inst,
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memcached");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_inst != NULL)
-       {
-               strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
-               vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
-       }
+               sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 
-       plugin_dispatch_values (type, &vl);
+       plugin_dispatch_values (&vl);
 }
 /* }}} */
 
@@ -322,6 +321,8 @@ static int memcached_read (void) /* {{{ */
 
        gauge_t bytes_used = NAN;
        gauge_t bytes_total = NAN;
+       gauge_t hits = NAN;
+       gauge_t gets = NAN;
        counter_t rusage_user = 0;
        counter_t rusage_syst = 0;
        counter_t octets_rx = 0;
@@ -431,6 +432,8 @@ static int memcached_read (void) /* {{{ */
                {
                        const char *name = fields[1] + 4;
                        submit_counter ("memcached_command", name, atoll (fields[2]));
+                       if (strcmp (name, "get") == 0)
+                               gets = atof (fields[2]);
                }
 
                /*
@@ -439,6 +442,7 @@ static int memcached_read (void) /* {{{ */
                else if (FIELD_IS ("get_hits"))
                {
                        submit_counter ("memcached_ops", "hits", atoll (fields[2]));
+                       hits = atof (fields[2]);
                }
                else if (FIELD_IS ("get_misses"))
                {
@@ -471,6 +475,16 @@ static int memcached_read (void) /* {{{ */
        if ((octets_rx != 0) || (octets_tx != 0))
                submit_counter2 ("memcached_octets", NULL, octets_rx, octets_tx);
        
+       if (!isnan (gets) && !isnan (hits))
+       {
+               gauge_t rate = NAN;
+
+               if (gets != 0.0)
+                       rate = 100.0 * hits / gets;
+
+               submit_gauge ("percent", "hitratio", rate);
+       }
+
        return 0;
 }
 /* }}} */