perl/Makefile: .perl-directory-stamp perl/Makefile.PL \
$(top_builddir)/config.status
- cd perl && @PERL@ Makefile.PL PREFIX=$(prefix) @PERL_BINDINGS_OPTIONS@
+ cd perl && @PERL@ Makefile.PL INSTALL_BASE=$(prefix) @PERL_BINDINGS_OPTIONS@
.perl-directory-stamp:
if test ! -d perl; then \
have_struct_kinfo_proc_freebsd="no"
],
[
+AC_INCLUDES_DEFAULT
#include <kvm.h>
#include <sys/param.h>
#include <sys/sysctl.h>
have_struct_kinfo_proc_openbsd="no"
],
[
+AC_INCLUDES_DEFAULT
#include <sys/param.h>
#include <sys/sysctl.h>
#include <kvm.h>
# This could be in iptc or ip4tc
if test "x$with_libiptc" = "xpkgconfig"
then
+ SAVE_LIBS="$LIBS"
AC_SEARCH_LIBS(iptc_init, [iptc ip4tc],
[with_libiptc="pkgconfig"],
[with_libiptc="no"],
[$with_libiptc_libs])
+ LIBS="$SAVE_LIBS"
fi
if test "x$with_libiptc" = "xpkgconfig"
then
fi
if test "x$with_libnetlink" = "xyes"
then
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $with_libnetlink_cflags"
+
+ AC_CACHE_CHECK(
+ [if function 'rtnl_dump_filter' expects five arguments],
+ [c_cv_rtnl_dump_filter_five_args],
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+ [
+AC_INCLUDES_DEFAULT
+#include <asm/types.h>
+#include <sys/socket.h>
+#if HAVE_LIBNETLINK_H
+# include <libnetlink.h>
+#elif HAVE_IPROUTE_LIBNETLINK_H
+# include <iproute/libnetlink.h>
+#elif HAVE_LINUX_LIBNETLINK_H
+# include <linux/libnetlink.h>
+#endif
+ ],
+ [
+if (rtnl_dump_filter(NULL, NULL, NULL, NULL, NULL))
+ return 1;
+return 0;
+ ]
+ )],
+ [c_cv_rtnl_dump_filter_five_args="yes"],
+ [c_cv_rtnl_dump_filter_five_args="no"]
+ )
+ )
+
+ AC_CACHE_CHECK(
+ [if function 'rtnl_dump_filter' expects three arguments],
+ [c_cv_rtnl_dump_filter_three_args],
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+ [
+AC_INCLUDES_DEFAULT
+#include <asm/types.h>
+#include <sys/socket.h>
+#if HAVE_LIBNETLINK_H
+# include <libnetlink.h>
+#elif HAVE_IPROUTE_LIBNETLINK_H
+# include <iproute/libnetlink.h>
+#elif HAVE_LINUX_LIBNETLINK_H
+# include <linux/libnetlink.h>
+#endif
+ ],
+ [
+if (rtnl_dump_filter(NULL, NULL, NULL))
+ return 1;
+return 0;
+ ]
+ )],
+ [c_cv_rtnl_dump_filter_three_args="yes"],
+ [c_cv_rtnl_dump_filter_three_args="no"]
+ )
+ )
+
+ CFLAGS="$SAVE_CFLAGS"
+
+ if test "x$c_cv_rtnl_dump_filter_five_args" = "xyes"
+ then
+ AC_DEFINE(RTNL_DUMP_FILTER_FIVE_ARGS, 1,
+ [Define to 1 if function 'rtnl_dump_filter' expects five arguments.])
+ fi
+ if test "x$c_cv_rtnl_dump_filter_three_args" = "xyes"
+ then
+ AC_DEFINE(RTNL_DUMP_FILTER_THREE_ARGS, 1,
+ [Define to 1 if function 'rtnl_dump_filter' expects three arguments.])
+ fi
+
BUILD_WITH_LIBNETLINK_CFLAGS="$with_libnetlink_cflags"
BUILD_WITH_LIBNETLINK_LIBS="$with_libnetlink_libs"
AC_SUBST(BUILD_WITH_LIBNETLINK_CFLAGS)
then
AC_MSG_NOTICE([Not checking for libvarnish: Manually configured])
with_libvarnish_cflags="-I$withval/include"
- with_libvarnish_libs="-L$withval/lib -lvarnish -lvarnishcompat -lvarnishapi"
+ with_libvarnish_libs="-L$withval/lib -lvarnishapi"
with_libvarnish="yes"
fi; fi; fi
],
if test "x$with_perfstat" = "xyes"
then
plugin_cpu="yes"
+ plugin_contextswitch="yes"
plugin_disk="yes"
plugin_memory="yes"
plugin_swap="yes"
plugin_interface="yes"
plugin_load="yes"
+ plugin_uptime="yes"
fi
if test "x$with_procinfo" = "xyes"
#
# Copyright © 2009 Adrian Perez <aperez@igalia.com>
#
-# Distributed under terms of the GPLv2 license.
+# Distributed under terms of the GPLv2 license or newer.
#
# Frank Marien (frank@apsu.be) 6 Sep 2012
# - quick fixes for 5.1 binary protocol
pkglib_LTLIBRARIES += contextswitch.la
contextswitch_la_SOURCES = contextswitch.c
contextswitch_la_LDFLAGS = -module -avoid-version
+contextswitch_la_LIBADD =
+if BUILD_WITH_PERFSTAT
+contextswitch_la_LIBADD += -lperfstat
+endif
collectd_LDADD += "-dlopen" contextswitch.la
collectd_DEPENDENCIES += contextswitch.la
endif
if BUILD_WITH_LIBKSTAT
uptime_la_LIBADD += -lkstat
endif
+if BUILD_WITH_PERFSTAT
+uptime_la_LIBADD += -lperfstat
+endif
collectd_LDADD += "-dlopen" uptime.la
collectd_DEPENDENCIES += uptime.la
endif
/*
* collectd - src/apcups.c
- * Copyright (C) 2006-2007 Florian octo Forster
+ * Copyright (C) 2006-2012 Florian octo Forster
* Copyright (C) 2006 Anthony Gialluca <tonyabg at charter.net>
* Copyright (C) 2000-2004 Kern Sibbald
* Copyright (C) 1996-1999 Andre M. Hedrick <andre at suse.com>
static int global_sockfd = -1;
+static int count_retries = 0;
+static int count_iterations = 0;
+static _Bool close_socket = 0;
+
static const char *config_keys[] =
{
"Host",
};
static int config_keys_num = 2;
-/* Close the network connection */
-static int apcups_shutdown (void)
+static int net_shutdown (int *fd)
{
uint16_t packet_size = 0;
- if (global_sockfd < 0)
- return (0);
+ if ((fd == NULL) || (*fd < 0))
+ return (EINVAL);
- DEBUG ("Gracefully shutting down socket %i.", global_sockfd);
+ swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+ close (*fd);
+ *fd = -1;
- /* send EOF sentinel */
- swrite (global_sockfd, (void *) &packet_size, sizeof (packet_size));
+ return (0);
+} /* int net_shutdown */
- close (global_sockfd);
- global_sockfd = -1;
+/* Close the network connection */
+static int apcups_shutdown (void)
+{
+ if (global_sockfd < 0)
+ return (0);
+ net_shutdown (&global_sockfd);
return (0);
} /* int apcups_shutdown */
-/*
+/*
* Open a TCP connection to the UPS network server
* Returns -1 on error
* Returns socket file descriptor otherwise
return (sd);
} /* int net_open (char *host, char *service, int port) */
-/*
+/*
* Receive a message from the other end. Each message consists of
* two packets. The first is a header that contains the size
* of the data that follows in the second packet.
/* get data size -- in short */
if (sread (*sockfd, (void *) &packet_size, sizeof (packet_size)) != 0)
{
+ close (*sockfd);
*sockfd = -1;
return (-1);
}
packet_size = ntohs (packet_size);
if (packet_size > buflen)
{
- DEBUG ("record length too large");
+ ERROR ("apcups plugin: Received %"PRIu16" bytes of payload "
+ "but have only %i bytes of buffer available.",
+ packet_size, buflen);
+ close (*sockfd);
+ *sockfd = -1;
return (-2);
}
/* now read the actual data */
if (sread (*sockfd, (void *) buf, packet_size) != 0)
{
+ close (*sockfd);
*sockfd = -1;
return (-1);
}
if (swrite (*sockfd, (void *) &packet_size, sizeof (packet_size)) != 0)
{
+ close (*sockfd);
*sockfd = -1;
return (-1);
}
/* send data packet */
if (swrite (*sockfd, (void *) buff, len) != 0)
{
+ close (*sockfd);
*sockfd = -1;
return (-2);
}
char *toksaveptr;
char *key;
double value;
+ _Bool retry = 1;
+ int status;
#if APCMAIN
# define PRINT_VALUE(name, val) printf(" Found property: name = %s; value = %f;\n", name, val)
# define PRINT_VALUE(name, val) /**/
#endif
- if (global_sockfd < 0)
+ while (retry)
{
- global_sockfd = net_open (host, port);
if (global_sockfd < 0)
{
- ERROR ("apcups plugin: Connecting to the "
- "apcupsd failed.");
+ global_sockfd = net_open (host, port);
+ if (global_sockfd < 0)
+ {
+ ERROR ("apcups plugin: Connecting to the "
+ "apcupsd failed.");
+ return (-1);
+ }
+ }
+
+
+ status = net_send (&global_sockfd, "status", strlen ("status"));
+ if (status != 0)
+ {
+ /* net_send is closing the socket on error. */
+ assert (global_sockfd < 0);
+ if (retry)
+ {
+ retry = 0;
+ count_retries++;
+ continue;
+ }
+
+ ERROR ("apcups plugin: Writing to the socket failed.");
return (-1);
}
- }
- if (net_send (&global_sockfd, "status", 6) < 0)
+ break;
+ } /* while (retry) */
+
+ /* When collectd's collection interval is larger than apcupsd's
+ * timeout, we would have to retry / re-connect each iteration. Try to
+ * detect this situation and shut down the socket gracefully in that
+ * case. Otherwise, keep the socket open to avoid overhead. */
+ count_iterations++;
+ if ((count_iterations == 10) && (count_retries > 2))
{
- ERROR ("apcups plugin: Writing to the socket failed.");
- return (-1);
+ NOTICE ("apcups plugin: There have been %i retries in the "
+ "first %i iterations. Will close the socket "
+ "in future iterations.",
+ count_retries, count_iterations);
+ close_socket = 1;
}
while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
if (strcmp ("LINEV", key) == 0)
apcups_detail->linev = value;
- else if (strcmp ("BATTV", key) == 0)
+ else if (strcmp ("BATTV", key) == 0)
apcups_detail->battv = value;
else if (strcmp ("ITEMP", key) == 0)
apcups_detail->itemp = value;
tokptr = strtok_r (NULL, ":", &toksaveptr);
} /* while (tokptr != NULL) */
}
-
+ status = errno; /* save errno, net_shutdown() may re-set it. */
+
+ if (close_socket)
+ net_shutdown (&global_sockfd);
+
if (n < 0)
{
- WARNING ("apcups plugin: Error reading from socket");
+ char errbuf[1024];
+ ERROR ("apcups plugin: Reading from socket failed: %s",
+ sstrerror (status, errbuf, sizeof (errbuf)));
return (-1);
}
apcups_detail.timeleft = -1.0;
apcups_detail.itemp = -300.0;
apcups_detail.linefreq = -1.0;
-
+
status = apc_query_server (conf_host == NULL
? APCUPS_DEFAULT_HOST
: conf_host,
conf_port, &apcups_detail);
-
+
/*
* if we did not connect then do not bother submitting
* zeros. We want rrd files to have NAN.
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread, &attr, do_flush, NULL);
+ pthread_attr_destroy (&attr);
}
static int init_hostname (void)
kstat_named_t *kn;
long long retval = -1LL;
-#ifdef assert
- assert (ksp != NULL);
- assert (ksp->ks_type == KSTAT_TYPE_NAMED);
-#else
if (ksp == NULL)
{
- ERROR ("ERROR: %s:%i: ksp == NULL\n", __FILE__, __LINE__);
+ ERROR ("get_kstat_value (\"%s\"): ksp is NULL.", name);
return (-1LL);
}
else if (ksp->ks_type != KSTAT_TYPE_NAMED)
{
- ERROR ("ERROR: %s:%i: ksp->ks_type != KSTAT_TYPE_NAMED\n", __FILE__, __LINE__);
+ ERROR ("get_kstat_value (\"%s\"): ksp->ks_type (%#x) "
+ "is not KSTAT_TYPE_NAMED (%#x).",
+ name,
+ (unsigned int) ksp->ks_type,
+ (unsigned int) KSTAT_TYPE_NAMED);
return (-1LL);
}
-#endif
if ((kn = (kstat_named_t *) kstat_data_lookup (ksp, name)) == NULL)
- return (retval);
+ return (-1LL);
if (kn->data_type == KSTAT_DATA_INT32)
retval = (long long) kn->value.i32;
/* no global variables */
/* #endif KERNEL_LINUX */
+#elif HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+/* #endif HAVE_PERFSTAT */
+
#else
# error "No applicable input method."
#endif
if (status == -2)
ERROR ("contextswitch plugin: Unable to find context switch value.");
-#endif /* KERNEL_LINUX */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_PERFSTAT
+ int status = 0;
+ perfstat_cpu_total_t perfcputotal;
+
+ status = perfstat_cpu_total(NULL, &perfcputotal, sizeof(perfstat_cpu_total_t), 1);
+ if (status < 0)
+ {
+ char errbuf[1024];
+ ERROR ("contextswitch plugin: perfstat_cpu_total: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ cs_submit(perfcputotal.pswitch);
+ status = 0;
+#endif /* defined(HAVE_PERFSTAT) */
return status;
}
return (0);
} /* }}} int cx_handle_instance_xpath */
-static int cx_handle_base_xpath (char *plugin_instance, /* {{{ */
+static int cx_handle_base_xpath (char const *plugin_instance, /* {{{ */
+ char const *host,
xmlXPathContextPtr xpath_ctx, const data_set_t *ds,
char *base_xpath, cx_xpath_t *xpath)
{
vl.values_len = ds->ds_num;
sstrncpy (vl.type, xpath->type, sizeof (vl.type));
sstrncpy (vl.plugin, "curl_xml", sizeof (vl.plugin));
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.host, (host != NULL) ? host : hostname_g, sizeof (vl.host));
if (plugin_instance != NULL)
sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
ds = plugin_get_ds (xpath->type);
if ( (cx_check_type(ds, xpath) == 0) &&
- (cx_handle_base_xpath(db->instance, xpath_ctx, ds, le->key, xpath) == 0) )
+ (cx_handle_base_xpath(db->instance, db->host,
+ xpath_ctx, ds, le->key, xpath) == 0) )
status = 0; /* we got atleast one success */
le = le->next;
if (tmp == NULL)
return (-1);
interfaces = tmp;
+ interfaces[interfaces_num] = NULL;
status = cf_util_get_string (ci, interfaces + interfaces_num);
if (status != 0)
memset (map, 0, sizeof (*map));
sstrncpy (map->type, ci->values[1].value.string, sizeof (map->type));
- if (ci->values_num == 2)
+ if (ci->values_num == 3)
sstrncpy (map->type_instance, ci->values[2].value.string,
sizeof (map->type_instance));
if (len < 0)
{
- if (errno == EAGAIN || errno == EINTR) continue;
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
break;
}
else if (len == 0)
{
/* We've reached EOF */
- NOTICE ("exec plugin: Program `%s' has closed STDERR.",
- pl->exec);
- close (fd_err);
+ NOTICE ("exec plugin: Program `%s' has closed STDERR.", pl->exec);
+
+ /* Remove file descriptor form select() set. */
FD_CLR (fd_err, &fdset);
+ copy = fdset;
highest_fd = fd;
+
+ /* Clean up file descriptor */
+ close (fd_err);
fd_err = -1;
continue;
}
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&t, &attr, exec_read_one, (void *) pl);
+ pthread_attr_destroy (&attr);
} /* for (pl) */
return (0);
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&t, &attr, exec_notification_one, (void *) pln);
+ pthread_attr_destroy (&attr);
} /* for (pl) */
return (0);
if (md == NULL)
return;
+ pthread_mutex_destroy(&md->lock);
md_entry_free (md->head);
pthread_mutex_destroy (&md->lock);
free (md);
return (-1);
}
+#ifdef RTNL_DUMP_FILTER_FIVE_ARGS
if (rtnl_dump_filter (&rth, link_filter, /* arg1 = */ NULL,
NULL, NULL) != 0)
+#elif defined(RTNL_DUMP_FILTER_THREE_ARGS)
+ if (rtnl_dump_filter (&rth, link_filter, /* arg = */ NULL) != 0)
+#else
+#error "Failed to determine the number of arguments to 'rtnl_dump_filter'!"
+#endif
{
ERROR ("netlink plugin: ir_read: rtnl_dump_filter failed.");
return (-1);
continue;
}
+#ifdef RTNL_DUMP_FILTER_FIVE_ARGS
if (rtnl_dump_filter (&rth, qos_filter, (void *) &ifindex,
NULL, NULL) != 0)
+#elif defined(RTNL_DUMP_FILTER_THREE_ARGS)
+ if (rtnl_dump_filter (&rth, qos_filter, /* arg = */ &ifindex) != 0)
+#else
+#error "Failed to determine the number of arguments to 'rtnl_dump_filter'!"
+#endif
{
ERROR ("netlink plugin: ir_read: rtnl_dump_filter failed.");
continue;
#endif
#if HAVE_LIBGCRYPT
+# include <pthread.h>
# include <gcrypt.h>
GCRY_THREAD_OPTION_PTHREAD_IMPL;
#endif
sizeof (network_config_ttl)) != 0)
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (ipv4-ttl): %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
sizeof (network_config_ttl)) != 0)
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt(ipv6-ttl): %s",
sstrerror (errno, errbuf,
sizeof (errbuf)));
return (-1);
&mreq, sizeof (mreq)) != 0)
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (ipv4-multicast-if): %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
sizeof (se->interface)) != 0)
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (ipv6-multicast-if): %s",
sstrerror (errno, errbuf,
sizeof (errbuf)));
return (-1);
sizeof(interface_name)) == -1 )
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (bind-if): %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
static int network_bind_socket (int fd, const struct addrinfo *ai, const int interface_idx)
{
+#if KERNEL_SOLARIS
+ char loop = 0;
+#else
int loop = 0;
+#endif
int yes = 1;
/* allow multiple sockets to use the same PORT number */
if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
&yes, sizeof(yes)) == -1) {
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (reuseaddr): %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
&loop, sizeof (loop)) == -1)
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (multicast-loop): %s",
sstrerror (errno, errbuf,
sizeof (errbuf)));
return (-1);
&mreq, sizeof (mreq)) == -1)
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (add-membership): %s",
sstrerror (errno, errbuf,
sizeof (errbuf)));
return (-1);
&loop, sizeof (loop)) == -1)
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (ipv6-multicast-loop): %s",
sstrerror (errno, errbuf,
sizeof (errbuf)));
return (-1);
&mreq, sizeof (mreq)) == -1)
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (ipv6-add-membership): %s",
sstrerror (errno, errbuf,
sizeof (errbuf)));
return (-1);
sizeof(interface_name)) == -1 )
{
char errbuf[1024];
- ERROR ("setsockopt: %s",
+ ERROR ("network plugin: setsockopt (bind-if): %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
* Copyright (C) 2009 Andrés J. Díaz
* Copyright (C) 2009 Manuel Sanmartin
* Copyright (C) 2010 Clément Stenac
+ * Copyright (C) 2012 Cosmin Ioiart
*
* 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
* Andrés J. Díaz <ajdiaz at connectical.com>
* Manuel Sanmartin
* Clément Stenac <clement.stenac at diwi.org>
+ * Cosmin Ioiart <cioiart at gmail.com>
**/
#include "collectd.h"
#define MAXARGLN 1024
/* #endif HAVE_PROCINFO_H */
+#elif KERNEL_SOLARIS
+# include <procfs.h>
+# include <dirent.h>
+/* #endif KERNEL_SOLARIS */
+
#else
# error "No applicable input method."
#endif
# include <regex.h>
#endif
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+
#ifndef ARG_MAX
# define ARG_MAX 4096
#endif
#endif /* HAVE_PROCINFO_H */
/* put name of process from config to list_head_g tree
- list_head_g is a list of 'procstat_t' structs with
- processes names we want to watch */
+ * list_head_g is a list of 'procstat_t' structs with
+ * processes names we want to watch */
static void ps_list_register (const char *name, const char *regexp)
{
procstat_t *new;
}
DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
- "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
+ "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
"vmem_code = %lu; "
"vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
"cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw);
} /* void ps_submit_proc_list */
+#if KERNEL_LINUX || KERNEL_SOLARIS
+static void ps_submit_fork_rate (derive_t value)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].derive = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ sstrncpy(vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy(vl.plugin, "processes", sizeof (vl.plugin));
+ sstrncpy(vl.plugin_instance, "", sizeof (vl.plugin_instance));
+ sstrncpy(vl.type, "fork_rate", sizeof (vl.type));
+ sstrncpy(vl.type_instance, "", sizeof (vl.type_instance));
+
+ plugin_dispatch_values(&vl);
+}
+#endif /* KERNEL_LINUX || KERNEL_SOLARIS*/
+
/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
#if KERNEL_LINUX
static int ps_read_tasks (int pid)
continue;
numfields = strsplit (buffer, fields,
- STATIC_ARRAY_SIZE (fields));
+ STATIC_ARRAY_SIZE (fields));
if (numfields < 2)
continue;
return buf;
} /* char *ps_get_cmdline (...) */
-static unsigned long read_fork_rate ()
+static int read_fork_rate ()
{
FILE *proc_stat;
- char buf[1024];
- unsigned long result = 0;
- int numfields;
- char *fields[3];
+ char buffer[1024];
+ value_t value;
+ _Bool value_valid = 0;
- proc_stat = fopen("/proc/stat", "r");
- if (proc_stat == NULL) {
+ proc_stat = fopen ("/proc/stat", "r");
+ if (proc_stat == NULL)
+ {
char errbuf[1024];
ERROR ("processes plugin: fopen (/proc/stat) failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
- return ULONG_MAX;
+ return (-1);
}
- while (fgets (buf, sizeof(buf), proc_stat) != NULL)
+ while (fgets (buffer, sizeof (buffer), proc_stat) != NULL)
{
- char *endptr;
+ int status;
+ char *fields[3];
+ int fields_num;
- numfields = strsplit(buf, fields, STATIC_ARRAY_SIZE (fields));
- if (numfields != 2)
+ fields_num = strsplit (buffer, fields,
+ STATIC_ARRAY_SIZE (fields));
+ if (fields_num != 2)
continue;
if (strcmp ("processes", fields[0]) != 0)
continue;
- errno = 0;
- endptr = NULL;
- result = strtoul(fields[1], &endptr, /* base = */ 10);
- if ((endptr == fields[1]) || (errno != 0)) {
- ERROR ("processes plugin: Cannot parse fork rate: %s",
- fields[1]);
- result = ULONG_MAX;
- break;
- }
+ status = parse_value (fields[1], &value, DS_TYPE_DERIVE);
+ if (status == 0)
+ value_valid = 1;
break;
}
-
fclose(proc_stat);
- return result;
+ if (!value_valid)
+ return (-1);
+
+ ps_submit_fork_rate (value.derive);
+ return (0);
}
+#endif /*KERNEL_LINUX */
-static void ps_submit_fork_rate (unsigned long value)
+#if KERNEL_SOLARIS
+static const char *ps_get_cmdline (pid_t pid, /* {{{ */
+ char *buffer, size_t buffer_size)
{
- value_t values[1];
- value_list_t vl = VALUE_LIST_INIT;
+ char path[PATH_MAX];
+ psinfo_t info;
+ int status;
- values[0].derive = (derive_t) value;
+ snprintf(path, sizeof (path), "/proc/%i/psinfo", pid);
- vl.values = values;
- vl.values_len = 1;
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
- sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
- sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
- sstrncpy (vl.type, "fork_rate", sizeof (vl.type));
- sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+ status = read_file_contents (path, (void *) &info, sizeof (info));
+ if (status != ((int) buffer_size))
+ {
+ ERROR ("processes plugin: Unexpected return value "
+ "while reading \"%s\": "
+ "Returned %i but expected %zu.",
+ path, status, buffer_size);
+ return (NULL);
+ }
- plugin_dispatch_values (&vl);
+ info.pr_psargs[sizeof (info.pr_psargs) - 1] = 0;
+ sstrncpy (buffer, info.pr_psargs, buffer_size);
+
+ return (buffer);
+} /* }}} int ps_get_cmdline */
+
+/*
+ * Reads process information on the Solaris OS. The information comes mainly from
+ * /proc/PID/status, /proc/PID/psinfo and /proc/PID/usage
+ * The values for input and ouput chars are calculated "by hand"
+ * Added a few "solaris" specific process states as well
+ */
+static int ps_read_process(int pid, procstat_t *ps, char *state)
+{
+ char filename[64];
+ char f_psinfo[64], f_usage[64];
+ char *buffer;
+
+ pstatus_t *myStatus;
+ psinfo_t *myInfo;
+ prusage_t *myUsage;
+
+ snprintf(filename, sizeof (filename), "/proc/%i/status", pid);
+ snprintf(f_psinfo, sizeof (f_psinfo), "/proc/%i/psinfo", pid);
+ snprintf(f_usage, sizeof (f_usage), "/proc/%i/usage", pid);
+
+
+ buffer = malloc(sizeof (pstatus_t));
+ memset(buffer, 0, sizeof (pstatus_t));
+ read_file_contents(filename, buffer, sizeof (pstatus_t));
+ myStatus = (pstatus_t *) buffer;
+
+ buffer = malloc(sizeof (psinfo_t));
+ memset(buffer, 0, sizeof(psinfo_t));
+ read_file_contents(f_psinfo, buffer, sizeof (psinfo_t));
+ myInfo = (psinfo_t *) buffer;
+
+ buffer = malloc(sizeof (prusage_t));
+ memset(buffer, 0, sizeof(prusage_t));
+ read_file_contents(f_usage, buffer, sizeof (prusage_t));
+ myUsage = (prusage_t *) buffer;
+
+ sstrncpy(ps->name, myInfo->pr_fname, sizeof (myInfo->pr_fname));
+ ps->num_lwp = myStatus->pr_nlwp;
+ if (myInfo->pr_wstat != 0) {
+ ps->num_proc = 0;
+ ps->num_lwp = 0;
+ *state = (char) 'Z';
+ return (0);
+ } else {
+ ps->num_proc = 1;
+ ps->num_lwp = myInfo->pr_nlwp;
+ }
+
+ /*
+ * Convert system time and user time from nanoseconds to microseconds
+ * for compatibility with the linux module
+ */
+ ps->cpu_system_counter = myStatus -> pr_stime.tv_nsec / 1000;
+ ps->cpu_user_counter = myStatus -> pr_utime.tv_nsec / 1000;
+
+ /*
+ * Convert rssize from KB to bytes to be consistent w/ the linux module
+ */
+ ps->vmem_rss = myInfo->pr_rssize * 1024;
+ ps->vmem_size = myInfo->pr_size * 1024;
+ ps->vmem_minflt_counter = myUsage->pr_minf;
+ ps->vmem_majflt_counter = myUsage->pr_majf;
+
+ /*
+ * TODO: Data and code segment calculations for Solaris
+ */
+
+ ps->vmem_data = -1;
+ ps->vmem_code = -1;
+ ps->stack_size = myStatus->pr_stksize;
+
+ /*
+ * Calculating input/ouput chars
+ * Formula used is total chars / total blocks => chars/block
+ * then convert input/output blocks to chars
+ */
+ ulong_t tot_chars = myUsage->pr_ioch;
+ ulong_t tot_blocks = myUsage->pr_inblk + myUsage->pr_oublk;
+ ulong_t chars_per_block = 1;
+ if (tot_blocks != 0)
+ chars_per_block = tot_chars / tot_blocks;
+ ps->io_rchar = myUsage->pr_inblk * chars_per_block;
+ ps->io_wchar = myUsage->pr_oublk * chars_per_block;
+ ps->io_syscr = myUsage->pr_sysc;
+ ps->io_syscw = myUsage->pr_sysc;
+
+
+ /*
+ * TODO: Find way of setting BLOCKED and PAGING status
+ */
+
+ *state = (char) 'R';
+ if (myStatus->pr_flags & PR_ASLEEP)
+ *state = (char) 'S';
+ else if (myStatus->pr_flags & PR_STOPPED)
+ *state = (char) 'T';
+ else if (myStatus->pr_flags & PR_DETACH)
+ *state = (char) 'E';
+ else if (myStatus->pr_flags & PR_DAEMON)
+ *state = (char) 'A';
+ else if (myStatus->pr_flags & PR_ISSYS)
+ *state = (char) 'Y';
+ else if (myStatus->pr_flags & PR_ORPHAN)
+ *state = (char) 'O';
+
+ sfree(myStatus);
+ sfree(myInfo);
+ sfree(myUsage);
+
+ return (0);
}
-#endif /* KERNEL_LINUX */
+/*
+ * Reads the number of threads created since the last reboot. On Solaris these
+ * are retrieved from kstat (module cpu, name sys, class misc, stat nthreads).
+ * The result is the sum for all the threads created on each cpu
+ */
+static int read_fork_rate()
+{
+ extern kstat_ctl_t *kc;
+ kstat_t *ksp_chain = NULL;
+ derive_t result = 0;
+
+ if (kc == NULL)
+ return (-1);
+
+ for (ksp_chain = kc->kc_chain;
+ ksp_chain != NULL;
+ ksp_chain = ksp_chain->ks_next)
+ {
+ if ((strcmp (ksp_chain->ks_module, "cpu") == 0)
+ && (strcmp (ksp_chain->ks_name, "sys") == 0)
+ && (strcmp (ksp_chain->ks_class, "misc") == 0))
+ {
+ long long tmp;
+
+ kstat_read (kc, ksp_chain, NULL);
+
+ tmp = get_kstat_value(ksp_chain, "nthreads");
+ if (tmp != -1LL)
+ result += tmp;
+ }
+ }
+
+ ps_submit_fork_rate (result);
+ return (0);
+}
+#endif /* KERNEL_SOLARIS */
#if HAVE_THREAD_INFO
static int mach_get_task_name (task_t t, int *pid, char *name, size_t name_max_len)
procstat_entry_t pse;
char state;
- unsigned long fork_rate;
-
procstat_t *ps_ptr;
running = sleeping = zombies = stopped = paging = blocked = 0;
for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
- fork_rate = read_fork_rate();
- if (fork_rate != ULONG_MAX)
- ps_submit_fork_rate(fork_rate);
+ read_fork_rate();
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
kvm_t *kd;
char errbuf[1024];
- struct kinfo_proc *procs; /* array of processes */
+ struct kinfo_proc *procs; /* array of processes */
struct kinfo_proc *proc_ptr = NULL;
- int count; /* returns number of processes */
+ int count; /* returns number of processes */
int i;
procstat_t *ps_ptr;
if (procentry[i].pi_pid == 0)
cmdline = "swapper";
cargs = cmdline;
- }
+ }
else
{
if (getargs(&procentry[i], sizeof(struct procentry64), arglist, MAXARGLN) >= 0)
for (ps = list_head_g; ps != NULL; ps = ps->next)
ps_submit_proc_list (ps);
-#endif /* HAVE_PROCINFO_H */
+/* #endif HAVE_PROCINFO_H */
+
+#elif KERNEL_SOLARIS
+ /*
+ * The Solaris section adds a few more process states and removes some
+ * process states compared to linux. Most notably there is no "PAGING"
+ * and "BLOCKED" state for a process. The rest is similar to the linux
+ * code.
+ */
+ int running = 0;
+ int sleeping = 0;
+ int zombies = 0;
+ int stopped = 0;
+ int detached = 0;
+ int daemon = 0;
+ int system = 0;
+ int orphan = 0;
+
+ struct dirent *ent;
+ DIR *proc;
+
+ int status;
+ procstat_t *ps_ptr;
+ char state;
+
+ char cmdline[PRARGSZ];
+
+ ps_list_reset ();
+
+ proc = opendir ("/proc");
+ if (proc == NULL)
+ return (-1);
+
+ while ((ent = readdir(proc)) != NULL)
+ {
+ int pid;
+ struct procstat ps;
+ procstat_entry_t pse;
+
+ if (!isdigit ((int) ent->d_name[0]))
+ continue;
+
+ if ((pid = atoi (ent->d_name)) < 1)
+ continue;
+
+ status = ps_read_process (pid, &ps, &state);
+ if (status != 0)
+ {
+ DEBUG("ps_read_process failed: %i", status);
+ continue;
+ }
+
+ pse.id = pid;
+ pse.age = 0;
+
+ pse.num_proc = ps.num_proc;
+ pse.num_lwp = ps.num_lwp;
+ pse.vmem_size = ps.vmem_size;
+ pse.vmem_rss = ps.vmem_rss;
+ pse.vmem_data = ps.vmem_data;
+ pse.vmem_code = ps.vmem_code;
+ pse.stack_size = ps.stack_size;
+
+ pse.vmem_minflt = 0;
+ pse.vmem_minflt_counter = ps.vmem_minflt_counter;
+ pse.vmem_majflt = 0;
+ pse.vmem_majflt_counter = ps.vmem_majflt_counter;
+
+ pse.cpu_user = 0;
+ pse.cpu_user_counter = ps.cpu_user_counter;
+ pse.cpu_system = 0;
+ pse.cpu_system_counter = ps.cpu_system_counter;
+
+ pse.io_rchar = ps.io_rchar;
+ pse.io_wchar = ps.io_wchar;
+ pse.io_syscr = ps.io_syscr;
+ pse.io_syscw = ps.io_syscw;
+
+ switch (state)
+ {
+ case 'R': running++; break;
+ case 'S': sleeping++; break;
+ case 'E': detached++; break;
+ case 'Z': zombies++; break;
+ case 'T': stopped++; break;
+ case 'A': daemon++; break;
+ case 'Y': system++; break;
+ case 'O': orphan++; break;
+ }
+
+
+ ps_list_add (ps.name,
+ ps_get_cmdline ((pid_t) pid,
+ cmdline, sizeof (cmdline)),
+ &pse);
+ } /* while(readdir) */
+ closedir (proc);
+
+ ps_submit_state ("running", running);
+ ps_submit_state ("sleeping", sleeping);
+ ps_submit_state ("zombies", zombies);
+ ps_submit_state ("stopped", stopped);
+ ps_submit_state ("detached", detached);
+ ps_submit_state ("daemon", daemon);
+ ps_submit_state ("system", system);
+ ps_submit_state ("orphan", orphan);
+
+ for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ ps_submit_proc_list (ps_ptr);
+
+ read_fork_rate();
+#endif /* KERNEL_SOLARIS */
return (0);
} /* int ps_read */
swap_submit (plugin_instance, "swap", type_instance, v);
} /* }}} void swap_submit_gauge */
-#if KERNEL_LINUX
+#if KERNEL_LINUX || HAVE_PERFSTAT
static void swap_submit_derive (const char *plugin_instance, /* {{{ */
const char *type_instance, derive_t value)
{
v.derive = value;
swap_submit (plugin_instance, "swap_io", type_instance, v);
} /* }}} void swap_submit_derive */
+#endif
+#if KERNEL_LINUX
static int swap_read_separate (void) /* {{{ */
{
FILE *fh;
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
+
swap_submit_gauge (NULL, "used", (gauge_t) (pmemory.pgsp_total - pmemory.pgsp_free) * pagesize);
swap_submit_gauge (NULL, "free", (gauge_t) pmemory.pgsp_free * pagesize );
+ swap_submit_gauge (NULL, "reserved", (gauge_t) pmemory.pgsp_rsvd * pagesize);
+ swap_submit_derive (NULL, "in", (derive_t) pmemory.pgspins * pagesize);
+ swap_submit_derive (NULL, "out", (derive_t) pmemory.pgspouts * pagesize);
return (0);
} /* }}} int swap_read */
static int port_collect_listening = 0;
static port_entry_t *port_list_head = NULL;
+#if KERNEL_LINUX
static uint32_t sequence_number = 0;
-#if KERNEL_LINUX
enum
{
SRC_DUNNO,
close (fdin);
close (fdout);
pthread_exit ((void *) 1);
+ return ((void *) 1);
}
fhout = fdopen (fdout, "w");
fclose (fhin); /* this closes fdin as well */
close (fdout);
pthread_exit ((void *) 1);
+ return ((void *) 1);
}
/* change output buffer to line buffered mode */
fclose (fhin);
fclose (fhout);
pthread_exit ((void *) 1);
+ return ((void *) 0);
}
while (42)
errno = 0;
if (fgets (buffer, sizeof (buffer), fhin) == NULL)
{
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+
if (errno != 0)
{
char errbuf[1024];
fclose (fhin);
fclose (fhout);
pthread_exit ((void *) 1);
+ return ((void *) 1);
}
if (strcasecmp (fields[0], "getval") == 0)
pthread_t th;
pthread_attr_t th_attr;
+ pthread_attr_init (&th_attr);
+ pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
+
if (us_open_socket () != 0)
pthread_exit ((void *) 1);
sstrerror (errno, errbuf, sizeof (errbuf)));
close (sock_fd);
sock_fd = -1;
+ pthread_attr_destroy (&th_attr);
pthread_exit ((void *) 1);
}
DEBUG ("Spawning child to handle connection on fd #%i", *remote_fd);
- pthread_attr_init (&th_attr);
- pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
-
status = pthread_create (&th, &th_attr, us_handle_client, (void *) remote_fd);
if (status != 0)
{
close (sock_fd);
sock_fd = -1;
+ pthread_attr_destroy (&th_attr);
status = unlink ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH);
if (status != 0)
/* Using sysctl interface to retrieve the boot time on *BSD / Darwin / OS X systems */
/* #endif HAVE_SYS_SYSCTL_H */
+#elif HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+/* Using perfstat_cpu_total to retrive the boot time in AIX */
+/* #endif HAVE_PERFSTAT */
+
#else
# error "No applicable input method."
#endif
"but `boottime' is zero!");
return (-1);
}
-#endif /* HAVE_SYS_SYSCTL_H */
+/* #endif HAVE_SYS_SYSCTL_H */
+
+#elif HAVE_PERFSTAT
+ int status;
+ perfstat_cpu_total_t cputotal;
+ int hertz;
+
+ status = perfstat_cpu_total(NULL, &cputotal,
+ sizeof(perfstat_cpu_total_t), 1);
+ if (status < 0)
+ {
+ char errbuf[1024];
+ ERROR ("uptime plugin: perfstat_cpu_total: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ hertz = sysconf(_SC_CLK_TCK);
+ if (hertz <= 0)
+ hertz = HZ;
+
+ boottime = time(NULL) - cputotal.lbolt / hertz;
+#endif /* HAVE_PERFSTAT */
return (0);
} /* }}} int uptime_init */
sstrncpy (vl.host, q_area->host, sizeof (vl.host));
sstrncpy (vl.plugin, q_area->plugin, sizeof (vl.plugin));
- sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.type_instance));
+ sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
sstrncpy (vl.type, r->type, sizeof (vl.type));
/* Set vl.type_instance {{{ */
if (h == NULL)
return;
+ pthread_mutex_destroy (&h->lock);
free (h->filename);
fbh_free_tree (h->tree);
} /* }}} void fbh_destroy */
/*
* Global variables
*/
-static kstat_t *ksp;
+
extern kstat_ctl_t *kc;
static void za_submit (const char* type, const char* type_instance, value_t* values, int values_len)
{
gauge_t arc_hits, arc_misses, l2_hits, l2_misses;
value_t l2_io[2];
+ kstat_t *ksp = NULL;
get_kstat (&ksp, "zfs", 0, "arcstats");
if (ksp == NULL)
static int za_init (void) /* {{{ */
{
- ksp = NULL;
-
/* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */
if (kc == NULL)
{