regex match: Fix unexpected match with empty meta data
[collectd.git] / src / uptime.c
index 4edfa84..dd33ab3 100644 (file)
  **/
 
 #include "collectd.h"
-#include "common.h"
+
 #include "plugin.h"
+#include "utils/common/common.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;
-extern kstat_ctl_t *kc;
-/* #endif HAVE_LIBKSTAT */
 
-#elif HAVE_SYS_SYSCTL_H
-static time_t boottime;
+#if HAVE_KSTAT_H
+#include <kstat.h>
 #endif
 
-static void uptime_submit (gauge_t uptime)
-{
-       value_t values[1];
-       value_list_t vl = VALUE_LIST_INIT;
+#if HAVE_LIBKSTAT
+extern kstat_ctl_t *kc;
+#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 */