Merge branch 'collectd-4.6' into collectd-4.7
[collectd.git] / src / memcached.c
index 2d999ce..b332157 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (C) 2007       Antony Dovgal
  * Copyright (C) 2007-2009  Florian Forster
  * Copyright (C) 2009       Doug MacEachern
+ * Copyright (C) 2009       Franck Lombardi
  *
  * 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
@@ -22,6 +23,7 @@
  *   Antony Dovgal <tony at daylessday dot org>
  *   Florian octo Forster <octo at verplant.org>
  *   Doug MacEachern <dougm at hyperic.com>
+ *   Franck Lombardi
  **/
 
 #include "collectd.h"
@@ -32,6 +34,7 @@
 # include <poll.h>
 # include <netdb.h>
 # include <sys/socket.h>
+# include <sys/un.h>
 # include <netinet/in.h>
 # include <netinet/tcp.h>
 
 
 static const char *config_keys[] =
 {
+       "Socket",
        "Host",
        "Port"
 };
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
+static char *memcached_socket = NULL;
 static char *memcached_host = NULL;
 static char memcached_port[16];
 
@@ -55,67 +60,98 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */
        int fd;
        ssize_t status;
        int buffer_fill;
+       int i = 0;
 
-       const char *host;
-       const char *port;
+       if (memcached_socket != NULL) {
+               struct sockaddr_un serv_addr;
 
-       struct addrinfo  ai_hints;
-       struct addrinfo *ai_list, *ai_ptr;
-       int              ai_return, i = 0;
+               memset (&serv_addr, 0, sizeof (serv_addr));
+               serv_addr.sun_family = AF_UNIX;
+               sstrncpy (serv_addr.sun_path, memcached_socket,
+                               sizeof (serv_addr.sun_path));
 
-       memset (&ai_hints, '\0', sizeof (ai_hints));
-       ai_hints.ai_flags    = 0;
-#ifdef AI_ADDRCONFIG
-/*     ai_hints.ai_flags   |= AI_ADDRCONFIG; */
-#endif
-       ai_hints.ai_family   = AF_INET;
-       ai_hints.ai_socktype = SOCK_STREAM;
-       ai_hints.ai_protocol = 0;
+               /* create our socket descriptor */
+               fd = socket (AF_UNIX, SOCK_STREAM, 0);
+               if (fd < 0) {
+                       char errbuf[1024];
+                       ERROR ("memcached: unix socket: %s", sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       return -1;
+               }
 
-       host = memcached_host;
-       if (host == NULL) {
-               host = MEMCACHED_DEF_HOST;
+               /* connect to the memcached daemon */
+               status = (ssize_t) connect (fd, (struct sockaddr *) &serv_addr,
+                               sizeof (serv_addr));
+               if (status != 0) {
+                       shutdown (fd, SHUT_RDWR);
+                       close (fd);
+                       fd = -1;
+               }
        }
+       else { /* if (memcached_socket == NULL) */
+               const char *host;
+               const char *port;
 
-       port = memcached_port;
-       if (strlen (port) == 0) {
-               port = MEMCACHED_DEF_PORT;
-       }
+               struct addrinfo  ai_hints;
+               struct addrinfo *ai_list, *ai_ptr;
+               int              ai_return = 0;
 
-       if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0) {
-               char errbuf[1024];
-               ERROR ("memcached: getaddrinfo (%s, %s): %s",
-                               host, port,
-                               (ai_return == EAI_SYSTEM)
-                               ? sstrerror (errno, errbuf, sizeof (errbuf))
-                               : gai_strerror (ai_return));
-               return -1;
-       }
+               memset (&ai_hints, '\0', sizeof (ai_hints));
+               ai_hints.ai_flags    = 0;
+#ifdef AI_ADDRCONFIG
+               /*      ai_hints.ai_flags   |= AI_ADDRCONFIG; */
+#endif
+               ai_hints.ai_family   = AF_INET;
+               ai_hints.ai_socktype = SOCK_STREAM;
+               ai_hints.ai_protocol = 0;
 
-       fd = -1;
-       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
-               /* create our socket descriptor */
-               if ((fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol)) < 0) {
+               host = memcached_host;
+               if (host == NULL) {
+                       host = MEMCACHED_DEF_HOST;
+               }
+
+               port = memcached_port;
+               if (strlen (port) == 0) {
+                       port = MEMCACHED_DEF_PORT;
+               }
+
+               if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0) {
                        char errbuf[1024];
-                       ERROR ("memcached: socket: %s", sstrerror (errno, errbuf, sizeof (errbuf)));
-                       continue;
+                       ERROR ("memcached: getaddrinfo (%s, %s): %s",
+                                       host, port,
+                                       (ai_return == EAI_SYSTEM)
+                                       ? sstrerror (errno, errbuf, sizeof (errbuf))
+                                       : gai_strerror (ai_return));
+                       return -1;
                }
 
-               /* connect to the memcached daemon */
-               if (connect (fd, (struct sockaddr *) ai_ptr->ai_addr, ai_ptr->ai_addrlen)) {
-                       shutdown(fd, SHUT_RDWR);
-                       close(fd);
-                       fd = -1;
-                       continue;
+               fd = -1;
+               for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
+                       /* create our socket descriptor */
+                       fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+                       if (fd < 0) {
+                               char errbuf[1024];
+                               ERROR ("memcached: socket: %s", sstrerror (errno, errbuf, sizeof (errbuf)));
+                               continue;
+                       }
+
+                       /* connect to the memcached daemon */
+                       status = (ssize_t) connect (fd, (struct sockaddr *) ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+                       if (status != 0) {
+                               shutdown (fd, SHUT_RDWR);
+                               close (fd);
+                               fd = -1;
+                               continue;
+                       }
+
+                       /* A socket could be opened and connecting succeeded. We're
+                        * done. */
+                       break;
                }
 
-               /* A socket could be opened and connecting succeeded. We're
-                * done. */
-               break;
+               freeaddrinfo (ai_list);
        }
 
-       freeaddrinfo (ai_list);
-
        if (fd < 0) {
                ERROR ("memcached: Could not connect to daemon.");
                return -1;
@@ -205,7 +241,12 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */
 
 static int memcached_config (const char *key, const char *value) /* {{{ */
 {
-       if (strcasecmp (key, "Host") == 0) {
+       if (strcasecmp (key, "Socket") == 0) {
+               if (memcached_socket != NULL) {
+                       free (memcached_socket);
+               }
+               memcached_socket = strdup (value);
+       } else if (strcasecmp (key, "Host") == 0) {
                if (memcached_host != NULL) {
                        free (memcached_host);
                }
@@ -336,13 +377,13 @@ static int memcached_read (void) /* {{{ */
 #define FIELD_IS(cnst) \
        (((sizeof(cnst) - 1) == name_len) && (strcmp (cnst, fields[1]) == 0))
 
-    ptr = buf;
-    saveptr = NULL;
-    while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
+       ptr = buf;
+       saveptr = NULL;
+       while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
        {
                int name_len;
 
-        ptr = NULL;
+               ptr = NULL;
 
                fields_num = strsplit(line, fields, 3);
                if (fields_num != 3)
@@ -368,7 +409,7 @@ static int memcached_read (void) /* {{{ */
                {
                        rusage_syst = atoll(fields[2]);
                }
-       
+
                /*
                 * Number of threads of this instance
                 */
@@ -384,12 +425,6 @@ static int memcached_read (void) /* {{{ */
                {
                        submit_gauge ("memcached_items", "current", atof (fields[2]));
                }
-/*             
-               else if (FIELD_IS ("total_items"))
-               {
-                       total_items = atoll(fields[2]);
-               }
- */
 
                /*
                 * Number of bytes used and available (total - used)
@@ -410,20 +445,6 @@ static int memcached_read (void) /* {{{ */
                {
                        submit_gauge ("memcached_connections", "current", atof (fields[2]));
                }
-/*
-               else if (FIELD_IS("total_connections"))
-               {
-                       total_connections = atoll(fields[2]);
-               }
-*/
-
-/*
- * ``Number of connection structures allocated by the server''
-               else if (FIELD_IS ("connection_structures"))
-               {
-                       connection_structures = atof(fields[2]);
-               }
- */
 
                /*
                 * Commands
@@ -468,13 +489,13 @@ static int memcached_read (void) /* {{{ */
 
        if (!isnan (bytes_used) && !isnan (bytes_total) && (bytes_used <= bytes_total))
                submit_gauge2 ("df", "cache", bytes_used, bytes_total - bytes_used);
-       
+
        if ((rusage_user != 0) || (rusage_syst != 0))
                submit_counter2 ("ps_cputime", NULL, rusage_user, rusage_syst);
 
        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;
@@ -501,7 +522,7 @@ void module_register (void) /* {{{ */
  * tab-width: 4
  * c-basic-offset: 4
  * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
+ * vim600: sw=4 ts=4 fdm=marker noexpandtab
+ * vim<600: sw=4 ts=4 noexpandtab
  */