/* #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;
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) /* {{{ */
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.
* 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
* 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
# 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>
#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[] =
{
* 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;
(ai_return == EAI_SYSTEM)
? sstrerror (errno, errbuf, sizeof (errbuf))
: gai_strerror (ai_return));
- return (-1);
+ return (NULL);
}
fd = -1;
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];
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)
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 */