Merge remote-tracking branch 'github/pr/1952'
authorFlorian Forster <octo@collectd.org>
Wed, 28 Sep 2016 13:21:04 +0000 (15:21 +0200)
committerFlorian Forster <octo@collectd.org>
Wed, 28 Sep 2016 13:21:04 +0000 (15:21 +0200)
AUTHORS
README
src/cpu.c
src/grpc.cc
src/hddtemp.c
src/lvm.c

diff --git a/AUTHORS b/AUTHORS
index 28220e7..8962e77 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -72,7 +72,7 @@ Aurélien Reynaud <collectd at wattapower.net>
  - LPAR plugin.
  - Various fixes for AIX, HP-UX and Solaris.
 
-Benjamin Gilbert <bgilbert at cs.cmu.edu>
+Benjamin Gilbert <bgilbert at backtick.net>
  - Improvements to the LVM plugin.
 
 Bert Vermeulen <bert at biot.com>
diff --git a/README b/README
index 9afbec6..bb72ac2 100644 (file)
--- a/README
+++ b/README
@@ -132,7 +132,7 @@ Features
       Monitor gps related data through gpsd.
 
     - grpc
-      Receive values over the network using the gRPC framework.
+      Send and receive values over the network using the gRPC framework.
 
     - hddtemp
       Hard disk temperatures using hddtempd.
index 424a5b5..36c4972 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -162,6 +162,12 @@ static int maxcpu;
 /* #endif  HAVE_LIBSTATGRAB */
 
 #elif defined(HAVE_PERFSTAT)
+#define TOTAL_IDLE 0
+#define TOTAL_USER 1
+#define TOTAL_SYS 2
+#define TOTAL_WAIT 3
+#define TOTAL_STAT_NUM 4
+static value_to_rate_state_t total_conv[TOTAL_STAT_NUM];
 static perfstat_cpu_t *perfcpu;
 static int numcpu;
 static int pnumcpu;
@@ -398,6 +404,24 @@ static cpu_state_t *get_cpu_state (size_t cpu_num, size_t state) /* {{{ */
        return (&cpu_states[index]);
 } /* }}} cpu_state_t *get_cpu_state */
 
+#if defined(HAVE_PERFSTAT) /* {{{ */
+/* populate global aggregate cpu rate */
+static int total_rate(gauge_t *sum_by_state, size_t state, derive_t d,
+                                         value_to_rate_state_t* conv, cdtime_t now)
+{
+       gauge_t rate = NAN;
+       int status = value_to_rate (&rate, (value_t) { .derive = d }, DS_TYPE_DERIVE, now, conv);
+       if (status != 0)
+               return (status);
+
+       sum_by_state[state] = rate;
+
+       if (state != COLLECTD_CPU_STATE_IDLE)
+               RATE_ADD (sum_by_state[COLLECTD_CPU_STATE_ACTIVE], sum_by_state[state]);
+       return (0);
+}
+#endif /* }}} HAVE_PERFSTAT */
+
 /* Populates the per-CPU COLLECTD_CPU_STATE_ACTIVE rate and the global rate_by_state
  * array. */
 static void aggregate (gauge_t *sum_by_state) /* {{{ */
@@ -426,6 +450,27 @@ static void aggregate (gauge_t *sum_by_state) /* {{{ */
 
                RATE_ADD (sum_by_state[COLLECTD_CPU_STATE_ACTIVE], this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate);
        }
+
+#if defined(HAVE_PERFSTAT) /* {{{ */
+       cdtime_t now = cdtime ();
+       perfstat_cpu_total_t cputotal = { 0 };
+
+       if (!perfstat_cpu_total(NULL, &cputotal, sizeof(cputotal), 1)) {
+               char errbuf[1024];
+               WARNING ("cpu plugin: perfstat_cpu_total: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return;
+       }
+
+       /* Reset COLLECTD_CPU_STATE_ACTIVE */
+       sum_by_state[COLLECTD_CPU_STATE_ACTIVE] = NAN;
+
+       /* Physical Processor Utilization */
+       total_rate(sum_by_state, COLLECTD_CPU_STATE_IDLE,   (derive_t) cputotal.pidle, &total_conv[TOTAL_IDLE], now);
+       total_rate(sum_by_state, COLLECTD_CPU_STATE_USER,   (derive_t) cputotal.puser, &total_conv[TOTAL_USER], now);
+       total_rate(sum_by_state, COLLECTD_CPU_STATE_SYSTEM, (derive_t) cputotal.psys , &total_conv[TOTAL_SYS],  now);
+       total_rate(sum_by_state, COLLECTD_CPU_STATE_WAIT,   (derive_t) cputotal.pwait, &total_conv[TOTAL_WAIT], now);
+#endif /* }}} HAVE_PERFSTAT */
 } /* }}} void aggregate */
 
 /* Commits (dispatches) the values for one CPU or the global aggregation.
index 3b1891f..15e2593 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/grpc.cc
  * Copyright (C) 2015-2016 Sebastian Harl
+ * Copyright (C) 2016      Florian octo Forster
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -22,6 +23,7 @@
  *
  * Authors:
  *   Sebastian Harl <sh at tokkee.org>
+ *   Florian octo Forster <octo at collectd.org>
  **/
 
 #include <grpc++/grpc++.h>
index 7ce1e98..cb6f6d2 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (C) 2005,2006  Vincent Stehlé
  * Copyright (C) 2006-2010  Florian octo Forster
  * Copyright (C) 2008       Sebastian Harl
+ * Copyright (C) 2014       Carnegie Mellon University
  *
  * 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 @@
  *   Vincent Stehlé <vincent.stehle at free.fr>
  *   Florian octo Forster <octo at collectd.org>
  *   Sebastian Harl <sh at tokkee.org>
+ *   Benjamin Gilbert <bgilbert at backtick.net>
  *
  * TODO:
  *   Do a pass, some day, and spare some memory. We consume too much for now
@@ -38,6 +40,7 @@
 # include <netinet/in.h>
 # include <netinet/tcp.h>
 # include <libgen.h> /* for basename */
+# include <assert.h>
 
 #if HAVE_LINUX_MAJOR_H
 # include <linux/major.h>
@@ -45,6 +48,7 @@
 
 #define HDDTEMP_DEF_HOST "127.0.0.1"
 #define HDDTEMP_DEF_PORT "7634"
+#define HDDTEMP_MAX_RECV_BUF (1 << 20)
 
 static const char *config_keys[] =
 {
@@ -79,11 +83,15 @@ static char hddtemp_port[16];
  *  we need to create a new socket each time. Is there another way?
  *  Hm, maybe we can re-use the `sockaddr' structure? -octo
  */
-static int hddtemp_query_daemon (char *buffer, int buffer_size)
+static char *hddtemp_query_daemon (void)
 {
        int fd;
        ssize_t status;
+
+       char *buffer;
+       int buffer_size;
        int buffer_fill;
+       char *new_buffer;
 
        const char *host;
        const char *port;
@@ -114,7 +122,7 @@ static int hddtemp_query_daemon (char *buffer, int buffer_size)
                                (ai_return == EAI_SYSTEM)
                                ? sstrerror (errno, errbuf, sizeof (errbuf))
                                : gai_strerror (ai_return));
-               return (-1);
+               return (NULL);
        }
 
        fd = -1;
@@ -154,16 +162,41 @@ static int hddtemp_query_daemon (char *buffer, int buffer_size)
        if (fd < 0)
        {
                ERROR ("hddtemp plugin: Could not connect to daemon.");
-               return (-1);
+               return (NULL);
        }
 
        /* receive data from the hddtemp daemon */
-       memset (buffer, '\0', buffer_size);
-
+       buffer = NULL;
+       buffer_size = 0;
        buffer_fill = 0;
-       while ((status = read (fd, buffer + buffer_fill, buffer_size - buffer_fill)) != 0)
+       while (1)
        {
-               if (status == -1)
+               if ((buffer_size == 0) || (buffer_fill >= buffer_size - 1))
+               {
+                       if (buffer_size == 0)
+                               buffer_size = 1024;
+                       else
+                               buffer_size *= 2;
+                       if (buffer_size > HDDTEMP_MAX_RECV_BUF)
+                       {
+                               WARNING ("hddtemp plugin: Message from hddtemp has been "
+                                               "truncated.");
+                               break;
+                       }
+                       new_buffer = realloc (buffer, buffer_size);
+                       if (new_buffer == NULL) {
+                               close (fd);
+                               free (buffer);
+                               ERROR ("hddtemp plugin: Allocation failed.");
+                               return (NULL);
+                       }
+                       buffer = new_buffer;
+               }
+               status = read (fd, buffer + buffer_fill, buffer_size - buffer_fill - 1);
+               if (status == 0) {
+                       break;
+               }
+               else if (status == -1)
                {
                        char errbuf[1024];
 
@@ -173,30 +206,25 @@ static int hddtemp_query_daemon (char *buffer, int buffer_size)
                        ERROR ("hddtemp plugin: Error reading from socket: %s",
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
                        close (fd);
-                       return (-1);
+                       free (buffer);
+                       return (NULL);
                }
                buffer_fill += status;
-
-               if (buffer_fill >= buffer_size)
-                       break;
        }
 
-       if (buffer_fill >= buffer_size)
-       {
-               buffer[buffer_size - 1] = '\0';
-               WARNING ("hddtemp plugin: Message from hddtemp has been "
-                               "truncated.");
-       }
-       else if (buffer_fill == 0)
+       if (buffer_fill == 0)
        {
                WARNING ("hddtemp plugin: Peer has unexpectedly shut down "
                                "the socket. Buffer: `%s'", buffer);
                close (fd);
-               return (-1);
+               free (buffer);
+               return (NULL);
        }
 
+       assert (buffer_fill < buffer_size);
+       buffer[buffer_fill] = '\0';
        close (fd);
-       return (0);
+       return (buffer);
 }
 
 static int hddtemp_config (const char *key, const char *value)
@@ -239,54 +267,46 @@ static void hddtemp_submit (char *type_instance, double value)
 
 static int hddtemp_read (void)
 {
-       char buf[1024];
-       char *fields[128];
+       char *buf;
        char *ptr;
        char *saveptr;
-       int num_fields;
-       int num_disks;
+       char *name;
+       char *model;
+       char *temperature;
+       char *mode;
 
        /* get data from daemon */
-       if (hddtemp_query_daemon (buf, sizeof (buf)) < 0)
+       buf = hddtemp_query_daemon ();
+       if (buf == NULL)
                return (-1);
 
        /* NB: strtok_r will eat up "||" and leading "|"'s */
-       num_fields = 0;
        ptr = buf;
        saveptr = NULL;
-       while ((fields[num_fields] = strtok_r (ptr, "|", &saveptr)) != NULL)
+       while ((name = strtok_r (ptr, "|", &saveptr)) != NULL &&
+              (model = strtok_r (NULL, "|", &saveptr)) != NULL &&
+              (temperature = strtok_r (NULL, "|", &saveptr)) != NULL &&
+              (mode = strtok_r (NULL, "|", &saveptr)) != NULL)
        {
-               ptr = NULL;
-               num_fields++;
+               double temperature_value;
 
-               if (num_fields >= 128)
-                       break;
-       }
-
-       num_disks = num_fields / 4;
-
-       for (int i = 0; i < num_disks; i++)
-       {
-               char *name;
-               double temperature;
-               char *mode;
-
-               mode = fields[4*i + 3];
-               name = basename (fields[4*i + 0]);
+               ptr = NULL;
 
                /* Skip non-temperature information */
                if (mode[0] != 'C' && mode[0] != 'F')
                        continue;
 
-               temperature = atof (fields[4*i + 2]);
+               name = basename (name);
+               temperature_value = atof (temperature);
 
                /* Convert farenheit to celsius */
                if (mode[0] == 'F')
-                       temperature = (temperature - 32.0) * 5.0 / 9.0;
+                       temperature_value = (temperature_value - 32.0) * 5.0 / 9.0;
 
-               hddtemp_submit (name, temperature);
+               hddtemp_submit (name, temperature_value);
        }
        
+       free (buf);
        return (0);
 } /* int hddtemp_read */
 
index 0d0f524..5e130d8 100644 (file)
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -18,7 +18,7 @@
  *
  * Authors:
  *   Chad Malfait <malfaitc at yahoo.com>
- *   Benjamin Gilbert <bgilbert at cs.cmu.edu>
+ *   Benjamin Gilbert <bgilbert at backtick.net>
  **/
 
 #include <lvm2app.h>