**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#if KERNEL_LINUX
-# define UPTIME_FILE "/proc/uptime"
-/* No need for includes, using /proc filesystem, Linux only. */
+#include <sys/sysinfo.h>
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
-/* Using kstats chain to retrieve the boot time, this applies to:
- * - Solaris / OpenSolaris
+/* Using kstats chain to retrieve the boot time on Solaris / OpenSolaris systems
*/
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYS_SYSCTL_H
-# include <sys/sysctl.h>
-/* Using sysctl interface to retrieve the boot time, this applies to:
- * - *BSD
- * - Darwin / OS X
- */
+#include <sys/sysctl.h>
+/* Using sysctl interface to retrieve the boot time on *BSD / Darwin / OS X
+ * systems */
/* #endif HAVE_SYS_SYSCTL_H */
+#elif HAVE_PERFSTAT
+#include <libperfstat.h>
+#include <sys/protosw.h>
+/* Using perfstat_cpu_total to retrive the boot time in AIX */
+/* #endif HAVE_PERFSTAT */
+
#else
-# error "No applicable input method."
+#error "No applicable input method."
#endif
-/*
+/*
* Global variables
*/
-#if KERNEL_LINUX
-/* global variables not needed */
-/* #endif KERNEL_LINUX */
-#elif HAVE_LIBKSTAT
-static time_t boottime;
+#if HAVE_LIBKSTAT
extern kstat_ctl_t *kc;
-/* #endif HAVE_LIBKSTAT */
-
-#elif HAVE_SYS_SYSCTL_H
-static time_t boottime;
-#endif
-
-static void uptime_submit (gauge_t uptime)
-{
- value_t values[1];
- value_list_t vl = VALUE_LIST_INIT;
+#endif /* #endif HAVE_LIBKSTAT */
- values[0].gauge = uptime;
+static void uptime_submit(gauge_t value) {
+ value_list_t vl = VALUE_LIST_INIT;
- vl.values = values;
- vl.values_len = 1;
+ vl.values = &(value_t){.gauge = value};
+ vl.values_len = 1;
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
- sstrncpy (vl.plugin, "uptime", sizeof (vl.plugin));
- sstrncpy (vl.type, "uptime", sizeof (vl.type));
+ sstrncpy(vl.plugin, "uptime", sizeof(vl.plugin));
+ sstrncpy(vl.type, "uptime", sizeof(vl.type));
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values(&vl);
}
-#if !defined(KERNEL_LINUX) || !KERNEL_LINUX
-static int uptime_init (void)
-{
-/* NOTE
-
- On unix systems other than Linux there is no /proc filesystem which
- calculates the uptime every time we call a read for the /proc/uptime
- file, the only information available is the boot time (in unix time,
- since epoch). Hence there is no need to read, every time the
- plugin_read is called, a value that won't change: this is a right
- task for the uptime_init function. However, since uptime_init is run
- only once, if the function fails in retrieving the boot time, the
- plugin is unregistered and there is no chance to try again later.
- Nevertheless, this is very unlikely to happen.
+/*
+ * On most unix systems the uptime is calculated by looking at the boot
+ * time (stored in unix time, since epoch) and the current one. We are
+ * going to do the same, reading the boot time value while executing
+ * the uptime_init function (there is no need to read, every time the
+ * plugin_read is called, a value that won't change). However, since
+ * uptime_init is run only once, if the function fails in retrieving
+ * the boot time, the plugin is unregistered and there is no chance to
+ * try again later. Nevertheless, this is very unlikely to happen.
*/
+static time_t uptime_get_sys(void) { /* {{{ */
+ time_t result;
+#if KERNEL_LINUX
+ struct sysinfo info;
+ int status;
-# if HAVE_LIBKSTAT
- kstat_t *ksp;
- kstat_named_t *knp;
-
- ksp = NULL;
- knp = NULL;
-
- /* kstats chain already opened by update_kstat (using *kc), let's verify everything went fine. */
- if (kc == NULL)
- {
- ERROR ("uptime plugin: kstat chain control structure not available.");
- return (-1);
- }
-
- ksp = kstat_lookup (kc, "unix", 0, "system_misc");
- if (ksp == NULL)
- {
- ERROR ("uptime plugin: Cannot find unix:0:system_misc kstat.");
- return (-1);
- }
-
- if (kstat_read (kc, ksp, NULL) < 0)
- {
- ERROR ("uptime plugin: kstat_read failed.");
- return (-1);
- }
-
- knp = (kstat_named_t *) kstat_data_lookup (ksp, "boot_time");
- if (knp == NULL)
- {
- ERROR ("uptime plugin: kstat_data_lookup (boot_time) failed.");
- return (-1);
- }
-
- boottime = (time_t) knp->value.ui32;
+ status = sysinfo(&info);
+ if (status != 0) {
+ ERROR("uptime plugin: Error calling sysinfo: %s", STRERRNO);
+ return -1;
+ }
+
+ result = (time_t)info.uptime;
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+ kstat_t *ksp;
+ kstat_named_t *knp;
+
+ ksp = NULL;
+ knp = NULL;
+
+ /* kstats chain already opened by update_kstat (using *kc), verify everything
+ * went fine. */
+ if (kc == NULL) {
+ ERROR("uptime plugin: kstat chain control structure not available.");
+ return -1;
+ }
+
+ ksp = kstat_lookup(kc, "unix", 0, "system_misc");
+ if (ksp == NULL) {
+ ERROR("uptime plugin: Cannot find unix:0:system_misc kstat.");
+ return -1;
+ }
+
+ if (kstat_read(kc, ksp, NULL) < 0) {
+ ERROR("uptime plugin: kstat_read failed.");
+ return -1;
+ }
+
+ knp = (kstat_named_t *)kstat_data_lookup(ksp, "boot_time");
+ if (knp == NULL) {
+ ERROR("uptime plugin: kstat_data_lookup (boot_time) failed.");
+ return -1;
+ }
+
+ if (knp->value.ui32 == 0) {
+ ERROR("uptime plugin: kstat_data_lookup returned success, "
+ "but `boottime' is zero!");
+ return -1;
+ }
+
+ result = time(NULL) - (time_t)knp->value.ui32;
/* #endif HAVE_LIBKSTAT */
-# elif HAVE_SYS_SYSCTL_H
- struct timeval boottv;
- size_t boottv_len;
- int status;
+#elif HAVE_SYS_SYSCTL_H
+ struct timeval boottv = {0};
+ size_t boottv_len;
+ int status;
- int mib[2];
+ int mib[] = {CTL_KERN, KERN_BOOTTIME};
- mib[0] = CTL_KERN;
- mib[1] = KERN_BOOTTIME;
+ boottv_len = sizeof(boottv);
- memset (&boottv, 0, sizeof (boottv));
- boottv_len = sizeof (boottv);
+ status = sysctl(mib, STATIC_ARRAY_SIZE(mib), &boottv, &boottv_len,
+ /* new_value = */ NULL, /* new_length = */ 0);
+ if (status != 0) {
+ ERROR("uptime plugin: No value read from sysctl interface: %s", STRERRNO);
+ return -1;
+ }
- status = sysctl (mib, STATIC_ARRAY_SIZE (mib), &boottv, &boottv_len,
- /* new_value = */ NULL, /* new_length = */ 0);
- if (status != 0)
- {
- char errbuf[1024];
- ERROR ("uptime plugin: No value read from sysctl interface: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
+ if (boottv.tv_sec == 0) {
+ ERROR("uptime plugin: sysctl(3) returned success, "
+ "but `boottime' is zero!");
+ return -1;
+ }
- boottime = boottv.tv_sec;
- if (boottime == 0)
- {
- ERROR ("uptime plugin: sysctl(3) returned success, "
- "but `boottime' is zero!");
- return (-1);
- }
-#endif /* HAVE_SYS_SYSCTL_H */
+ result = time(NULL) - boottv.tv_sec;
+/* #endif HAVE_SYS_SYSCTL_H */
- return (0);
+#elif HAVE_PERFSTAT
+ int status;
+ perfstat_cpu_total_t cputotal;
+ int hertz;
-}
-#endif /* !KERNEL_LINUX */
+ status = perfstat_cpu_total(NULL, &cputotal, sizeof(perfstat_cpu_total_t), 1);
+ if (status < 0) {
+ ERROR("uptime plugin: perfstat_cpu_total: %s", STRERRNO);
+ return -1;
+ }
-static int uptime_read (void)
-{
- gauge_t uptime;
+ hertz = sysconf(_SC_CLK_TCK);
+ if (hertz <= 0)
+ hertz = HZ;
-#if KERNEL_LINUX
- FILE *fh;
-
- fh = fopen (UPTIME_FILE, "r");
-
- if (fh == NULL)
- {
- char errbuf[1024];
- ERROR ("uptime plugin: Cannot open "UPTIME_FILE": %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
-
- if ( fscanf (fh, "%lf", &uptime) < 1 )
- {
- WARNING ("uptime plugin: No value read from "UPTIME_FILE);
- fclose (fh);
- return (-1);
- }
-
- fclose (fh);
-/* #endif KERNEL_LINUX */
+ result = cputotal.lbolt / hertz;
+#endif /* HAVE_PERFSTAT */
-#elif HAVE_LIBKSTAT || HAVE_SYS_SYSCTL_H
- time_t elapsed;
+ return result;
+} /* }}} int uptime_get_sys */
- elapsed = time (NULL) - boottime;
+static int uptime_read(void) {
+ gauge_t uptime;
+ time_t elapsed;
- uptime = (gauge_t) elapsed;
-#endif /* HAVE_LIBKSTAT || HAVE_SYS_SYSCTL_H */
+ /* calculate the amount of time elapsed since boot, AKA uptime */
+ elapsed = uptime_get_sys();
- uptime_submit (uptime);
+ uptime = (gauge_t)elapsed;
- return (0);
+ uptime_submit(uptime);
+
+ return 0;
}
-void module_register (void)
-{
-#if !defined(KERNEL_LINUX) || !KERNEL_LINUX
- plugin_register_init ("uptime", uptime_init);
-#endif
- plugin_register_read ("uptime", uptime_read);
+void module_register(void) {
+ plugin_register_read("uptime", uptime_read);
} /* void module_register */