modbus plugin: Fix a small memory leak in mb_config_add_datagroup().
[collectd.git] / src / contextswitch.c
index 0db727c..c207318 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/contextswitch.c
  * Copyright (C) 2009  Patrik Weiskircher
+ * Copyright (C) 2010  Kimo Rosenbaum
  *
  * 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
  *
  * Authors:
  *   Patrik Weiskircher <weiskircher at inqnet.at>
+ *   Kimo Rosenbaum <http://github.com/kimor79>
  **/
 
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
 
-#if !KERNEL_LINUX
+#ifdef HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+#endif
+
+#if HAVE_SYSCTLBYNAME
+/* no global variables */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif KERNEL_LINUX
+/* no global variables */
+/* #endif KERNEL_LINUX */
+
+#else
 # error "No applicable input method."
 #endif
 
-static void cs_submit (unsigned long context_switches)
+static void cs_submit (derive_t context_switches)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = context_switches;
+       values[0].derive = (derive_t) context_switches;
 
        vl.values = values;
        vl.values_len = 1;
@@ -45,11 +59,31 @@ static void cs_submit (unsigned long context_switches)
 
 static int cs_read (void)
 {
+#if HAVE_SYSCTLBYNAME
+       int value = 0;
+       size_t value_len = sizeof (value);
+       int status;
+
+       status = sysctlbyname ("vm.stats.sys.v_swtch",
+                       &value, &value_len,
+                       /* new pointer = */ NULL, /* new length = */ 0);
+       if (status != 0)
+       {
+               ERROR("contextswitch plugin: sysctlbyname "
+                               "(vm.stats.sys.v_swtch) failed");
+               return (-1);
+       }
+
+       cs_submit (value);
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif KERNEL_LINUX
        FILE *fh;
        char buffer[64];
        int numfields;
-       char *fields[2];
-       unsigned long result = 0;
+       char *fields[3];
+       derive_t result = 0;
+       int status = -2;
 
        fh = fopen ("/proc/stat", "r");
        if (fh == NULL) {
@@ -58,35 +92,38 @@ static int cs_read (void)
                return (-1);
        }
 
-       while (fgets(buffer, sizeof(buffer), fh))
+       while (fgets(buffer, sizeof(buffer), fh) != NULL)
        {
-               if (strncmp(buffer, "ctxt", 4))
+               char *endptr;
+
+               numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE (fields));
+               if (numfields != 2)
                        continue;
 
-               numfields = strsplit(buffer, fields, 2);
-               if (numfields != 2) {
-                       ERROR ("contextswitch plugin: ctxt in /proc/stat contains more than 2 fields.");
-                       break;
-               }
+               if (strcmp("ctxt", fields[0]) != 0)
+                       continue;
 
-               result = strtoul(fields[1], NULL, 10);
-               if (errno == ERANGE && result == ULONG_MAX) {
-                       ERROR ("contextswitch plugin: ctxt value in /proc/stat overflows.");
+               errno = 0;
+               endptr = NULL;
+               result = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10);
+               if ((endptr == fields[1]) || (errno != 0)) {
+                       ERROR ("contextswitch plugin: Cannot parse ctxt value: %s",
+                                       fields[1]);
+                       status = -1;
                        break;
                }
 
+               cs_submit(result);
+               status = 0;
                break;
        }
        fclose(fh);
 
-       if (result == 0) {
-               ERROR ("contextswitch plugin: unable to find context switch value.");
-               return -1;
-       }
-
-       cs_submit(result);
+       if (status == -2)
+               ERROR ("contextswitch plugin: Unable to find context switch value.");
+#endif /* KERNEL_LINUX */
 
-       return 0;
+       return status;
 }
 
 void module_register (void)