Merge pull request #550 from marekbecka/nfs4
[collectd.git] / src / swap.c
index 9a8641c..0642afa 100644 (file)
@@ -106,61 +106,36 @@ static int pagesize;
 static _Bool values_absolute = 1;
 static _Bool values_percentage = 0;
 
-static const char *config_keys[] =
+static int swap_config (oconfig_item_t *ci) /* {{{ */
 {
-       "ReportBytes",
-       "ReportByDevice",
-       "ValuesAbsolute",
-       "ValuesPercentage"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-
-static int swap_config (const char *key, const char *value) /* {{{ */
-{
-       if (strcasecmp ("ReportBytes", key) == 0)
+       int i;
+
+       for (i = 0; i < ci->children_num; i++)
        {
+               oconfig_item_t *child = ci->children + i;
+               if (strcasecmp ("ReportBytes", child->key) == 0)
 #if KERNEL_LINUX
-               report_bytes = IS_TRUE (value) ? 1 : 0;
+                       cf_util_get_boolean (child, &report_bytes);
 #else
-               WARNING ("swap plugin: The \"ReportBytes\" option is only "
-                               "valid under Linux. "
-                               "The option is going to be ignored.");
+                       WARNING ("swap plugin: The \"ReportBytes\" option "
+                                       "is only valid under Linux. "
+                                       "The option is going to be ignored.");
 #endif
-       }
-       else if (strcasecmp ("ReportByDevice", key) == 0)
-       {
+               else if (strcasecmp ("ReportByDevice", child->key) == 0)
 #if SWAP_HAVE_REPORT_BY_DEVICE
-               if (IS_TRUE (value))
-                       report_by_device = 1;
-               else
-                       report_by_device = 0;
+                       cf_util_get_boolean (child, &report_by_device);
 #else
-               WARNING ("swap plugin: The \"ReportByDevice\" option is not "
-                               "supported on this platform. "
-                               "The option is going to be ignored.");
+                       WARNING ("swap plugin: The \"ReportByDevice\" option "
+                                       "is not supported on this platform. "
+                                       "The option is going to be ignored.");
 #endif /* SWAP_HAVE_REPORT_BY_DEVICE */
-       }
-       else if (strcasecmp (key, "ValuesAbsolute") == 0)
-       {
-               if (IS_TRUE (value))
-                       values_absolute = 1;
+               else if (strcasecmp ("ValuesAbsolute", child->key) == 0)
+                       cf_util_get_boolean (child, &values_absolute);
+               else if (strcasecmp ("ValuesPercentage", child->key) == 0)
+                       cf_util_get_boolean (child, &values_percentage);
                else
-                       values_absolute = 0;
-
-               return (0);
-       }
-       else if (strcasecmp (key, "ValuesPercentage") == 0)
-       {
-               if (IS_TRUE (value))
-                       values_percentage = 1;
-               else
-                       values_percentage = 0;
-
-               return (0);
-       }
-       else
-       {
-               return (-1);
+                       WARNING ("swap plugin: Unknown config option: \"%s\"",
+                                       child->key);
        }
 
        return (0);
@@ -213,44 +188,50 @@ static int swap_init (void) /* {{{ */
        return (0);
 } /* }}} int swap_init */
 
-static void swap_submit (const char *plugin_instance, /* {{{ */
-               const char *type, const char *type_instance,
-               value_t value)
+static void swap_submit_usage (char const *plugin_instance, /* {{{ */
+               gauge_t used, gauge_t free,
+               char const *other_name, gauge_t other_value)
 {
+       value_t v[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       assert (type != NULL);
-
-       vl.values = &value;
-       vl.values_len = 1;
+       vl.values = v;
+       vl.values_len = STATIC_ARRAY_SIZE (v);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
        if (plugin_instance != NULL)
-               sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
-       sstrncpy (vl.type, type, sizeof (vl.type));
-       if (type_instance != NULL)
-               sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+               sstrncpy (vl.plugin_instance, plugin_instance,
+                               sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "swap", sizeof (vl.type));
 
-       plugin_dispatch_values (&vl);
-} /* }}} void swap_submit_inst */
+       if (values_absolute)
+               plugin_dispatch_multivalue (&vl, 0,
+                               "used", used, "free", free,
+                               other_name, other_value, NULL);
+       if (values_percentage)
+               plugin_dispatch_multivalue (&vl, 1,
+                               "used", used, "free", free,
+                               other_name, other_value, NULL);
+} /* }}} void swap_submit_usage */
 
-static void swap_submit_gauge (char const *plugin_instance, char const *type, /* {{{ */
-               char const *type_instance, gauge_t value)
+#if KERNEL_LINUX || HAVE_PERFSTAT
+__attribute__((nonnull(1)))
+static void swap_submit_derive (char const *type_instance, /* {{{ */
+               derive_t value)
 {
-       value_t v;
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t v[1];
 
-       v.gauge = value;
-       swap_submit (plugin_instance, type, type_instance, v);
-} /* }}} void swap_submit_gauge */
+       v[0].derive = value;
 
-#if KERNEL_LINUX || HAVE_PERFSTAT
-static void swap_submit_derive (const char *plugin_instance, /* {{{ */
-               const char *type_instance, derive_t value)
-{
-       value_t v;
+       vl.values = v;
+       vl.values_len = STATIC_ARRAY_SIZE (v);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
+       sstrncpy (vl.type, "swap_io", sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
-       v.derive = value;
-       swap_submit (plugin_instance, "swap_io", type_instance, v);
+       plugin_dispatch_values (&vl);
 } /* }}} void swap_submit_derive */
 #endif
 
@@ -276,9 +257,8 @@ static int swap_read_separate (void) /* {{{ */
                char *endptr;
 
                char path[PATH_MAX];
-               gauge_t size;
+               gauge_t total;
                gauge_t used;
-               gauge_t free;
 
                numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
                if (numfields != 5)
@@ -289,7 +269,7 @@ static int swap_read_separate (void) /* {{{ */
 
                errno = 0;
                endptr = NULL;
-               size = strtod (fields[2], &endptr);
+               total = strtod (fields[2], &endptr);
                if ((endptr == fields[2]) || (errno != 0))
                        continue;
 
@@ -299,21 +279,10 @@ static int swap_read_separate (void) /* {{{ */
                if ((endptr == fields[3]) || (errno != 0))
                        continue;
 
-               if (size < used)
+               if (total < used)
                        continue;
 
-               free = size - used;
-
-               if (values_absolute)
-               {
-                       swap_submit_gauge (path, "swap", "used", used);
-                       swap_submit_gauge (path, "swap", "free", free);
-               }
-               if (values_percentage)
-               {
-                       swap_submit_gauge (path, "percent", "used", 100.0 * used / (used + free));
-                       swap_submit_gauge (path, "percent", "free", 100.0 * free / (used + free));
-               }
+               swap_submit_usage (path, used, total - used, NULL, NAN);
        }
 
        fclose (fh);
@@ -326,11 +295,10 @@ static int swap_read_combined (void) /* {{{ */
        FILE *fh;
        char buffer[1024];
 
-       uint8_t have_data = 0;
-       gauge_t swap_used   = 0.0;
-       gauge_t swap_cached = 0.0;
-       gauge_t swap_free   = 0.0;
-       gauge_t swap_total  = 0.0;
+       gauge_t swap_used   = NAN;
+       gauge_t swap_cached = NAN;
+       gauge_t swap_free   = NAN;
+       gauge_t swap_total  = NAN;
 
        fh = fopen ("/proc/meminfo", "r");
        if (fh == NULL)
@@ -351,47 +319,30 @@ static int swap_read_combined (void) /* {{{ */
                        continue;
 
                if (strcasecmp (fields[0], "SwapTotal:") == 0)
-               {
-                       swap_total = strtod (fields[1], /* endptr = */ NULL);
-                       have_data |= 0x01;
-               }
+                       strtogauge (fields[1], &swap_total);
                else if (strcasecmp (fields[0], "SwapFree:") == 0)
-               {
-                       swap_free = strtod (fields[1], /* endptr = */ NULL);
-                       have_data |= 0x02;
-               }
+                       strtogauge (fields[1], &swap_free);
                else if (strcasecmp (fields[0], "SwapCached:") == 0)
-               {
-                       swap_cached = strtod (fields[1], /* endptr = */ NULL);
-                       have_data |= 0x04;
-               }
+                       strtogauge (fields[1], &swap_cached);
        }
 
        fclose (fh);
 
-       if (have_data != 0x07)
+       if (isnan (swap_total) || isnan (swap_free))
                return (ENOENT);
 
-       if (isnan (swap_total)
-                       || (swap_total <= 0.0)
-                       || ((swap_free + swap_cached) > swap_total))
-               return (EINVAL);
-
-       swap_used = swap_total - (swap_free + swap_cached);
+       /* Some systems, OpenVZ for example, don't provide SwapCached. */
+       if (isnan (swap_cached))
+               swap_used = swap_total - swap_free;
+       else
+               swap_used = swap_total - (swap_free + swap_cached);
+       assert (!isnan (swap_used));
 
-       if (values_absolute)
-       {
-               swap_submit_gauge (NULL, "swap", "used",   1024.0 * swap_used);
-               swap_submit_gauge (NULL, "swap", "free",   1024.0 * swap_free);
-               swap_submit_gauge (NULL, "swap", "cached", 1024.0 * swap_cached);
-       }
-       if (values_percentage)
-       {
-               swap_submit_gauge (NULL, "percent", "used",   100.0 * swap_used / swap_total);
-               swap_submit_gauge (NULL, "percent", "free",   100.0 * swap_free / swap_total);
-               swap_submit_gauge (NULL, "percent", "cached", 100.0 * swap_cached / swap_total);
-       }
+       if (swap_used < 0.0)
+               return (EINVAL);
 
+       swap_submit_usage (NULL, swap_used, swap_free,
+                       isnan (swap_cached) ? NULL : "cached", swap_cached);
        return (0);
 } /* }}} int swap_read_combined */
 
@@ -469,8 +420,8 @@ static int swap_read_io (void) /* {{{ */
                swap_out = swap_out * pagesize;
        }
 
-       swap_submit_derive (NULL, "in",  swap_in);
-       swap_submit_derive (NULL, "out", swap_out);
+       swap_submit_derive ("in",  swap_in);
+       swap_submit_derive ("out", swap_out);
 
        return (0);
 } /* }}} int swap_read_io */
@@ -540,21 +491,7 @@ static int swap_read_kstat (void) /* {{{ */
        swap_resv  = (gauge_t) ((ai.ani_resv + ai.ani_free - ai.ani_max) * pagesize);
        swap_avail = (gauge_t) ((ai.ani_max - ai.ani_resv) * pagesize);
 
-       if (values_absolute)
-       {
-               swap_submit_gauge (NULL, "swap", "used", swap_alloc);
-               swap_submit_gauge (NULL, "swap", "free", swap_avail);
-               swap_submit_gauge (NULL, "swap", "reserved", swap_resv);
-       }
-       if (values_percentage)
-       {
-               gauge_t swap_total = swap_alloc + swap_avail + swap_resv;
-
-               swap_submit_gauge (NULL, "percent", "used", 100.0 * swap_alloc / swap_total);
-               swap_submit_gauge (NULL, "percent", "free", 100.0 * swap_avail / swap_total);
-               swap_submit_gauge (NULL, "percent", "cached", 100.0 * swap_resv / swap_total);
-       }
-
+       swap_submit_usage (NULL, swap_alloc, swap_avail, "reserved", swap_resv);
        return (0);
 } /* }}} int swap_read_kstat */
 /* #endif 0 && HAVE_LIBKSTAT */
@@ -653,17 +590,8 @@ static int swap_read (void) /* {{{ */
                sstrncpy (path, s->swt_ent[i].ste_path, sizeof (path));
                escape_slashes (path, sizeof (path));
 
-               if (values_absolute)
-               {
-                       swap_submit_gauge (path, "swap", "used", this_total - this_avail);
-                       swap_submit_gauge (path, "swap", "free", this_avail);
-               }
-               if (values_percentage)
-               {
-                       swap_submit_gauge (path, "percent", "used", 100.0 * (this_total - this_avail) / this_total);
-                       swap_submit_gauge (path, "percent", "free", 100.0 * this_avail / this_total);
-               }
-
+               swap_submit_usage (path, this_total - this_avail, this_avail,
+                               NULL, NAN);
         } /* for (swap_num) */
 
         if (total < avail)
@@ -675,21 +603,10 @@ static int swap_read (void) /* {{{ */
                 return (-1);
         }
 
-       /* If the "separate" option was specified (report_by_device == 2), all
+       /* If the "separate" option was specified (report_by_device == 1), all
         * values have already been dispatched from within the loop. */
        if (!report_by_device)
-       {
-               if (values_absolute)
-               {
-                       swap_submit_gauge (NULL, "swap", "used", (total - avail));
-                       swap_submit_gauge (NULL, "swap", "free", avail);
-               }
-               if (values_percentage)
-               {
-                       swap_submit_gauge (NULL, "percent", "used", 100.0 * (total - avail) / total);
-                       swap_submit_gauge (NULL, "percent", "free", 100.0 * avail / total);
-               }
-       }
+               swap_submit_usage (NULL, total - avail, avail, NULL, NAN);
 
        sfree (s_paths);
         sfree (s);
@@ -740,6 +657,8 @@ static int swap_read (void) /* {{{ */
 # define C_SWAP_BLOCK_SIZE 512.0
 #endif
 
+       /* TODO: Report per-device stats. The path name is available from
+        * swap_entries[i].se_path */
        for (i = 0; i < swap_num; i++)
        {
                if ((swap_entries[i].se_flags & SWF_ENABLE) == 0)
@@ -756,19 +675,9 @@ static int swap_read (void) /* {{{ */
                return (-1);
        }
 
-       if (values_absolute)
-       {
-               swap_submit_gauge (NULL, "swap", "used", used);
-               swap_submit_gauge (NULL, "swap", "free", (total - used));
-       }
-       if (values_percentage)
-       {
-               swap_submit_gauge (NULL, "percent", "used", 100.0 * used / total);
-               swap_submit_gauge (NULL, "percent", "free", 100.0 * (total - used) / total);
-       }
+       swap_submit_usage (NULL, used, total - used, NULL, NAN);
 
        sfree (swap_entries);
-
        return (0);
 } /* }}} int swap_read */
 /* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
@@ -791,17 +700,9 @@ static int swap_read (void) /* {{{ */
                return (-1);
 
        /* The returned values are bytes. */
-       if (values_absolute)
-       {
-               swap_submit_gauge (NULL, "swap", "used", (gauge_t) sw_usage.xsu_used);
-               swap_submit_gauge (NULL, "swap", "free", (gauge_t) sw_usage.xsu_avail);
-       }
-       if (values_percentage)
-       {
-               gauge_t swap_total = (gauge_t) (sw_usage.xsu_used + sw_usage.xsu_avail);
-               swap_submit_gauge (NULL, "percent", "used", 100.0 * ((gauge_t) sw_usage.xsu_used)  / swap_total);
-               swap_submit_gauge (NULL, "percent", "free", 100.0 * ((gauge_t) sw_usage.xsu_avail) / swap_total);
-       }
+       swap_submit_usage (NULL,
+                       (gauge_t) sw_usage.xsu_used, (gauge_t) sw_usage.xsu_avail,
+                       NULL, NAN);
 
        return (0);
 } /* }}} int swap_read */
@@ -814,7 +715,6 @@ static int swap_read (void) /* {{{ */
        int             status;
 
        gauge_t used;
-       gauge_t free;
        gauge_t total;
 
        if (kvm_obj == NULL)
@@ -831,18 +731,7 @@ static int swap_read (void) /* {{{ */
        total *= (gauge_t) kvm_pagesize;
        used  *= (gauge_t) kvm_pagesize;
 
-       free = total - used;
-
-       if (values_absolute)
-       {
-               swap_submit_gauge (NULL, "swap", "used", used);
-               swap_submit_gauge (NULL, "swap", "free", free);
-       }
-       if (values_percentage)
-       {
-               swap_submit_gauge (NULL, "percent", "used", 100.0 * used / total);
-               swap_submit_gauge (NULL, "percent", "free", 100.0 * free / total);
-       }
+       swap_submit_usage (NULL, used, total - used, NULL, NAN);
 
        return (0);
 } /* }}} int swap_read */
@@ -854,21 +743,11 @@ static int swap_read (void) /* {{{ */
        sg_swap_stats *swap;
 
        swap = sg_get_swap_stats ();
-
        if (swap == NULL)
                return (-1);
 
-       if (values_absolute)
-       {
-               swap_submit_gauge (NULL, "swap", "used", (gauge_t) swap->used);
-               swap_submit_gauge (NULL, "swap", "free", (gauge_t) swap->free);
-       }
-       if (values_percentage)
-       {
-               gauge_t swap_total = (gauge_t) (swap->used + swap->free);
-               swap_submit_gauge (NULL, "percent", "used", 100.0 * ((gauge_t) swap->used) / swap_total);
-               swap_submit_gauge (NULL, "percent", "free", 100.0 * ((gauge_t) swap->free) / swap_total);
-       }
+       swap_submit_usage (NULL, (gauge_t) swap->used, (gauge_t) swap->free,
+                       NULL, NAN);
 
        return (0);
 } /* }}} int swap_read */
@@ -880,6 +759,10 @@ static int swap_read (void) /* {{{ */
        perfstat_memory_total_t pmemory;
        int status;
 
+       gauge_t total;
+       gauge_t free;
+       gauge_t reserved;
+
        memset (&pmemory, 0, sizeof (pmemory));
         status = perfstat_memory_total (NULL, &pmemory, sizeof(perfstat_memory_total_t), 1);
        if (status < 0)
@@ -890,21 +773,13 @@ static int swap_read (void) /* {{{ */
                 return (-1);
         }
 
-        if (values_absolute)
-        {
-               swap_submit_gauge (NULL, "swap", "used", (gauge_t) (pmemory.pgsp_total - pmemory.pgsp_free) * pagesize);
-               swap_submit_gauge (NULL, "swap", "free", (gauge_t) pmemory.pgsp_free * pagesize);
-               swap_submit_gauge (NULL, "swap", "reserved", (gauge_t) pmemory.pgsp_rsvd * pagesize);
-       }
-        if (values_percentage)
-        {
-               gauge_t swap_total = (gauge_t) pmemory.pgsp_total;
-               swap_submit_gauge (NULL, "percent", "used",     100.0 * ((gauge_t) (pmemory.pgsp_total - pmemory.pgsp_free)) / swap_total);
-               swap_submit_gauge (NULL, "percent", "free",     100.0 * ((gauge_t) pmemory.pgsp_free) / swap_total);
-               swap_submit_gauge (NULL, "percent", "reserved", 100.0 * ((gauge_t) pmemory.pgsp_rsvd) / swap_total);
-       }
-       swap_submit_derive (NULL, "in",  (derive_t) pmemory.pgspins * pagesize);
-       swap_submit_derive (NULL, "out", (derive_t) pmemory.pgspouts * pagesize);
+       total    = (gauge_t) (pmemory.pgsp_total * pagesize);
+       free     = (gauge_t) (pmemory.pgsp_free * pagesize);
+       reserved = (gauge_t) (pmemory.pgsp_rsvd * pagesize);
+
+       swap_submit_usage (NULL, total - free, free, "reserved", reserved);
+       swap_submit_derive ("in",  (derive_t) pmemory.pgspins * pagesize);
+       swap_submit_derive ("out", (derive_t) pmemory.pgspouts * pagesize);
 
        return (0);
 } /* }}} int swap_read */
@@ -912,8 +787,7 @@ static int swap_read (void) /* {{{ */
 
 void module_register (void)
 {
-       plugin_register_config ("swap", swap_config,
-                       config_keys, config_keys_num);
+       plugin_register_complex_config ("swap", swap_config);
        plugin_register_init ("swap", swap_init);
        plugin_register_read ("swap", swap_read);
 } /* void module_register */