Merge branch 'pr/1918'
authorFlorian Forster <octo@collectd.org>
Fri, 16 Sep 2016 08:50:34 +0000 (10:50 +0200)
committerFlorian Forster <octo@collectd.org>
Fri, 16 Sep 2016 08:50:34 +0000 (10:50 +0200)
123 files changed:
ChangeLog
bindings/perl/lib/Collectd.pm
contrib/examples/myplugin.c
contrib/migrate-4-5.px
src/Makefile.am
src/amqp.c
src/apache.c
src/apcups.c
src/apple_sensors.c
src/aquaero.c
src/ascent.c
src/battery.c
src/battery_statefs.c
src/bind.c
src/chrony.c
src/collectd-perl.pod
src/collectd.conf.in
src/collectd.conf.pod
src/conntrack.c
src/contextswitch.c
src/cpu.c
src/cpufreq.c
src/cpusleep.c
src/curl.c
src/curl_json.c
src/curl_xml.c
src/daemon/common.c
src/daemon/common.h
src/daemon/common_test.c
src/daemon/meta_data.c
src/daemon/meta_data.h
src/daemon/plugin.c
src/dbi.c
src/df.c
src/disk.c
src/dns.c
src/email.c
src/entropy.c
src/ethstat.c
src/fhcount.c
src/filecount.c
src/gps.c
src/hddtemp.c
src/hugepages.c
src/interface.c
src/ipc.c
src/ipmi.c
src/iptables.c
src/ipvs.c
src/irq.c
src/java.c
src/load.c
src/lpar.c
src/lua.c
src/lvm.c
src/madwifi.c
src/match_regex.c
src/mbmon.c
src/md.c
src/memcachec.c
src/memcached.c
src/mic.c
src/modbus.c
src/mqtt.c
src/multimeter.c
src/mysql.c
src/netapp.c
src/netlink.c
src/nginx.c
src/ntpd.c
src/nut.c
src/olsrd.c
src/onewire.c
src/openldap.c
src/openvpn.c
src/perl.c
src/pinba.c
src/ping.c
src/powerdns.c
src/processes.c
src/protocols.c
src/python.c
src/redis.c
src/routeros.c
src/rrdcached.c
src/sensors.c
src/serial.c
src/sigrok.c
src/smart.c
src/snmp.c
src/statsd.c
src/swap.c
src/tail.c
src/tail_csv.c
src/tape.c
src/target_replace.c
src/target_set.c
src/target_v5upgrade.c
src/teamspeak2.c
src/ted.c
src/thermal.c
src/tokyotyrant.c
src/turbostat.c
src/types.db
src/uptime.c
src/users.c
src/utils_format_graphite.c
src/utils_format_graphite.h
src/varnish.c
src/virt.c
src/vmem.c
src/vserver.c
src/wireless.c
src/write_graphite.c
src/write_kafka.c
src/write_log.c
src/write_mongodb.c
src/write_redis.c
src/xencpu.c
src/xmms.c
src/zfs_arc.c
src/zookeeper.c
version-gen.sh

index 4e969b5..5155954 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,161 @@
+2016-09-11, Version 5.6.0
+       * Build system: An option to to avoid building the DF plugin against XFS
+         has been added. Thanks to Ruben Kerkhof. #1878
+       * Build system: Autoconf â‰¥ 2.60, a C99-capable compiler and pkg-config
+         are now required. Thanks to Ruben Kerkhof.
+       * Build system: Building with "-Werror" is now optional. Thanks to Ruben
+         Kerkhof. #1222
+       * Build system: Many compilation issues on non-Linux platforms have been
+         fixed, leading to wider plugin support. Thanks to Ruben Kerkhof,
+         Dagobert Michelsen, Havard Eidnes and Robert Viduya.
+       * Build system: The configuration summary now also ends up in
+         config.log. Thanks to Sebastian Harl.
+       * collectd: All command-line options now override global options from
+         the config file. Thanks to Sebastian Harl. #366
+       * collectd: A number of unit tests for commonly used functions have been
+         added. Thanks to Florian Forster.
+       * collectd: Plugins start up and read timeouts are now logged. Thanks to
+         Marc Fournier. #1293, #1254
+       * collectd: Support for a timeout has been added to "FLUSH" callbacks.
+         Thanks to Manuel Luis Sanmartín Rozada.
+       * collectd: The "-T" command line switch now reports more errors. Thanks
+         to Corey Kosak. #1642
+       * collectd: The max size of value list elements ("DATA_MAX_NAME_LEN")
+         has been doubled and is now configurable at build time. Thanks to Amy
+         Lin, Florian Forster and Radu Brumariu. #1120
+       * Set target: The "MetaData" option has been added. Thanks to Yves
+         Mettier and Kevin Bowling. #1106, #1656, #1913
+       * AMQP, Write_HTTP, Write_Kafka plugins: Support for libyajl < 2 has
+         been added. Thanks to Florian Forster.
+       * APC UPS plugin: Parsing of end markers has been fixed. Thanks to
+         Florian Forster #617
+       * APC UPS plugin: The "PersistentConnection" option has been added.
+         Thanks to Florian Forster #617
+       * ceph, DNS, Exec, IPTables, Ping, turbostat plugins: When running
+         unprivileged, these plugins will now warn about insuffiscient
+         permissions or capabilities(7). Thanks to Marc Fournier. #1530
+       * Chrony plugin: This new plugin collects NTP data from the chrony NTP
+         server. Thanks to Claudius Zingerli. #1548
+       * cpusleep plugin: This new plugin measures time spent by CPU in deep
+         sleep mode. Thanks to Rinigus. #1826
+       * CPU plugin: The "ReportNumCpu" option has been added. Thanks to Fabien
+         Wernli.
+       * cURL, cURL-JSON, cURL-XML plugins: The new "Statistics" reports
+         various per-HTTP connection timers. Thanks to Sebastian Harl. #1004
+       * DBI plugin: The "Interval" option has been added to "Database" blocks.
+         Thanks to Michal Bebjak.
+       * Disk plugin: Support for FreeBSD has been added. Thanks to Xin Li,
+         Brad Davis, Ruben Kerfhof and Kevin Bowling.
+       * Empty Counter match: Support for derives has been implemented. Thanks
+         to Florian Forster. #1813
+       * GenericJMX plugin: Support for TabularData and the "PluginName" option
+         have been added. Thanks to David Crane. #1290, #1291
+       * GPS plugin: This new plugin reports the number of sattelites seen by
+         and precision of a GPS receiver. Thanks to Nicolas Jourden. #1346
+       * gRPC plugin: This new client and server plugin allows sending and
+         receiving metrics using the gRPC protocol. Comparable to the UnixSock
+         plugin, but using TCP and TLS. Thanks to Sebastian Harl and Florian
+         Forster.
+       * Interface plugin: Reporting dropped packets has been added. Thanks to
+         Marc Falzon. #1555
+       * Interface plugin: The "ReportInactive" has been added, letting users
+         skip inactive network interfaces. Thanks to Rinigus. #1791
+       * Interface plugin: The new, Solaris-only "UniqueName" option has been
+         added. Thanks to Yoga Ramalingam. #1416
+       * Lua plugin: This new language binding allows writing plugins using the
+         Lua programming language. Thanks to Julien Ammous, Florian Forster and
+         Ruben Kerkhof.
+       * Memory plugin: Reporting of ARC memory on Solaris has been added.
+         Thanks to Brian ONeill.
+       * MQTT plugin: This new plugin sends metrics to and/or receives metrics
+         from an MQTT broker. Thanks to Marc Falzon, Jan-Piet Mens, Nicholas
+         Humfrey and Florian Forster. #805, #1124
+       * MySQL plugin: Connection to the database server can now be done over
+         SSL. Thanks to Brian Lalor. #1256
+       * MySQL plugin: Monitoring slow queries has been added. Thanks to skob.
+         #1773
+       * MySQL plugin: mysql_bpool_pages-flushed has been renamed to
+         mysql_bpool_counters-pages_flushed because the value is cumulative.
+         Thanks to Marek Becka.
+       * MySQL plugin: Support for Galera statistics has been added. Thanks to
+         Rachid Zarouali. #1849
+       * MySQL plugin: Support for InnoDB metrics was improved. Thanks to Aman
+         Gupta. #1111
+       * MySQL plugin: The "mysql_sort" type has been split into 3 different
+         types. Thanks to Pavel Rochnyack. #1592
+       * Network plugin: Decryption error logging has been improved. Thanks to
+         Pavel Rochnyack. #1735
+       * Notify Nagios plugin: This new plugin sends notifications to Nagios as
+         a passive check result. Thanks to Florian Forster.
+       * NTPd plugin: The plugin now detects if the ntp daemon reports
+         nanoseconds instead of microseconds. Thanks to Matwey V. Kornilov.
+         #1783
+       * OpenLDAP plugin: Several connection-related improvements have been
+         made. Thanks to Marc Fournier. #1308
+       * OpenLDAP plugin: Support for "simple authentication" has been added.
+         Thanks to Marek Becka. #1087
+       * Ping plugin: The "Size" option has been added, allowing the ICMP data
+         payload size to be configured. Thanks to Witold Baryluk. #1395
+       * PostgreSQL, DBI, Oracle plugins: The new "PluginInstanceFrom" option
+         has been added. Thanks to Pavel Rochnyack. #1707
+       * PowerDNS plugin: The recursor metrics have been updated to 3.7.3 and
+         missing rr types have been added. Thanks to Ruben Kerkhof.
+       * Processes plugin: Counting of context switches was added for Linux.
+         Thanks to Manuel Luis Sanmartín Rozada. #1036
+       * Processes plugin: Improve reliability of thread counts on Linux.
+         Thanks to Manuel Luis Sanmartín Rozada.
+       * Python plugin: Minimal Python version requirement has been bumped to
+         2.6. Thanks to Ruben Kerkhof. #1864
+       * Redis plugin: Several additional metrics are now collected. Thanks to
+         Marc Falzon and Matteo Contrini. #1807, #1483
+       * Sensors plugin: The "UseLabels" option has been added. Thanks to
+         Christian Fetzer.
+       * SMART plugin: The new "IgnoreSleepMode" option has been added. Thanks
+         to Scott Talbert. #1770
+       * SMART plugin: The new "UseSerial" option allows identifying devices in
+         a stable way. Thanks to Scott Talbert. #1794
+       * SNMP plugin: The "IpAddress" can now be used for instances. Thanks to
+         Vincent Bernat. #1397
+       * StatsD plugin: Latency calculation histogram is now able to shrink
+         automatically to optimal size. Thanks to Pavel Rochnyack. #1622
+       * StatsD plugin: The "CounterSum" option has been added. Thanks to
+         Florian Forster. #929, #1282, #1311
+       * UUID plugin: The plugin now also looks in in smbios system table and
+         "/sys/class/dmi". Thanks to Ruben Kerkhof. #1490
+       * virt plugin: The "PluginInstanceFormat" option has been added. Thanks
+         to Ruben Kerkhof. #1100
+       * Write Graphite plugin: The "ReconnectInterval" option has been added.
+         Thanks to Toni Moreno and Florian Forster.
+       * Write HTTP plugin: A KairosDB formatter has been added. Thanks to
+         Aurélien Rougemont. #1809
+       * Write HTTP plugin: Notifications are now handled by this plugin.
+         Thanks to Florian Forster.
+       * Write HTTP plugin: The "LogHttpError" option has been added. Thanks to
+         vzubko.
+       * Write HTTP plugin: The new "Headers" option allows setting custom HTTP
+         headers in outgoing requests. Thanks to Brandon Arp. #1634
+       * Write Kafka plugin: Key handling has been made more comprehensive and
+         reliable. Thanks to Florian Forster, Pierre-Yves Ritschard and Vincent
+         Bernat. #1765, #1695, #1393
+       * Write Redis plugin: The "Database", "MaxSetSize", "Prefix" and
+         "StoreRates" options have been added. Thanks to Brian Kelly and
+         Sebastian Pfahl.
+       * Write Riemann plugin: The new "BatchFlushTimeout" and "Timeout" option
+         have been added. Thanks to Pierre-Yves Ritschard and Gergely Nagy.
+       * Write Riemann plugin: This plugin now requires the riemann-c-client
+         library, version 1.6.0+. This adds support for submitting values to
+         Riemann over TLS. Thanks to Gergely Nagy. #986
+       * Write TSDB, Write Sensu, Write Riemann, Write Graphite, Write TSDB
+         plugin: TCP keepalive is now enabled, helping graceful recovery from
+         unclean network disconnections. Thanks to Marc Fournier. #1549
+       * XenCPU plugin: This new plugin collects XEN Hypervisor CPU stats.
+         Thanks to Pavel Rochnyack. #1608
+       * ZFS ARC plugin: Several new statistics have been added and a couple of
+         obsolete ones removed. Thanks to Brad Davis, Brian ONeill and Ruben
+         Kerkhof.
+       * Zone plugin: This new plugin reads per-zone CPU usage on Solaris.
+         Thanks to Mathijs Mohlmann and Dagobert Michelsen.
+
 2016-07-25, Version 5.5.2
        * collectd: A division by zero has been fixed in the
          "plugin_dispatch_multivalue()" function. Thanks to Corey Kosak.
index c1adf44..7e89e45 100644 (file)
@@ -172,7 +172,6 @@ sub plugin_call_all {
        my $type = shift;
 
        my %plugins;
-       my $interval;
 
        our $cb_name = undef;
 
@@ -181,13 +180,13 @@ sub plugin_call_all {
        }
 
        if (TYPE_LOG != $type) {
-               DEBUG ("Collectd::plugin_call: type = \"$type\" ("
+               DEBUG ("Collectd::plugin_call_all: type = \"$type\" ("
                        . $types{$type} . "), args=\""
                        . join(', ', map { defined($_) ? $_ : '<undef>' } @_) . "\"");
        }
 
        if (! defined $plugins[$type]) {
-               ERROR ("Collectd::plugin_call: unknown type \"$type\"");
+               ERROR ("Collectd::plugin_call_all: unknown type \"$type\"");
                return;
        }
 
@@ -196,21 +195,9 @@ sub plugin_call_all {
                %plugins = %{$plugins[$type]};
        }
 
-       $interval = plugin_get_interval ();
-
        foreach my $plugin (keys %plugins) {
-               my $p = $plugins{$plugin};
-
-               my $status = 0;
-
-               if ($p->{'wait_left'} > 0) {
-                       $p->{'wait_left'} -= $interval;
-               }
-
-               next if ($p->{'wait_left'} > 0);
-
-               $cb_name = $p->{'cb_name'};
-               $status = call_by_name (@_);
+               $cb_name = $plugins{$plugin};
+               my $status = call_by_name (@_);
 
                if (! $status) {
                        my $err = undef;
@@ -230,23 +217,7 @@ sub plugin_call_all {
                }
 
                if ($status) {
-                       $p->{'wait_left'} = 0;
-                       $p->{'wait_time'} = $interval;
-               }
-               elsif (TYPE_READ == $type) {
-                       if ($p->{'wait_time'} < $interval) {
-                               $p->{'wait_time'} = $interval;
-                       }
-
-                       $p->{'wait_left'} = $p->{'wait_time'};
-                       $p->{'wait_time'} *= 2;
-
-                       if ($p->{'wait_time'} > 86400) {
-                               $p->{'wait_time'} = 86400;
-                       }
-
-                       WARNING ("${plugin}->read() failed with status $status. "
-                               . "Will suspend it for $p->{'wait_left'} seconds.");
+                       #NOOP
                }
                elsif (TYPE_INIT == $type) {
                        ERROR ("${plugin}->init() failed with status $status. "
@@ -309,21 +280,29 @@ sub plugin_register {
        }
        elsif ((TYPE_DATASET != $type) && (! ref $data)) {
                my $pkg = scalar caller;
-
-               my %p : shared;
-
                if ($data !~ m/^$pkg\:\:/) {
                        $data = $pkg . "::" . $data;
                }
-
-               %p = (
-                       wait_time => plugin_get_interval (),
-                       wait_left => 0,
-                       cb_name   => $data,
-               );
-
+               if (TYPE_READ == $type) {
+                       return plugin_register_read($name, $data);
+               }
+               if (TYPE_WRITE == $type) {
+                       return plugin_register_write($name, $data);
+               }
+               if (TYPE_LOG == $type) {
+                       return plugin_register_log($name, $data);
+               }
+               if (TYPE_NOTIF == $type) {
+                       return plugin_register_notification($name, $data);
+               }
+               if (TYPE_FLUSH == $type) {
+                       #For collectd-5.6 only
+                       lock %{$plugins[$type]};
+                       $plugins[$type]->{$name} = $data;
+                       return plugin_register_flush($name, $data);
+               }
                lock %{$plugins[$type]};
-               $plugins[$type]->{$name} = \%p;
+               $plugins[$type]->{$name} = $data;
        }
        else {
                ERROR ("Collectd::plugin_register: Invalid data.");
@@ -351,6 +330,21 @@ sub plugin_unregister {
                lock %cf_callbacks;
                delete $cf_callbacks{$name};
        }
+       elsif (TYPE_READ == $type) {
+               return plugin_unregister_read ($name);
+       }
+       elsif (TYPE_WRITE == $type) {
+               return plugin_unregister_write($name);
+       }
+       elsif (TYPE_LOG == $type) {
+               return plugin_unregister_log ($name);
+       }
+       elsif (TYPE_NOTIF == $type) {
+               return plugin_unregister_notification($name);
+       }
+       elsif (TYPE_FLUSH == $type) {
+               return plugin_unregister_flush($name);
+       }
        elsif (defined $plugins[$type]) {
                lock %{$plugins[$type]};
                delete $plugins[$type]->{$name};
index e1b89f6..71fb5f8 100644 (file)
@@ -85,36 +85,50 @@ static int my_init (void)
 } /* static int my_init (void) */
 
 /*
- * This function is called in regular intervalls to collect the data.
+ * This is a utility function used by the read callback to populate a
+ * value_list_t and pass it to plugin_dispatch_values.
  */
-static int my_read (void)
+static int my_submit (gauge_t value)
 {
-       value_t values[1]; /* the size of this list should equal the number of
-                                                 data sources */
        value_list_t vl = VALUE_LIST_INIT;
 
-       /* do the magic to read the data */
-       values[0].gauge = random ();
-
-       vl.values     = values;
+       /* Convert the gauge_t to a value_t and add it to the value_list_t. */
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
-       vl.time       = time (NULL);
+
+       /* Only set vl.time yourself if you update multiple metrics (i.e. you
+        * have multiple calls to plugin_dispatch_values()) and they need to all
+        * have the same timestamp. */
+       /* vl.time = cdtime(); */
+
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "myplugin", sizeof (vl.plugin));
 
        /* it is strongly recommended to use a type defined in the types.db file
         * instead of a custom type */
-       sstrncpy (vl.type, "myplugin", sizeof (vl.plugin));
+       sstrncpy (vl.type, "myplugin", sizeof (vl.type));
        /* optionally set vl.plugin_instance and vl.type_instance to reasonable
         * values (default: "") */
 
        /* dispatch the values to collectd which passes them on to all registered
         * write functions */
-       plugin_dispatch_values (&vl);
+       return plugin_dispatch_values (&vl);
+}
+
+/*
+ * This function is called in regular intervalls to collect the data.
+ */
+static int my_read (void)
+{
+       /* do the magic to read the data */
+       gauge_t value = random ();
+
+       if (my_submit (value) != 0)
+               WARNING ("myplugin plugin: Dispatching a random value failed.");
 
        /* A return value != 0 indicates an error and the plugin will be skipped
         * for an increasing amount of time. */
-    return 0;
+       return 0;
 } /* static int my_read (void) */
 
 /*
index c2a9555..8e5a7ed 100755 (executable)
@@ -104,8 +104,6 @@ our %TypesCounterToDerive = # {{{
   protocol_counter => ["value"],
   ps_cputime => ["user", "syst"],
   ps_pagefaults => ["minflt", "majflt"],
-  ps_code => ["value"],
-  ps_data => ["value"],
   serial_octets => ["rx", "tx"],
   swap_io => ["value"],
   virt_cpu_total => ["ns"],
index b76e43c..3477dc2 100644 (file)
@@ -1285,6 +1285,7 @@ pkglib_LTLIBRARIES += write_log.la
 write_log_la_SOURCES = write_log.c \
                         utils_format_graphite.c utils_format_graphite.h
 write_log_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+write_log_la_LIBADD = libformat_json.la
 endif
 
 if BUILD_PLUGIN_WRITE_MONGODB
index 89f051e..06fd1f1 100644 (file)
@@ -1070,11 +1070,13 @@ static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */
     if (publish)
     {
         char cbname[128];
-        user_data_t ud = { conf, camqp_config_free };
-
         ssnprintf (cbname, sizeof (cbname), "amqp/%s", conf->name);
 
-        status = plugin_register_write (cbname, camqp_write, &ud);
+        status = plugin_register_write (cbname, camqp_write,
+                &(user_data_t) {
+                    .data = conf,
+                    .free_func = camqp_config_free,
+                });
         if (status != 0)
         {
             camqp_config_free (conf);
index e10a15d..578b8de 100644 (file)
@@ -239,23 +239,22 @@ static int config_add (oconfig_item_t *ci)
 
        if (status == 0)
        {
-               user_data_t ud = {
-                       .data = st,
-                       .free_func = apache_free
-               };
-
                char callback_name[3*DATA_MAX_NAME_LEN];
 
                ssnprintf (callback_name, sizeof (callback_name),
                                "apache/%s/%s",
                                (st->host != NULL) ? st->host : hostname_g,
-                               (st->name != NULL) ? st->name : "default"),
+                               (st->name != NULL) ? st->name : "default");
 
                status = plugin_register_complex_read (/* group = */ NULL,
                                /* name      = */ callback_name,
                                /* callback  = */ apache_read_host,
                                /* interval  = */ 0,
-                               /* user_data = */ &ud);
+                               &(user_data_t) {
+                                       .data = st,
+                                       .free_func = apache_free,
+                               });
+
        }
 
        if (status != 0)
@@ -412,19 +411,15 @@ static void submit_value (const char *type, const char *type_instance,
 } /* void submit_value */
 
 static void submit_derive (const char *type, const char *type_instance,
-               derive_t c, apache_t *st)
+               derive_t d, apache_t *st)
 {
-       value_t v;
-       v.derive = c;
-       submit_value (type, type_instance, v, st);
+       submit_value (type, type_instance, (value_t) { .derive = d }, st);
 } /* void submit_derive */
 
 static void submit_gauge (const char *type, const char *type_instance,
                gauge_t g, apache_t *st)
 {
-       value_t v;
-       v.gauge = g;
-       submit_value (type, type_instance, v, st);
+       submit_value (type, type_instance, (value_t) { .gauge = g }, st);
 } /* void submit_gauge */
 
 static void submit_scoreboard (char *buf, apache_t *st)
index af5f24c..821bd65 100644 (file)
@@ -416,12 +416,9 @@ static int apcups_config (oconfig_item_t *ci)
 
 static void apc_submit_generic (const char *type, const char *type_inst, double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "apcups", sizeof (vl.plugin));
index 48fbcb9..06ca7a8 100644 (file)
@@ -83,15 +83,9 @@ static int as_init (void)
 static void as_submit (const char *type, const char *type_instance,
                double val)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       DEBUG ("type = %s; type_instance = %s; val = %f;",
-                       type, type_instance, val);
-
-       values[0].gauge = val;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = val };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "apple_sensors", sizeof (vl.plugin));
index 81a4efd..08271f8 100644 (file)
@@ -60,16 +60,13 @@ static void aquaero_submit (const char *type, const char *type_instance,
                double value)
 {
        const char *instance = conf_device?conf_device:"default";
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
        /* Don't report undefined values. */
        if (value == AQ5_FLOAT_UNDEF)
                return;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
 
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
index 11bb97f..16568e6 100644 (file)
@@ -126,12 +126,9 @@ static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 static int ascent_submit_gauge (const char *plugin_instance, /* {{{ */
     const char *type, const char *type_instance, gauge_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "ascent", sizeof (vl.plugin));
index 3e6d7bd..ebf41de 100644 (file)
@@ -78,12 +78,9 @@ static _Bool query_statefs = 0;
 static void battery_submit2 (char const *plugin_instance, /* {{{ */
                char const *type, char const *type_instance, gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "battery", sizeof (vl.plugin));
@@ -392,47 +389,17 @@ static int sysfs_file_to_buffer(char const *dir, /* {{{ */
                char const *basename,
                char *buffer, size_t buffer_size)
 {
-       int status;
-       FILE *fp;
        char filename[PATH_MAX];
+       int status;
 
        ssnprintf (filename, sizeof (filename), "%s/%s/%s",
                        dir, power_supply, basename);
 
-       /* No file isn't the end of the world -- not every system will be
-        * reporting the same set of statistics */
-       if (access (filename, R_OK) != 0)
-               return ENOENT;
-
-       fp = fopen (filename, "r");
-       if (fp == NULL)
-       {
-               status = errno;
-               if (status != ENOENT)
-               {
-                       char errbuf[1024];
-                       WARNING ("battery plugin: fopen (%s) failed: %s", filename,
-                                       sstrerror (status, errbuf, sizeof (errbuf)));
-               }
+       status = (int) read_file_contents (filename, buffer, buffer_size);
+       if (status < 0)
                return status;
-       }
-
-       if (fgets (buffer, buffer_size, fp) == NULL)
-       {
-               status = errno;
-               if (status != ENODEV)
-               {
-                       char errbuf[1024];
-                       WARNING ("battery plugin: fgets (%s) failed: %s", filename,
-                                       sstrerror (status, errbuf, sizeof (errbuf)));
-               }
-               fclose (fp);
-               return status;
-       }
 
        strstripnewline (buffer);
-
-       fclose (fp);
        return 0;
 } /* }}} int sysfs_file_to_buffer */
 
index 53730ed..03729fd 100644 (file)
@@ -51,18 +51,12 @@ SOFTWARE.
 #include <stdio.h>
 
 #define STATEFS_ROOT "/run/state/namespaces/Battery/"
-#define BUFFER_SIZE 512
-
-static int submitted_this_run = 0;
 
 static void battery_submit(const char *type, gauge_t value,
                            const char *type_instance) {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
   sstrncpy(vl.host, hostname_g, sizeof(vl.host));
   sstrncpy(vl.plugin, "battery", sizeof(vl.plugin));
@@ -72,67 +66,52 @@ static void battery_submit(const char *type, gauge_t value,
   if (type_instance != NULL)
     sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
   plugin_dispatch_values(&vl);
-
-  submitted_this_run++;
-}
-
-static _Bool getvalue(const char *fname, gauge_t *value) {
-  FILE *fh;
-  char buffer[BUFFER_SIZE];
-
-  if ((fh = fopen(fname, "r")) == NULL) {
-    WARNING("battery plugin: cannot open StateFS file %s", fname);
-    return (0);
-  }
-
-  if (fgets(buffer, STATIC_ARRAY_SIZE(buffer), fh) == NULL) {
-    fclose(fh);
-    return (0); // empty file
-  }
-
-  (*value) = atof(buffer);
-
-  fclose(fh);
-
-  return (1);
 }
 
 /* cannot be static, is referred to from battery.c */
 int battery_read_statefs(void) {
-  gauge_t value = NAN;
-
-  submitted_this_run = 0;
-
-  if (getvalue(STATEFS_ROOT "ChargePercentage", &value))
-    battery_submit("charge", value, NULL);
-  // Use capacity as a charge estimate if ChargePercentage is not available
-  else if (getvalue(STATEFS_ROOT "Capacity", &value))
-    battery_submit("charge", value, NULL);
-
-  if (getvalue(STATEFS_ROOT "Current", &value))
-    battery_submit("current", value * 1e-6, NULL); // from uA to A
-
-  if (getvalue(STATEFS_ROOT "Energy", &value))
-    battery_submit("energy_wh", value * 1e-6, NULL); // from uWh to Wh
-
-  if (getvalue(STATEFS_ROOT "Power", &value))
-    battery_submit("power", value * 1e-6, NULL); // from uW to W
-
-  if (getvalue(STATEFS_ROOT "Temperature", &value))
-    battery_submit("temperature", value * 0.1, NULL); // from 10xC to C
-
-  if (getvalue(STATEFS_ROOT "TimeUntilFull", &value))
-    battery_submit("duration", value, "full");
-
-  if (getvalue(STATEFS_ROOT "TimeUntilLow", &value))
-    battery_submit("duration", value, "low");
+  value_t v;
+  int success = 0;
+
+  if (parse_value_file(STATEFS_ROOT "ChargePercentage", &v, DS_TYPE_GAUGE) == 0) {
+    battery_submit("charge", v.gauge, NULL);
+    success++;
+  } else if (parse_value_file(STATEFS_ROOT "Capacity", &v, DS_TYPE_GAUGE) == 0) {
+    // Use capacity as a charge estimate if ChargePercentage is not available
+    battery_submit("charge", v.gauge, NULL);
+    success++;
+  } else {
+    WARNING("battery plugin: Neither \""STATEFS_ROOT"ChargePercentage\" "
+            "nor \""STATEFS_ROOT"Capacity\" could be read.");
+  }
 
-  if (getvalue(STATEFS_ROOT "Voltage", &value))
-    battery_submit("voltage", value * 1e-6, NULL); // from uV to V
+  struct {
+    char *path;
+    char *type;
+    char *type_instance;
+    gauge_t factor;
+  } metrics[] = {
+    {STATEFS_ROOT "Current",       "current",     NULL,  1e-6}, // from uA to A
+    {STATEFS_ROOT "Energy",        "energy_wh",   NULL,  1e-6}, // from uWh to Wh
+    {STATEFS_ROOT "Power",         "power",       NULL,  1e-6}, // from uW to W
+    {STATEFS_ROOT "Temperature",   "temperature", NULL,   0.1}, // from 10xC to C
+    {STATEFS_ROOT "TimeUntilFull", "duration",    "full", 1.0},
+    {STATEFS_ROOT "TimeUntilLow",  "duration",    "low",  1.0},
+    {STATEFS_ROOT "Voltage",       "voltage",     NULL,  1e-6}, // from uV to V
+  };
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(metrics); i++) {
+    if (parse_value_file(metrics[i].path, &v, DS_TYPE_GAUGE) != 0) {
+      WARNING("battery plugin: Reading \"%s\" failed.", metrics[i].path);
+      continue;
+    }
+
+    battery_submit(metrics[i].type, v.gauge * metrics[i].factor, metrics[i].type_instance);
+    success++;
+  }
 
-  if (submitted_this_run == 0) {
-    ERROR("battery plugin: statefs backend: none of the statistics are "
-          "available");
+  if (success == 0) {
+    ERROR("battery plugin: statefs backend: none of the statistics are available");
     return (-1);
   }
 
index 9b6b32e..09de4a3 100644 (file)
@@ -247,12 +247,9 @@ static int memsummary_translation_table_length =
 static void submit (time_t ts, const char *plugin_instance, /* {{{ */
     const char *type, const char *type_instance, value_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0] = value;
-
-  vl.values = values;
+  vl.values = &value;
   vl.values_len = 1;
   if (config_parse_time)
     vl.time = TIME_T_TO_CDTIME_T (ts);
index f6294e4..353ede7 100644 (file)
@@ -677,12 +677,9 @@ ntohf(tFloat p_float)
 static void
 chrony_push_data(const char *p_type, const char *p_type_inst, double p_value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = p_value;    /* TODO: Check type??? (counter, gauge, derive, absolute) */
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = p_value };
   vl.values_len = 1;
 
   /* XXX: Shall g_chrony_host/g_chrony_port be reflected in the plugin's output? */
index 0102e92..9af3c0c 100644 (file)
@@ -75,6 +75,20 @@ Adds I<Dir> to the B<@INC> array. This is the same as using the B<-IDir>
 command line option or B<use lib Dir> in the source code. Please note that it
 only has effect on plugins loaded after this option.
 
+=item B<RegisterLegacyFlush> I<true|false>
+
+The C<Perl plugin> used to register one flush callback (called B<"perl">) and
+call all Perl-based flush handlers when this callback was called. Newer versions
+of the plugin wrap the Perl flush handlers and register them directly with the
+daemon I<in addition> to the legacy B<"perl"> callback. This allows to call
+specific Perl flush handlers, but has the downside that flushing I<all> plugins
+now calls the Perl flush handlers twice (once directly and once via the legacy
+callback). Unfortunately, removing the B<"perl"> callback would break backwards
+compatibility.
+
+This option allows you to disable the legacy B<"perl"> flush callback if you care
+about the double call and don't call the B<"perl"> callback in your setup.
+
 =back
 
 =head1 WRITING YOUR OWN PLUGINS
@@ -759,18 +773,6 @@ dispatched by the perl plugin after upgrades.
 
 =back
 
-=head1 KNOWN BUGS
-
-=over 4
-
-=item *
-
-Currently, it is not possible to flush a single Perl plugin only. You can
-either flush all Perl plugins or none at all and you have to use C<perl> as
-plugin name when doing so.
-
-=back
-
 =head1 SEE ALSO
 
 L<collectd(1)>,
index 0fc13dc..345af3d 100644 (file)
 #</Plugin>
 
 #<Plugin hugepages>
-#    ReportPerNodeHP "true"
-#    ReportRootHP "true"
+#    ReportPerNodeHP  true
+#    ReportRootHP     true
+#    ValuesPages      true
+#    ValuesBytes      false
+#    ValuesPercentage false
 #</Plugin>
 
 #<Plugin interface>
 #    StoreRates true
 #    AlwaysAppendDS false
 #    EscapeCharacter "_"
+#    SeparateInstances false
+#    DropDuplicateFields false
 #  </Node>
 #</Plugin>
 
index 20d8c6b..9d4b791 100644 (file)
@@ -241,6 +241,12 @@ Path to the plugins (shared objects) of collectd.
 Set one or more files that contain the data-set descriptions. See
 L<types.db(5)> for a description of the format of this file.
 
+If this option is not specified, a default file is read. If you need to define
+custom types in addition to the types defined in the default file, you need to
+explicitly load both. In other words, if the B<TypesDB> option is encountered
+the default behavior is disabled and if you need the default types you have to
+also explicitly load them.
+
 =item B<Interval> I<Seconds>
 
 Configures the interval in which to query the read plugins. Obviously smaller
@@ -2830,20 +2836,35 @@ options (default is enabled).
 
 =over 4
 
-=item B<ReportPerNodeHP> I<true>|I<false>
+=item B<ReportPerNodeHP> B<true>|B<false>
 
 If enabled, information will be collected from the hugepage
 counters in "/sys/devices/system/node/*/hugepages".
 This is used to check the per-node hugepage statistics on
 a NUMA system.
 
-=item B<ReportRootHP> I<true>|I<false>
+=item B<ReportRootHP> B<true>|B<false>
 
 If enabled, information will be collected from the hugepage
 counters in "/sys/kernel/mm/hugepages".
 This can be used on both NUMA and non-NUMA systems to check
 the overall hugepage statistics.
 
+=item B<ValuesPages> B<true>|B<false>
+
+Whether to report hugepages metrics in number of pages.
+Defaults to B<true>.
+
+=item B<ValuesBytes> B<false>|B<true>
+
+Whether to report hugepages metrics in bytes.
+Defaults to B<false>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Whether to report hugepages metrics as percentage.
+Defaults to B<false>.
+
 =back
 
 =head2 Plugin C<interface>
@@ -7818,6 +7839,32 @@ If set to B<true>, append the name of the I<Data Source> (DS) to the "metric"
 identifier. If set to B<false> (the default), this is only done when there is
 more than one DS.
 
+=item B<DropDuplicateFields> B<false>|B<true>
+
+If set to B<true>, detect and remove duplicate components in Graphite metric
+names. For example, the metric name  C<host.load.load.shortterm> will
+be shortened to C<host.load.shortterm>.
+
+=back
+
+=head2 Plugin C<write_log>
+
+The C<write_log> plugin writes metrics as INFO log messages.
+
+This plugin supports two output formats: I<Graphite> and I<JSON>.
+
+Synopsis:
+
+ <Plugin write_log>
+   Format Graphite
+ </Plugin>
+
+=over 4
+
+=item B<Format> I<Format>
+
+The output format to use. Can be one of C<Graphite> or C<JSON>.
+
 =back
 
 =head2 Plugin C<write_tsdb>
@@ -9093,6 +9140,8 @@ Available options:
 
 =item B<TypeInstance> I<Regex>
 
+=item B<MetaData> I<String> I<Regex>
+
 Match values where the given regular expressions match the various fields of
 the identifier of a value. If multiple regular expressions are given, B<all>
 regexen must match for a value to match.
@@ -9381,6 +9430,10 @@ Available options:
 
 =item B<TypeInstance> I<Regex> I<Replacement>
 
+=item B<MetaData> I<String> I<Regex> I<Replacement>
+
+=item B<DeleteMetaData> I<String> I<Regex>
+
 Match the appropriate field with the given regular expression I<Regex>. If the
 regular expression matches, that part that matches is replaced with
 I<Replacement>. If multiple places of the input buffer match a given regular
@@ -9419,9 +9472,37 @@ Available options:
 
 =item B<MetaData> I<String> I<String>
 
-Set the appropriate field to the given string. The strings for plugin instance
-and type instance may be empty, the strings for host and plugin may not be
-empty. It's currently not possible to set the type of a value this way.
+Set the appropriate field to the given string. The strings for plugin instance,
+type instance, and meta data may be empty, the strings for host and plugin may
+not be empty. It's currently not possible to set the type of a value this way.
+
+The following placeholders will be replaced by an appropriate value:
+
+=over 4
+
+=item B<%{host}>
+
+=item B<%{plugin}>
+
+=item B<%{plugin_instance}>
+
+=item B<%{type}>
+
+=item B<%{type_instance}>
+
+These placeholders are replaced by the identifier field of the same name.
+
+=item B<%{meta:>I<name>B<}>
+
+These placeholders are replaced by the meta data value with the given name.
+
+=back
+
+Please note that these placeholders are B<case sensitive>!
+
+=item B<DeleteMetaData> I<String>
+
+Delete the named meta data field.
 
 =back
 
index ce90ede..4a72b2f 100644 (file)
@@ -74,61 +74,26 @@ static void conntrack_submit (const char *type, const char *type_instance,
 static int conntrack_read (void)
 {
        value_t conntrack, conntrack_max, conntrack_pct;
-       FILE *fh;
-       char buffer[64] = { 0 };
-       size_t buffer_len;
 
-       fh = fopen (old_files?CONNTRACK_FILE_OLD:CONNTRACK_FILE, "r");
-       if (fh == NULL)
-               return (-1);
-
-       if (fgets (buffer, sizeof (buffer), fh) == NULL)
+       char const *path = old_files ? CONNTRACK_FILE_OLD : CONNTRACK_FILE;
+       if (parse_value_file (path, &conntrack, DS_TYPE_GAUGE) != 0)
        {
-               fclose (fh);
+               ERROR ("conntrack plugin: Reading \"%s\" failed.", path);
                return (-1);
        }
-       fclose (fh);
 
-       /* strip trailing newline. */
-       buffer_len = strlen (buffer);
-       while ((buffer_len > 0) && isspace ((int) buffer[buffer_len - 1]))
+       path = old_files ? CONNTRACK_MAX_FILE_OLD : CONNTRACK_MAX_FILE;
+       if (parse_value_file (path, &conntrack_max, DS_TYPE_GAUGE) != 0)
        {
-               buffer[buffer_len - 1] = 0;
-               buffer_len--;
-       }
-
-       if (parse_value (buffer, &conntrack, DS_TYPE_GAUGE) != 0)
-               return (-1);
-
-       conntrack_submit ("conntrack", NULL, conntrack);
-
-       fh = fopen (old_files?CONNTRACK_MAX_FILE_OLD:CONNTRACK_MAX_FILE, "r");
-       if (fh == NULL)
-               return (-1);
-
-       memset (buffer, 0, sizeof (buffer));
-       if (fgets (buffer, sizeof (buffer), fh) == NULL)
-       {
-               fclose (fh);
+               ERROR ("conntrack plugin: Reading \"%s\" failed.", path);
                return (-1);
        }
-       fclose (fh);
-
-       /* strip trailing newline. */
-       buffer_len = strlen (buffer);
-       while ((buffer_len > 0) && isspace ((int) buffer[buffer_len - 1]))
-       {
-               buffer[buffer_len - 1] = 0;
-               buffer_len--;
-       }
-
-       if (parse_value (buffer, &conntrack_max, DS_TYPE_GAUGE) != 0)
-               return (-1);
 
-       conntrack_submit ("conntrack", "max", conntrack_max);
        conntrack_pct.gauge = (conntrack.gauge / conntrack_max.gauge) * 100;
-       conntrack_submit ("percent", "used", conntrack_pct);
 
+       conntrack_submit ("conntrack", NULL,   conntrack);
+       conntrack_submit ("conntrack", "max",  conntrack_max);
+       conntrack_submit ("percent",   "used", conntrack_pct);
 
        return (0);
 } /* static int conntrack_read */
index 76e2a6c..3bd6d9f 100644 (file)
 
 static void cs_submit (derive_t context_switches)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = (derive_t) context_switches;
-
-       vl.values = values;
+       vl.values = &(value_t) { .derive = context_switches };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "contextswitch", sizeof (vl.plugin));
index 1ac5b4a..fbd0714 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -325,12 +325,9 @@ static int init (void)
 
 static void submit_value (int cpu_num, int cpu_state, const char *type, value_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       memcpy(&values[0], &value, sizeof(value));
-
-       vl.values = values;
+       vl.values = &value;
        vl.values_len = 1;
 
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -346,26 +343,22 @@ static void submit_value (int cpu_num, int cpu_state, const char *type, value_t
        plugin_dispatch_values (&vl);
 }
 
-static void submit_percent(int cpu_num, int cpu_state, gauge_t percent)
+static void submit_percent (int cpu_num, int cpu_state, gauge_t value)
 {
-       value_t value;
-
        /* This function is called for all known CPU states, but each read
         * method will only report a subset. The remaining states are left as
         * NAN and we ignore them here. */
-       if (isnan (percent))
+       if (isnan (value))
                return;
 
-       value.gauge = percent;
-       submit_value (cpu_num, cpu_state, "percent", value);
+       submit_value (cpu_num, cpu_state, "percent",
+                       (value_t) { .gauge = value });
 }
 
-static void submit_derive(int cpu_num, int cpu_state, derive_t derive)
+static void submit_derive (int cpu_num, int cpu_state, derive_t value)
 {
-       value_t value;
-
-       value.derive = derive;
-       submit_value (cpu_num, cpu_state, "cpu", value);
+       submit_value (cpu_num, cpu_state, "cpu",
+                       (value_t) { .derive = value });
 }
 
 /* Takes the zero-index number of a CPU and makes sure that the module-global
@@ -464,14 +457,11 @@ static void cpu_commit_one (int cpu_num, /* {{{ */
 } /* }}} void cpu_commit_one */
 
 /* Commits the number of cores */
-static void cpu_commit_num_cpu (gauge_t num_cpu) /* {{{ */
+static void cpu_commit_num_cpu (gauge_t value) /* {{{ */
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = num_cpu;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
 
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -555,7 +545,7 @@ static int cpu_stage (size_t cpu_num, size_t state, derive_t d, cdtime_t now) /*
        int status;
        cpu_state_t *s;
        gauge_t rate = NAN;
-       value_t val = {.derive = d};
+       value_t val = { .derive = d };
 
        if (state >= COLLECTD_CPU_STATE_ACTIVE)
                return (EINVAL);
index 1e9e857..a2cc3ad 100644 (file)
@@ -25,8 +25,6 @@
 #include "common.h"
 #include "plugin.h"
 
-#define MODULE_NAME "cpufreq"
-
 static int num_cpu = 0;
 
 static int cpufreq_init (void)
@@ -59,72 +57,39 @@ static int cpufreq_init (void)
        return (0);
 } /* int cpufreq_init */
 
-static void cpufreq_submit (int cpu_num, double value)
+static void cpufreq_submit (int cpu_num, value_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &value;
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "cpufreq", sizeof (vl.plugin));
        sstrncpy (vl.type, "cpufreq", sizeof (vl.type));
-       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
-                       "%i", cpu_num);
+       ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%i", cpu_num);
 
        plugin_dispatch_values (&vl);
 }
 
 static int cpufreq_read (void)
 {
-        int status;
-       unsigned long long val;
-       FILE *fp;
-       char filename[256];
-       char buffer[16];
-
        for (int i = 0; i < num_cpu; i++)
        {
-               status = ssnprintf (filename, sizeof (filename),
-                               "/sys/devices/system/cpu/cpu%d/cpufreq/"
-                               "scaling_cur_freq", i);
-               if ((status < 1) || ((unsigned int)status >= sizeof (filename)))
-                       return (-1);
+               char filename[PATH_MAX];
+               ssnprintf (filename, sizeof (filename),
+                               "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
 
-               if ((fp = fopen (filename, "r")) == NULL)
+               value_t v;
+               if (parse_value_file (filename, &v, DS_TYPE_GAUGE) != 0)
                {
-                       char errbuf[1024];
-                       WARNING ("cpufreq: fopen (%s): %s", filename,
-                                       sstrerror (errno, errbuf,
-                                               sizeof (errbuf)));
-                       return (-1);
+                       WARNING ("cpufreq plugin: Reading \"%s\" failed.", filename);
+                       continue;
                }
 
-               if (fgets (buffer, 16, fp) == NULL)
-               {
-                       char errbuf[1024];
-                       WARNING ("cpufreq: fgets: %s",
-                                       sstrerror (errno, errbuf,
-                                               sizeof (errbuf)));
-                       fclose (fp);
-                       return (-1);
-               }
-
-               if (fclose (fp))
-               {
-                       char errbuf[1024];
-                       WARNING ("cpufreq: fclose: %s",
-                                       sstrerror (errno, errbuf,
-                                               sizeof (errbuf)));
-               }
-
-
-               /* You're seeing correctly: The file is reporting kHz values.. */
-               val = atoll (buffer) * 1000;
+               /* convert kHz to Hz */
+               v.gauge *= 1000.0;
 
-               cpufreq_submit (i, val);
+               cpufreq_submit (i, v);
        }
 
        return (0);
index 326c29c..5de0e47 100644 (file)
 #include <time.h>
 
 static void cpusleep_submit(derive_t cpu_sleep) {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].derive = cpu_sleep;
-
-  vl.values = values;
+  vl.values = &(value_t) { .derive = cpu_sleep };
   vl.values_len = 1;
   sstrncpy(vl.host, hostname_g, sizeof(vl.host));
   sstrncpy(vl.plugin, "cpusleep", sizeof(vl.plugin));
index 74ef13c..8401e6c 100644 (file)
@@ -608,14 +608,11 @@ static int cc_init (void) /* {{{ */
 } /* }}} int cc_init */
 
 static void cc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */
-    const cu_match_value_t *mv)
+    value_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0] = mv->value;
-
-  vl.values = values;
+  vl.values = &value;
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
@@ -629,12 +626,9 @@ static void cc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */
 
 static void cc_submit_response_code (const web_page_t *wp, long code) /* {{{ */
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = code;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = (gauge_t) code };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
@@ -647,12 +641,9 @@ static void cc_submit_response_code (const web_page_t *wp, long code) /* {{{ */
 static void cc_submit_response_time (const web_page_t *wp, /* {{{ */
     cdtime_t response_time)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = CDTIME_T_TO_DOUBLE (response_time);
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = CDTIME_T_TO_DOUBLE (response_time) };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
@@ -714,7 +705,7 @@ static int cc_read_page (web_page_t *wp) /* {{{ */
       continue;
     }
 
-    cc_submit (wp, wm, mv);
+    cc_submit (wp, wm, mv->value);
     match_value_reset (mv);
   } /* for (wm = wp->matches; wm != NULL; wm = wm->next) */
 
index ab0237e..4dab1ab 100644 (file)
@@ -144,6 +144,9 @@ static int cj_get_type (cj_key_t *key)
 {
   const data_set_t *ds;
 
+  if ((key == NULL) || !CJ_IS_KEY (key))
+    return -EINVAL;
+
   ds = plugin_get_ds (key->type);
   if (ds == NULL)
   {
@@ -227,12 +230,15 @@ static int cj_cb_number (void *ctx,
   buffer[sizeof (buffer) - 1] = 0;
 
   if ((key == NULL) || !CJ_IS_KEY (key)) {
-    if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/)
+    if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/) {
       NOTICE ("curl_json plugin: Found \"%s\", but the configuration expects"
               " a map.", buffer);
+      return (CJ_CB_CONTINUE);
+    }
+
     cj_cb_inc_array_index (ctx, /* update_key = */ 1);
     key = db->state[db->depth].key;
-    if (key == NULL) {
+    if ((key == NULL) || !CJ_IS_KEY (key)) {
       return (CJ_CB_CONTINUE);
     }
   }
@@ -769,14 +775,12 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
     cb_name = ssnprintf_alloc ("curl_json-%s-%s",
                db->instance, db->url ? db->url : db->sock);
 
-    user_data_t ud = {
-      .data = db,
-      .free_func = cj_free
-    };
-
     plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
                                   /* interval = */ db->interval,
-                                  &ud);
+                                  &(user_data_t) {
+                                    .data = db,
+                                    .free_func = cj_free,
+                                  });
     sfree (cb_name);
   }
   else
index c8a1313..924665c 100644 (file)
@@ -1026,13 +1026,12 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
 
     cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url);
 
-    user_data_t ud = {
-      .data = db,
-      .free_func = cx_free
-    };
-
     plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read,
-                                  /* interval = */ 0, &ud);
+        /* interval = */ 0,
+        &(user_data_t) {
+          .data = db,
+          .free_func = cx_free,
+        });
     sfree (cb_name);
   }
   else
index 05b1199..e2c872c 100644 (file)
@@ -334,50 +334,60 @@ int strsplit (char *string, char **fields, size_t size)
        return ((int) i);
 }
 
-int strjoin (char *buffer, size_t buffer_size,
-               char **fields, size_t fields_num,
-               const char *sep)
-{
-       size_t avail;
-       char *ptr;
-       size_t sep_len;
+int strjoin(char *buffer, size_t buffer_size, char **fields, size_t fields_num,
+            const char *sep) {
+  size_t avail = 0;
+  char *ptr = buffer;
+  size_t sep_len = 0;
 
-       if ((buffer_size < 1) || (fields_num == 0))
-               return (-1);
+  size_t buffer_req = 0;
 
-       memset (buffer, 0, buffer_size);
-       ptr = buffer;
-       avail = buffer_size - 1;
+  if (((fields_num != 0) && (fields == NULL)) ||
+      ((buffer_size != 0) && (buffer == NULL)))
+    return (-EINVAL);
 
-       sep_len = 0;
-       if (sep != NULL)
-               sep_len = strlen (sep);
+  if (buffer != NULL)
+    buffer[0] = 0;
 
-       for (size_t i = 0; i < fields_num; i++)
-       {
-               size_t field_len;
+  if (buffer_size != 0)
+    avail = buffer_size - 1;
 
-               if ((i > 0) && (sep_len > 0))
-               {
-                       if (avail < sep_len)
-                               return (-1);
+  if (sep != NULL)
+    sep_len = strlen(sep);
 
-                       memcpy (ptr, sep, sep_len);
-                       ptr += sep_len;
-                       avail -= sep_len;
-               }
+  for (size_t i = 0; i < fields_num; i++) {
+    size_t field_len = strlen(fields[i]);
 
-               field_len = strlen (fields[i]);
-               if (avail < field_len)
-                       return (-1);
+    if (i != 0)
+      buffer_req += sep_len;
+    buffer_req += field_len;
 
-               memcpy (ptr, fields[i], field_len);
-               ptr += field_len;
-               avail -= field_len;
-       }
+    if ((i != 0) && (sep_len > 0)) {
+      if (sep_len >= avail) {
+        /* prevent subsequent iterations from writing to the
+         * buffer. */
+        avail = 0;
+        continue;
+      }
 
-       assert (buffer[buffer_size - 1] == 0);
-       return ((int) strlen (buffer));
+      memcpy(ptr, sep, sep_len);
+
+      ptr += sep_len;
+      avail -= sep_len;
+    }
+
+    if (field_len > avail)
+      field_len = avail;
+
+    memcpy(ptr, fields[i], field_len);
+    ptr += field_len;
+
+    avail -= field_len;
+    if (ptr != NULL)
+      *ptr = 0;
+  }
+
+  return (int)buffer_req;
 }
 
 int escape_string (char *buffer, size_t buffer_size)
@@ -1199,6 +1209,18 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
        return (0);
 } /* int parse_values */
 
+int parse_value_file (char const *path, value_t *ret_value, int ds_type)
+{
+       char buffer[256];
+
+       if (read_file_contents (path, buffer, sizeof (buffer)) < 0)
+               return errno;
+
+       strstripnewline (buffer);
+
+       return parse_value (buffer, ret_value, ds_type);
+} /* int parse_value_file */
+
 #if !HAVE_GETPWNAM_R
 int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf,
                size_t buflen, struct passwd **pwbufp)
index 720e5f1..6d01ca4 100644 (file)
@@ -147,10 +147,12 @@ int strsplit (char *string, char **fields, size_t size);
  *   is equivalent to the Perl built-in `join'.
  *
  * PARAMETERS
- *   `dst'         Buffer where the result is stored.
+ *   `dst'         Buffer where the result is stored. Can be NULL if you need to
+ *                 determine the required buffer size only.
  *   `dst_len'     Length of the destination buffer. No more than this many
  *                 bytes will be written to the memory pointed to by `dst',
- *                 including the trailing null-byte.
+ *                 including the trailing null-byte. Must be zero if dst is
+ *                 NULL.
  *   `fields'      Array of strings to be joined.
  *   `fields_num'  Number of elements in the `fields' array.
  *   `sep'         String to be inserted between any two elements of `fields'.
@@ -158,9 +160,10 @@ int strsplit (char *string, char **fields, size_t size);
  *                 Instead of passing "" (empty string) one can pass NULL.
  *
  * RETURN VALUE
- *   Returns the number of characters in `dst', NOT including the trailing
- *   null-byte. If an error occurred (empty array or `dst' too small) a value
- *   smaller than zero will be returned.
+ *   Returns the number of characters in the resulting string, excluding a
+ *   tailing null byte. If this value is greater than or equal to "dst_len", the
+ *   result in "dst" is truncated (but still null terminated). On error a
+ *   negative value is returned.
  */
 int strjoin (char *dst, size_t dst_len, char **fields, size_t fields_num, const char *sep);
 
@@ -322,6 +325,11 @@ int parse_identifier_vl (const char *str, value_list_t *vl);
 int parse_value (const char *value, value_t *ret_value, int ds_type);
 int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds);
 
+/* parse_value_file reads "path" and parses its content as an integer or
+ * floating point, depending on "ds_type". On success, the value is stored in
+ * "ret_value" and zero is returned. On failure, a non-zero value is returned. */
+int parse_value_file (char const *path, value_t *ret_value, int ds_type);
+
 #if !HAVE_GETPWNAM_R
 int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf,
                size_t buflen, struct passwd **pwbufp);
index 202ddf6..44e198d 100644 (file)
@@ -148,46 +148,54 @@ DEF_TEST(strsplit)
   return (0);
 }
 
-DEF_TEST(strjoin)
-{
-  char buffer[16];
-  char *fields[4];
-  int status;
-
-  fields[0] = "foo";
-  fields[1] = "bar";
-  fields[2] = "baz";
-  fields[3] = "qux";
-
-  status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
-  OK(status == 7);
-  EXPECT_EQ_STR ("foo!bar", buffer);
-
-  status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
-  OK(status == 3);
-  EXPECT_EQ_STR ("foo", buffer);
-
-  status = strjoin (buffer, sizeof (buffer), fields, 0, "!");
-  OK(status < 0);
-
-  status = strjoin (buffer, sizeof (buffer), fields, 2, "rcht");
-  OK(status == 10);
-  EXPECT_EQ_STR ("foorchtbar", buffer);
-
-  status = strjoin (buffer, sizeof (buffer), fields, 4, "");
-  OK(status == 12);
-  EXPECT_EQ_STR ("foobarbazqux", buffer);
+DEF_TEST(strjoin) {
+  struct {
+    char **fields;
+    size_t fields_num;
+    char *separator;
+
+    int want_return;
+    char *want_buffer;
+  } cases
+      [] = {
+          /* Normal case. */
+          {(char *[]){"foo", "bar"}, 2, "!", 7, "foo!bar"},
+          /* One field only. */
+          {(char *[]){"foo"}, 1, "!", 3, "foo"},
+          /* No fields at all. */
+          {NULL, 0, "!", 0, ""},
+          /* Longer separator. */
+          {(char *[]){"foo", "bar"}, 2, "rcht", 10, "foorchtbar"},
+          /* Empty separator. */
+          {(char *[]){"foo", "bar"}, 2, "", 6, "foobar"},
+          /* NULL separator. */
+          {(char *[]){"foo", "bar"}, 2, NULL, 6, "foobar"},
+          /* buffer not large enough -> string is truncated. */
+          {(char *[]){"aaaaaa", "bbbbbb", "c!"}, 3, "-", 16, "aaaaaa-bbbbbb-c"},
+          /* buffer not large enough -> last field fills buffer completely. */
+          {(char *[]){"aaaaaaa", "bbbbbbb", "!"}, 3, "-", 17,
+           "aaaaaaa-bbbbbbb"},
+          /* buffer not large enough -> string does *not* end in separator. */
+          {(char *[]){"aaaa", "bbbb", "cccc", "!"}, 4, "-", 16,
+           "aaaa-bbbb-cccc"},
+          /* buffer not large enough -> string does not end with partial
+             separator. */
+          {(char *[]){"aaaaaa", "bbbbbb", "!"}, 3, "+-", 17, "aaaaaa+-bbbbbb"},
+      };
+
+  for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases); i++) {
+    char buffer[16];
+    int status;
 
-  status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
-  OK(status == 15);
-  EXPECT_EQ_STR ("foo!bar!baz!qux", buffer);
+    memset(buffer, 0xFF, sizeof(buffer));
+    status = strjoin(buffer, sizeof(buffer), cases[i].fields,
+                     cases[i].fields_num, cases[i].separator);
+    EXPECT_EQ_INT(cases[i].want_return, status);
+    EXPECT_EQ_STR(cases[i].want_buffer, buffer);
+  }
 
-  fields[0] = "0123";
-  fields[1] = "4567";
-  fields[2] = "8901";
-  fields[3] = "2345";
-  status = strjoin (buffer, sizeof (buffer), fields, 4, "-");
-  OK(status < 0);
+  /* use (NULL, 0) to determine required buffer size. */
+  EXPECT_EQ_INT(3, strjoin(NULL, 0, (char *[]){"a", "b"}, 2, "-"));
 
   return (0);
 }
index 9e4fd07..a11fccb 100644 (file)
 
 #include "collectd.h"
 
+#include "common.h"
 #include "plugin.h"
 #include "meta_data.h"
 
+#define MD_MAX_NONSTRING_CHARS 128
+
 /*
  * Data types
  */
@@ -729,4 +732,68 @@ int meta_data_get_boolean (meta_data_t *md, /* {{{ */
   return (0);
 } /* }}} int meta_data_get_boolean */
 
+int meta_data_as_string (meta_data_t *md, /* {{{ */
+    const char *key, char **value)
+{
+  meta_entry_t *e;
+  char *actual;
+  char buffer[MD_MAX_NONSTRING_CHARS];  /* For non-string types. */
+  char *temp;
+  int type;
+
+  if ((md == NULL) || (key == NULL) || (value == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  e = md_entry_lookup (md, key);
+  if (e == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  type = e->type;
+
+  switch (type)
+  {
+    case MD_TYPE_STRING:
+      actual = e->value.mv_string;
+      break;
+    case MD_TYPE_SIGNED_INT:
+      ssnprintf (buffer, sizeof (buffer), "%"PRIi64, e->value.mv_signed_int);
+      actual = buffer;
+      break;
+    case MD_TYPE_UNSIGNED_INT:
+      ssnprintf (buffer, sizeof (buffer), "%"PRIu64, e->value.mv_unsigned_int);
+      actual = buffer;
+      break;
+    case MD_TYPE_DOUBLE:
+      ssnprintf (buffer, sizeof (buffer), GAUGE_FORMAT, e->value.mv_double);
+      actual = buffer;
+      break;
+    case MD_TYPE_BOOLEAN:
+      actual = e->value.mv_boolean ? "true" : "false";
+      break;
+    default:
+      pthread_mutex_unlock (&md->lock);
+      ERROR ("meta_data_as_string: unknown type %d for key `%s'", type, key);
+      return (-ENOENT);
+  }
+
+  pthread_mutex_unlock (&md->lock);
+
+  temp = md_strdup (actual);
+  if (temp == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    ERROR ("meta_data_as_string: md_strdup failed for key `%s'.", key);
+    return (-ENOMEM);
+  }
+
+  *value = temp;
+
+  return (0);
+} /* }}} int meta_data_as_string */
+
 /* vim: set sw=2 sts=2 et fdm=marker : */
index 0398c54..f4a4f21 100644 (file)
@@ -84,5 +84,10 @@ int meta_data_get_boolean (meta_data_t *md,
     const char *key,
     _Bool *value);
 
+/* Returns the value as a string, regardless of the type. */
+int meta_data_as_string (meta_data_t *md,
+    const char *key,
+    char **value);
+
 #endif /* META_DATA_H */
 /* vim: set sw=2 sts=2 et : */
index c6efc3f..d4b962f 100644 (file)
@@ -151,34 +151,28 @@ static const char *plugin_get_dir (void)
 }
 
 static void plugin_update_internal_statistics (void) { /* {{{ */
-       derive_t copy_write_queue_length;
-       value_list_t vl = VALUE_LIST_INIT;
-       value_t values[2];
 
-       copy_write_queue_length = write_queue_length;
+       gauge_t copy_write_queue_length = (gauge_t) write_queue_length;
 
        /* Initialize `vl' */
-       vl.values = values;
-       vl.values_len = 2;
-       vl.time = 0;
+       value_list_t vl = VALUE_LIST_INIT;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "collectd", sizeof (vl.plugin));
 
-       vl.type_instance[0] = 0;
-       vl.values_len = 1;
-
        /* Write queue */
        sstrncpy (vl.plugin_instance, "write_queue",
                        sizeof (vl.plugin_instance));
 
        /* Write queue : queue length */
-       vl.values[0].gauge = (gauge_t) copy_write_queue_length;
+       vl.values = &(value_t) { .gauge = copy_write_queue_length };
+       vl.values_len = 1;
        sstrncpy (vl.type, "queue_length", sizeof (vl.type));
        vl.type_instance[0] = 0;
        plugin_dispatch_values (&vl);
 
        /* Write queue : Values dropped (queue length > low limit) */
-       vl.values[0].derive = (derive_t) stats_values_dropped;
+       vl.values = &(value_t) { .gauge = (gauge_t) stats_values_dropped };
+       vl.values_len = 1;
        sstrncpy (vl.type, "derive", sizeof (vl.type));
        sstrncpy (vl.type_instance, "dropped", sizeof (vl.type_instance));
        plugin_dispatch_values (&vl);
@@ -188,7 +182,8 @@ static void plugin_update_internal_statistics (void) { /* {{{ */
                        sizeof (vl.plugin_instance));
 
        /* Cache : Nb entry in cache tree */
-       vl.values[0].gauge = (gauge_t) uc_get_size();
+       vl.values = &(value_t) { .gauge = (gauge_t) uc_get_size() };
+       vl.values_len = 1;
        sstrncpy (vl.type, "cache_size", sizeof (vl.type));
        vl.type_instance[0] = 0;
        plugin_dispatch_values (&vl);
index 19d4b0a..fefbf87 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
@@ -390,24 +390,19 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
     }
     else
     {
-      char *name = NULL;
-
       databases = temp;
       databases[databases_num] = db;
       databases_num++;
 
-      name = ssnprintf_alloc("dbi:%s", db->name);
-
-      user_data_t ud = {
-        .data = db
-      };
-
+      char *name = ssnprintf_alloc("dbi:%s", db->name);
       plugin_register_complex_read (/* group = */ NULL,
           /* name = */ name ? name : db->name,
           /* callback = */ cdbi_read_database,
           /* interval = */ (db->interval > 0) ? db->interval : 0,
-          /* user_data = */ &ud);
-      free (name);
+          &(user_data_t) {
+            .data = db,
+         });
+      sfree (name);
     }
   }
 
index af54c92..632787b 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -161,12 +161,9 @@ static void df_submit_one (char *plugin_instance,
                const char *type, const char *type_instance,
                gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "df", sizeof (vl.plugin));
index 465b005..2c0d8b5 100644 (file)
@@ -297,14 +297,14 @@ static void disk_submit (const char *plugin_instance,
                const char *type,
                derive_t read, derive_t write)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = read;
-       values[1].derive = write;
+       value_t values[] = {
+               { .derive = read },
+               { .derive = write },
+       };
 
        vl.values = values;
-       vl.values_len = 2;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, plugin_instance,
@@ -317,14 +317,14 @@ static void disk_submit (const char *plugin_instance,
 #if KERNEL_FREEBSD || KERNEL_LINUX
 static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = io_time;
-       values[1].derive = weighted_time;
+       value_t values[] = {
+               { .derive = io_time },
+               { .derive = weighted_time },
+       };
 
        vl.values = values;
-       vl.values_len = 2;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
@@ -337,12 +337,9 @@ static void submit_io_time (char const *plugin_instance, derive_t io_time, deriv
 #if KERNEL_LINUX
 static void submit_in_progress (char const *disk_name, gauge_t in_progress)
 {
-       value_t v;
        value_list_t vl = VALUE_LIST_INIT;
 
-       v.gauge = in_progress;
-
-       vl.values = &v;
+       vl.values = &(value_t) { .gauge = in_progress };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
@@ -352,7 +349,6 @@ static void submit_in_progress (char const *disk_name, gauge_t in_progress)
        plugin_dispatch_values (&vl);
 }
 
-
 static counter_t disk_calc_time_incr (counter_t delta_time, counter_t delta_ops)
 {
        double interval = CDTIME_T_TO_DOUBLE (plugin_get_interval ());
index 0494b4b..ae53710 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -370,12 +370,9 @@ static int dns_init (void)
 static void submit_derive (const char *type, const char *type_instance,
                derive_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .derive = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "dns", sizeof (vl.plugin));
@@ -387,14 +384,14 @@ static void submit_derive (const char *type, const char *type_instance,
 
 static void submit_octets (derive_t queries, derive_t responses)
 {
-       value_t values[2];
+       value_t values[] = {
+          { .derive = queries },
+          { .derive = responses },
+        };
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = queries;
-       values[1].derive = responses;
-
        vl.values = values;
-       vl.values_len = 2;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "dns", sizeof (vl.plugin));
        sstrncpy (vl.type, "dns_octets", sizeof (vl.type));
index 2662da9..97fbdfe 100644 (file)
@@ -653,12 +653,9 @@ static int email_shutdown (void)
 
 static void email_submit (const char *type, const char *type_instance, gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "email", sizeof (vl.plugin));
index f4f4ac4..b385c2a 100644 (file)
 
 #define ENTROPY_FILE "/proc/sys/kernel/random/entropy_avail"
 
-static void entropy_submit (double entropy)
+static void entropy_submit (value_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = entropy;
-
-       vl.values = values;
+       vl.values = &value;
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "entropy", sizeof (vl.plugin));
@@ -53,26 +50,14 @@ static void entropy_submit (double entropy)
 
 static int entropy_read (void)
 {
-       double entropy;
-       FILE *fh;
-       char buffer[64];
-
-       fh = fopen (ENTROPY_FILE, "r");
-       if (fh == NULL)
-               return (-1);
-
-       if (fgets (buffer, sizeof (buffer), fh) == NULL)
+       value_t v;
+       if (parse_value_file (ENTROPY_FILE, &v, DS_TYPE_GAUGE) != 0)
        {
-               fclose (fh);
+               ERROR ("entropy plugin: Reading \""ENTROPY_FILE"\" failed.");
                return (-1);
        }
-       fclose (fh);
-
-       entropy = atof (buffer);
-       
-       if (entropy > 0.0)
-               entropy_submit (entropy);
 
+       entropy_submit (v);
        return (0);
 }
 
index d0e7728..f0b8d9f 100644 (file)
@@ -172,7 +172,6 @@ static void ethstat_submit_value (const char *device,
 {
   static c_complain_t complain_no_map = C_COMPLAIN_INIT_STATIC;
 
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
   value_map_t *map = NULL;
 
@@ -189,8 +188,7 @@ static void ethstat_submit_value (const char *device,
     return;
   }
 
-  values[0].derive = value;
-  vl.values = values;
+  vl.values = &(value_t) { .derive = value };
   vl.values_len = 1;
 
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
index 4b3abff..a2f5aa8 100644 (file)
@@ -60,13 +60,9 @@ static int fhcount_config(const char *key, const char *value) {
 
 static void fhcount_submit(
     const char *type, const char *type_instance, gauge_t value) {
-
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
 
   // Compose the metric
@@ -79,7 +75,6 @@ static void fhcount_submit(
   plugin_dispatch_values(&vl);
 }
 
-
 static int fhcount_read(void) {
   int numfields = 0;
   int buffer_len = 60;
index 9de9e6c..c1e53a2 100644 (file)
@@ -61,13 +61,10 @@ static size_t directories_num = 0;
 
 static void fc_submit_dir (const fc_directory_conf_t *dir)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = (gauge_t) dir->files_num;
-
-  vl.values = values;
-  vl.values_len = STATIC_ARRAY_SIZE (values);
+  vl.values = &(value_t) { .gauge = (gauge_t) dir->files_num };
+  vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "filecount", sizeof (vl.plugin));
   sstrncpy (vl.plugin_instance, dir->instance, sizeof (vl.plugin_instance));
@@ -75,7 +72,7 @@ static void fc_submit_dir (const fc_directory_conf_t *dir)
 
   plugin_dispatch_values (&vl);
 
-  values[0].gauge = (gauge_t) dir->files_size;
+  vl.values = &(value_t) { .gauge = (gauge_t) dir->files_size };
   sstrncpy (vl.type, "bytes", sizeof (vl.type));
 
   plugin_dispatch_values (&vl);
index f72cef4..d5b7176 100644 (file)
--- a/src/gps.c
+++ b/src/gps.c
@@ -220,12 +220,9 @@ quit:
  */
 static void cgps_submit (const char *type, gauge_t value, const char *type_instance)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "gps", sizeof (vl.plugin));
index 865ea86..31960b5 100644 (file)
@@ -226,12 +226,9 @@ static int hddtemp_config (const char *key, const char *value)
 
 static void hddtemp_submit (char *type_instance, double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "hddtemp", sizeof (vl.plugin));
index ac9441d..f62df83 100644 (file)
@@ -4,15 +4,15 @@
  *
  * Copyright(c) 2016 Intel Corporation. All rights reserved.
  *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
  *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * Authors:
  *   Jaroslav Safka <jaroslavx.safka@intel.com>
  *   Kim-Marie Jones <kim-marie.jones@intel.com>
+ *   Florian Forster <octo at collectd.org>
  */
 
 #include "collectd.h"
+
 #include "common.h" /* auxiliary functions */
 #include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
 
 static const char g_plugin_name[] = "hugepages";
-static const char g_cfg_rpt_numa[] = "ReportPerNodeHP";
-static const char g_cfg_rpt_mm[] = "ReportRootHP";
 
-static const char *g_config_keys[] = {
-  g_cfg_rpt_numa,
-  g_cfg_rpt_mm,
-};
-static size_t g_config_keys_num = STATIC_ARRAY_SIZE(g_config_keys);
-static int g_flag_rpt_numa = 1;
-static int g_flag_rpt_mm = 1;
+static _Bool g_flag_rpt_numa = 1;
+static _Bool g_flag_rpt_mm = 1;
+
+static _Bool g_values_pages = 1;
+static _Bool g_values_bytes = 0;
+static _Bool g_values_percent = 0;
+
+#define HP_HAVE_NR 0x01
+#define HP_HAVE_SURPLUS 0x02
+#define HP_HAVE_FREE 0x04
+#define HP_HAVE_ALL 0x07
 
 struct entry_info {
   char *d_name;
   const char *node;
-};
+  size_t page_size_kb;
 
-static int huge_config_callback(const char *key, const char *val)
-{
-  DEBUG("%s: HugePages config key='%s', val='%s'", g_plugin_name, key, val);
+  gauge_t nr;
+  gauge_t surplus;
+  gauge_t free;
+  uint8_t flags;
+};
 
-  if (strcasecmp(key, g_cfg_rpt_numa) == 0) {
-    g_flag_rpt_numa = IS_TRUE(val);
-    return 0;
-  }
-  if (strcasecmp(key, g_cfg_rpt_mm) == 0) {
-    g_flag_rpt_mm = IS_TRUE(val);
-    return 0;
+static int hp_config(oconfig_item_t *ci) {
+  for (int i = 0; i < ci->children_num; i++) {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp("ReportPerNodeHP", child->key) == 0)
+      cf_util_get_boolean(child, &g_flag_rpt_numa);
+    else if (strcasecmp("ReportRootHP", child->key) == 0)
+      cf_util_get_boolean(child, &g_flag_rpt_mm);
+    else if (strcasecmp("ValuesPages", child->key) == 0)
+      cf_util_get_boolean(child, &g_values_pages);
+    else if (strcasecmp("ValuesBytes", child->key) == 0)
+      cf_util_get_boolean(child, &g_values_bytes);
+    else if (strcasecmp("ValuesPercentage", child->key) == 0)
+      cf_util_get_boolean(child, &g_values_percent);
+    else
+      ERROR("%s: Invalid configuration option: \"%s\".", g_plugin_name,
+            child->key);
   }
 
-  return -1;
+  return (0);
 }
 
-static void submit_hp(const char *plug_inst, const char *type,
-  const char *type_instance, gauge_t free_value, gauge_t used_value)
-{
-  value_t values[2];
+static void submit_hp(const struct entry_info *info) {
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = free_value;
-  values[1].gauge = used_value;
-
-  vl.values = values;
-  vl.values_len = 2;
-  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
-  sstrncpy (vl.plugin, g_plugin_name, sizeof (vl.plugin));
-  sstrncpy (vl.plugin_instance, plug_inst, 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));
+  vl.values = &(value_t) { .gauge = NAN };
+  vl.values_len = 1;
+
+  sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+  sstrncpy(vl.plugin, g_plugin_name, sizeof(vl.plugin));
+  if (info->node) {
+    ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%zuKb",
+              info->node, info->page_size_kb);
+  } else {
+    ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%zuKb",
+              info->page_size_kb);
   }
 
-  DEBUG("submit_hp pl_inst:%s, inst_type %s, type %s, free=%lf, used=%lf",
-      plug_inst, type_instance, type, free_value, used_value);
+  /* ensure all metrics have the same timestamp */
+  vl.time = cdtime();
 
-  plugin_dispatch_values (&vl);
+  gauge_t free = info->free;
+  gauge_t used = (info->nr + info->surplus) - info->free;
+
+  if (g_values_pages) {
+    sstrncpy(vl.type, "vmpage_number", sizeof(vl.type));
+    plugin_dispatch_multivalue(&vl, /* store_percentage = */ 0, DS_TYPE_GAUGE,
+                               "free", free, "used", used, NULL);
+  }
+  if (g_values_bytes) {
+    gauge_t page_size = (gauge_t)(1024 * info->page_size_kb);
+    sstrncpy(vl.type, "memory", sizeof(vl.type));
+    plugin_dispatch_multivalue(&vl, /* store_percentage = */ 0, DS_TYPE_GAUGE,
+                               "free", free * page_size, "used",
+                               used * page_size, NULL);
+  }
+  if (g_values_percent) {
+    sstrncpy(vl.type, "percent", sizeof(vl.type));
+    plugin_dispatch_multivalue(&vl, /* store_percentage = */ 1, DS_TYPE_GAUGE,
+                               "free", free, "used", used, NULL);
+  }
 }
 
 static int read_hugepage_entry(const char *path, const char *entry,
-    void *e_info)
-{
+                               void *e_info) {
   char path2[PATH_MAX];
-  static const char type[] = "hugepages";
-  static const char partial_type_inst[] = "free_used";
-  char type_instance[PATH_MAX];
-  char *strin;
-  struct entry_info *hpsize_plinst = e_info;
-  static int flag = 0;
-  static double used_hp = 0;
-  static double free_hp = 0;
+  struct entry_info *info = e_info;
   double value;
 
   ssnprintf(path2, sizeof(path2), "%s/%s", path, entry);
@@ -112,58 +134,40 @@ static int read_hugepage_entry(const char *path, const char *entry,
     return -1;
   }
 
-  if (fscanf(fh, "%lf", &value) !=1) {
+  if (fscanf(fh, "%lf", &value) != 1) {
     ERROR("%s: cannot parse file %s", g_plugin_name, path2);
     fclose(fh);
     return -1;
   }
+  fclose(fh);
 
   if (strcmp(entry, "nr_hugepages") == 0) {
-    used_hp += value;
-    flag++;
+    info->nr = value;
+    info->flags |= HP_HAVE_NR;
   } else if (strcmp(entry, "surplus_hugepages") == 0) {
-    used_hp += value;
-    flag++;
+    info->surplus = value;
+    info->flags |= HP_HAVE_SURPLUS;
   } else if (strcmp(entry, "free_hugepages") == 0) {
-    used_hp -= value;
-    free_hp = value;
-    flag++;
+    info->free = value;
+    info->flags |= HP_HAVE_FREE;
   }
 
-  if (flag == 3) {
-    /* Can now submit "used" and "free" values.
-     * 0x2D is the ASCII "-" character, after which the string
-     *   contains "<size>kB"
-     * The string passed as param 3 to submit_hp is of the format:
-     *   <type>-<partial_type_inst>-<size>kB
-     */
-    strin = strchr(hpsize_plinst->d_name, 0x2D);
-    if (strin != NULL) {
-      ssnprintf(type_instance, sizeof(type_instance), "%s%s", partial_type_inst, strin);
-    } else {
-      ssnprintf(type_instance, sizeof(type_instance), "%s%s", partial_type_inst,
-          hpsize_plinst->d_name);
-    }
-    submit_hp(hpsize_plinst->node, type, type_instance, free_hp, used_hp);
-
-    /* Reset for next time */
-    flag = 0;
-    used_hp = 0;
-    free_hp = 0;
+  if (info->flags != HP_HAVE_ALL) {
+    return 0;
   }
 
-  fclose(fh);
+  submit_hp(info);
+
+  /* Reset flags so subsequent calls don't submit again. */
+  info->flags = 0;
   return 0;
 }
 
-static int read_syshugepages(const char* path, const char* node)
-{
-  static const char hugepages_dir[] = "hugepages";
+static int read_syshugepages(const char *path, const char *node) {
+  static const char hugepages_dir[] = "hugepages-";
   DIR *dir;
   struct dirent *result;
   char path2[PATH_MAX];
-  struct entry_info e_info;
-  long lim;
 
   dir = opendir(path);
   if (dir == NULL) {
@@ -171,55 +175,56 @@ static int read_syshugepages(const char* path, const char* node)
     return -1;
   }
 
-  errno = 0;
-  if ((lim = pathconf(path, _PC_NAME_MAX)) == -1) {
-    /* Limit not defined if errno == 0, otherwise error */
-    if (errno != 0) {
-      ERROR("%s: pathconf failed", g_plugin_name);
-      closedir(dir);
-      return -1;
-    } else {
-      lim = PATH_MAX;
-    }
-  }
-
   /* read "hugepages-XXXXXkB" entries */
   while ((result = readdir(dir)) != NULL) {
-    if (strncmp(result->d_name, hugepages_dir, sizeof(hugepages_dir)-1)) {
+    if (strncmp(result->d_name, hugepages_dir, sizeof(hugepages_dir) - 1)) {
       /* not node dir */
       errno = 0;
       continue;
     }
 
-    /* /sys/devices/system/node/node?/hugepages/ */
-    ssnprintf(path2, (size_t) lim, "%s/%s", path, result->d_name);
+    long page_size = strtol(result->d_name + strlen(hugepages_dir),
+                            /* endptr = */ NULL, /* base = */ 10);
+    if (errno != 0) {
+      char errbuf[1024];
+      ERROR("%s: failed to determine page size from directory name \"%s\": %s",
+            g_plugin_name, result->d_name,
+            sstrerror(errno, errbuf, sizeof(errbuf)));
+      continue;
+    }
 
-    e_info.d_name = result->d_name;
-    e_info.node = node;
-    walk_directory(path2, read_hugepage_entry, &e_info, 0);
+    /* /sys/devices/system/node/node?/hugepages/ */
+    ssnprintf(path2, sizeof(path2), "%s/%s", path, result->d_name);
+
+    walk_directory(path2, read_hugepage_entry,
+                   &(struct entry_info){
+                       .d_name = result->d_name,
+                       .node = node,
+                       .page_size_kb = (size_t)page_size,
+                   },
+                   /* hidden = */ 0);
     errno = 0;
   }
 
   /* Check if NULL return from readdir() was an error */
   if (errno != 0) {
-      ERROR("%s: readdir failed", g_plugin_name);
-      closedir(dir);
-      return -1;
+    ERROR("%s: readdir failed", g_plugin_name);
+    closedir(dir);
+    return -1;
   }
 
   closedir(dir);
   return 0;
 }
 
-static int read_nodes(void)
-{
+static int read_nodes(void) {
   static const char sys_node[] = "/sys/devices/system/node";
   static const char node_string[] = "node";
-  static const char sys_node_hugepages[] = "/sys/devices/system/node/%s/hugepages";
+  static const char sys_node_hugepages[] =
+      "/sys/devices/system/node/%s/hugepages";
   DIR *dir;
   struct dirent *result;
   char path[PATH_MAX];
-  long lim;
 
   dir = opendir(sys_node);
   if (dir == NULL) {
@@ -227,44 +232,30 @@ static int read_nodes(void)
     return -1;
   }
 
-  errno = 0;
-  if ((lim = pathconf(sys_node, _PC_NAME_MAX)) == -1) {
-    /* Limit not defined if errno == 0, otherwise error */
-    if (errno != 0) {
-      ERROR("%s: pathconf failed", g_plugin_name);
-      closedir(dir);
-      return -1;
-    } else {
-      lim = PATH_MAX;
-    }
-  }
-
   while ((result = readdir(dir)) != NULL) {
-    if (strncmp(result->d_name, node_string, sizeof(node_string)-1)) {
+    if (strncmp(result->d_name, node_string, sizeof(node_string) - 1)) {
       /* not node dir */
       errno = 0;
       continue;
     }
 
-    ssnprintf(path, (size_t) lim, sys_node_hugepages, result->d_name);
+    ssnprintf(path, sizeof(path), sys_node_hugepages, result->d_name);
     read_syshugepages(path, result->d_name);
     errno = 0;
   }
 
   /* Check if NULL return from readdir() was an error */
   if (errno != 0) {
-      ERROR("%s: readdir failed", g_plugin_name);
-      closedir(dir);
-      return -1;
+    ERROR("%s: readdir failed", g_plugin_name);
+    closedir(dir);
+    return -1;
   }
 
   closedir(dir);
   return 0;
 }
 
-
-static int huge_read(void)
-{
+static int huge_read(void) {
   static const char sys_mm_hugepages[] = "/sys/kernel/mm/hugepages";
 
   if (g_flag_rpt_mm) {
@@ -281,10 +272,7 @@ static int huge_read(void)
   return 0;
 }
 
-void module_register(void)
-{
-  plugin_register_config(g_plugin_name, huge_config_callback, g_config_keys,
-      g_config_keys_num);
+void module_register(void) {
+  plugin_register_complex_config(g_plugin_name, hp_config);
   plugin_register_read(g_plugin_name, huge_read);
 }
-
index b8ed6e4..849de95 100644 (file)
@@ -168,17 +168,17 @@ static void if_submit (const char *dev, const char *type,
                derive_t rx,
                derive_t tx)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
+       value_t values[] = {
+               { .derive = rx },
+               { .derive = tx },
+       };
 
        if (ignorelist_match (ignorelist, dev) != 0)
                return;
 
-       values[0].derive = rx;
-       values[1].derive = tx;
-
        vl.values = values;
-       vl.values_len = 2;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "interface", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
index b164cdf..d6d2bbd 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -97,12 +97,9 @@ static void ipc_submit_g (const char *plugin_instance,
                           const char *type_instance,
                           gauge_t value) /* {{{ */
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "ipc", sizeof (vl.plugin));
index ad62299..a42b787 100644 (file)
@@ -115,7 +115,6 @@ static void sensor_read_handler (ipmi_sensor_t *sensor,
     ipmi_states_t __attribute__((unused)) *states,
     void *user_data)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
   c_ipmi_sensor_list_t *list_item = (c_ipmi_sensor_list_t *)user_data;
@@ -214,9 +213,7 @@ static void sensor_read_handler (ipmi_sensor_t *sensor,
     return;
   }
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
 
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
index f691122..35975e6 100644 (file)
@@ -242,7 +242,6 @@ static int submit6_match (const struct ip6t_entry_match *match,
                           int rule_num)
 {
     int status;
-    value_t values[1];
     value_list_t vl = VALUE_LIST_INIT;
 
     /* Select the rules to collect */
@@ -260,8 +259,6 @@ static int submit6_match (const struct ip6t_entry_match *match,
             return (0);
     }
 
-    vl.values = values;
-    vl.values_len = 1;
     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
     sstrncpy (vl.plugin, "ip6tables", sizeof (vl.plugin));
 
@@ -285,16 +282,16 @@ static int submit6_match (const struct ip6t_entry_match *match,
     }
 
     sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
-    values[0].derive = (derive_t) entry->counters.bcnt;
+    vl.values = &(value_t) { .derive = (derive_t) entry->counters.bcnt };
+    vl.values_len = 1;
     plugin_dispatch_values (&vl);
 
     sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
-    values[0].derive = (derive_t) entry->counters.pcnt;
+    vl.values = &(value_t) { .derive = (derive_t) entry->counters.pcnt };
     plugin_dispatch_values (&vl);
 
     return (0);
-} /* int submit_match */
-
+} /* int submit6_match */
 
 /* This needs to return `int' for IPT_MATCH_ITERATE to work. */
 static int submit_match (const struct ipt_entry_match *match,
@@ -303,7 +300,6 @@ static int submit_match (const struct ipt_entry_match *match,
                          int rule_num)
 {
     int status;
-    value_t values[1];
     value_list_t vl = VALUE_LIST_INIT;
 
     /* Select the rules to collect */
@@ -321,8 +317,6 @@ static int submit_match (const struct ipt_entry_match *match,
             return (0);
     }
 
-    vl.values = values;
-    vl.values_len = 1;
     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
     sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin));
 
@@ -346,11 +340,12 @@ static int submit_match (const struct ipt_entry_match *match,
     }
 
     sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
-    values[0].derive = (derive_t) entry->counters.bcnt;
+    vl.values = &(value_t) { .derive = (derive_t) entry->counters.bcnt };
+    vl.values_len = 1;
     plugin_dispatch_values (&vl);
 
     sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
-    values[0].derive = (derive_t) entry->counters.pcnt;
+    vl.values = &(value_t) { .derive = (derive_t) entry->counters.pcnt };
     plugin_dispatch_values (&vl);
 
     return (0);
index 92690e8..d2ceb50 100644 (file)
@@ -228,12 +228,9 @@ static int get_ti (struct ip_vs_dest_entry *de, char *ti, size_t size)
 static void cipvs_submit_connections (const char *pi, const char *ti,
                derive_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = value;
-
-       vl.values     = values;
+       vl.values     = &(value_t) { .derive = value };
        vl.values_len = 1;
 
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -250,14 +247,14 @@ static void cipvs_submit_connections (const char *pi, const char *ti,
 static void cipvs_submit_if (const char *pi, const char *t, const char *ti,
                derive_t rx, derive_t tx)
 {
-       value_t values[2];
+       value_t values[] = {
+               { .derive = rx },
+               { .derive = tx },
+       };
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = rx;
-       values[1].derive = tx;
-
        vl.values     = values;
-       vl.values_len = 2;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
 
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin));
index 0f1d3f0..cb444a4 100644 (file)
--- a/src/irq.c
+++ b/src/irq.c
@@ -72,15 +72,12 @@ static int irq_config (const char *key, const char *value)
 
 static void irq_submit (const char *irq_name, derive_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
        if (ignorelist_match (ignorelist, irq_name) != 0)
                return;
 
-       values[0].derive = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .derive = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "irq", sizeof (vl.plugin));
index 67740ac..cd173c5 100644 (file)
@@ -1425,13 +1425,11 @@ static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new read callback: %s", cbi->name);
 
-  user_data_t ud = {
-    .data = cbi,
-    .free_func = cjni_callback_info_destroy
-  };
-
   plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
-      /* interval = */ 0, &ud);
+      /* interval = */ 0, &(user_data_t) {
+        .data = cbi,
+        .free_func = cjni_callback_info_destroy,
+      });
 
   (*jvm_env)->DeleteLocalRef (jvm_env, o_read);
 
@@ -1449,12 +1447,10 @@ static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new write callback: %s", cbi->name);
 
-  user_data_t ud = {
-    .data = cbi,
-    .free_func = cjni_callback_info_destroy
-  };
-
-  plugin_register_write (cbi->name, cjni_write, &ud);
+  plugin_register_write (cbi->name, cjni_write, &(user_data_t) {
+        .data = cbi,
+        .free_func = cjni_callback_info_destroy,
+      });
 
   (*jvm_env)->DeleteLocalRef (jvm_env, o_write);
 
@@ -1472,12 +1468,10 @@ static jint JNICALL cjni_api_register_flush (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new flush callback: %s", cbi->name);
 
-  user_data_t ud = {
-    .data = cbi,
-    .free_func = cjni_callback_info_destroy
-  };
-
-  plugin_register_flush (cbi->name, cjni_flush, &ud);
+  plugin_register_flush (cbi->name, cjni_flush, &(user_data_t) {
+        .data = cbi,
+        .free_func = cjni_callback_info_destroy,
+      });
 
   (*jvm_env)->DeleteLocalRef (jvm_env, o_flush);
 
@@ -1502,12 +1496,10 @@ static jint JNICALL cjni_api_register_log (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new log callback: %s", cbi->name);
 
-  user_data_t ud = {
-    .data = cbi,
-    .free_func = cjni_callback_info_destroy
-  };
-
-  plugin_register_log (cbi->name, cjni_log, &ud);
+  plugin_register_log (cbi->name, cjni_log, &(user_data_t) {
+        .data = cbi,
+        .free_func = cjni_callback_info_destroy,
+      });
 
   (*jvm_env)->DeleteLocalRef (jvm_env, o_log);
 
@@ -1526,12 +1518,10 @@ static jint JNICALL cjni_api_register_notification (JNIEnv *jvm_env, /* {{{ */
 
   DEBUG ("java plugin: Registering new notification callback: %s", cbi->name);
 
-  user_data_t ud = {
-    .data = cbi,
-    .free_func = cjni_callback_info_destroy
-  };
-
-  plugin_register_notification (cbi->name, cjni_notification, &ud);
+  plugin_register_notification (cbi->name, cjni_notification, &(user_data_t) {
+        .data = cbi,
+        .free_func = cjni_callback_info_destroy,
+      });
 
   (*jvm_env)->DeleteLocalRef (jvm_env, o_notification);
 
index cc3be37..a3f6bb1 100644 (file)
@@ -78,8 +78,6 @@ static int load_config (const char *key, const char *value)
 }
 static void load_submit (gauge_t snum, gauge_t mnum, gauge_t lnum)
 {
-       value_t values[3];
-       value_list_t vl = VALUE_LIST_INIT;
         int cores = 0;
         char errbuf[1024];
 
@@ -97,9 +95,12 @@ static void load_submit (gauge_t snum, gauge_t mnum, gauge_t lnum)
                lnum /= cores;
        }
 
-       values[0].gauge = snum;
-       values[1].gauge = mnum;
-       values[2].gauge = lnum;
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t values[] = {
+               { .gauge = snum },
+               { .gauge = mnum },
+               { .gauge = lnum },
+       };
 
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
index 5b0bd13..0e32c83 100644 (file)
@@ -114,12 +114,9 @@ static int lpar_init (void)
 
 static void lpar_submit (const char *type_instance, double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = (gauge_t)value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        if (report_by_serial)
        {
index ba5fbce..d10b4ea 100644 (file)
--- a/src/lua.c
+++ b/src/lua.c
@@ -303,15 +303,13 @@ static int lua_cb_register_read(lua_State *L) /* {{{ */
   cb->lua_function_name = strdup(function_name);
   pthread_mutex_init(&cb->lock, NULL);
 
-  user_data_t ud = {
-    .data = cb
-  };
-
   int status = plugin_register_complex_read(/* group = */ "lua",
                                             /* name      = */ function_name,
                                             /* callback  = */ clua_read,
                                             /* interval  = */ 0,
-                                            /* user_data = */ &ud);
+                                            &(user_data_t) {
+                                              .data = cb,
+                                            });
 
   if (status != 0)
     return luaL_error(L, "%s", "plugin_register_complex_read failed");
@@ -349,13 +347,11 @@ static int lua_cb_register_write(lua_State *L) /* {{{ */
   cb->lua_function_name = strdup(function_name);
   pthread_mutex_init(&cb->lock, NULL);
 
-  user_data_t ud = {
-    .data = cb
-  };
-
   int status = plugin_register_write(/* name = */ function_name,
                                     /* callback  = */ clua_write,
-                                    /* user_data = */ &ud);
+                                    &(user_data_t) {
+                                      .data = cb,
+                                    });
 
   if (status != 0)
     return luaL_error(L, "%s", "plugin_register_write failed");
index 6b9a031..77cb6eb 100644 (file)
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -55,12 +55,9 @@ static char const *get_lv_property_string(lv_t lv, char const *property)
 static void lvm_submit (char const *plugin_instance, char const *type_instance,
         uint64_t ivalue)
 {
-    value_t v;
     value_list_t vl = VALUE_LIST_INIT;
 
-    v.gauge = (gauge_t) ivalue;
-
-    vl.values = &v;
+    vl.values = &(value_t) { .gauge = (gauge_t) ivalue };
     vl.values_len = 1;
 
     sstrncpy(vl.host, hostname_g, sizeof (vl.host));
index 053bd7f..42474bc 100644 (file)
@@ -538,7 +538,7 @@ static int madwifi_config (const char *key, const char *value)
 
 
 static void submit (const char *dev, const char *type, const char *ti1,
-                       const char *ti2, value_t *val, int len)
+                       const char *ti2, value_t *val, size_t len)
 {
        value_list_t vl = VALUE_LIST_INIT;
 
@@ -558,28 +558,26 @@ static void submit (const char *dev, const char *type, const char *ti1,
 }
 
 static void submit_derive (const char *dev, const char *type, const char *ti1,
-                               const char *ti2, derive_t val)
+                               const char *ti2, derive_t value)
 {
-       value_t item;
-       item.derive = val;
-       submit (dev, type, ti1, ti2, &item, 1);
+       submit (dev, type, ti1, ti2, &(value_t) { .derive = value }, 1);
 }
 
 static void submit_derive2 (const char *dev, const char *type, const char *ti1,
                                const char *ti2, derive_t val1, derive_t val2)
 {
-       value_t items[2];
-       items[0].derive = val1;
-       items[1].derive = val2;
-       submit (dev, type, ti1, ti2, items, 2);
+       value_t values[] = {
+          { .derive = val1 },
+          { .derive = val2 },
+        };
+
+       submit (dev, type, ti1, ti2, values, STATIC_ARRAY_SIZE (values));
 }
 
 static void submit_gauge (const char *dev, const char *type, const char *ti1,
-                               const char *ti2, gauge_t val)
+                               const char *ti2, gauge_t value)
 {
-       value_t item;
-       item.gauge = val;
-       submit (dev, type, ti1, ti2, &item, 1);
+       submit (dev, type, ti1, ti2, &(value_t) { .gauge = value }, 1);
 }
 
 static void submit_antx (const char *dev, const char *name,
index cd63016..dd8319e 100644 (file)
 
 #include "collectd.h"
 
+#include "common.h"
 #include "filter_chain.h"
+#include "meta_data.h"
+#include "utils_llist.h"
 
 #include <sys/types.h>
 #include <regex.h>
@@ -64,6 +67,7 @@ struct mr_match_s
        mr_regex_t *plugin_instance;
        mr_regex_t *type;
        mr_regex_t *type_instance;
+       llist_t *meta;  /* Maps each meta key into mr_regex_t* */
        _Bool invert;
 };
 
@@ -77,7 +81,7 @@ static void mr_free_regex (mr_regex_t *r) /* {{{ */
 
        regfree (&r->re);
        memset (&r->re, 0, sizeof (r->re));
-       free (r->re_str);
+       sfree (r->re_str);
 
        if (r->next != NULL)
                mr_free_regex (r->next);
@@ -93,8 +97,14 @@ static void mr_free_match (mr_match_t *m) /* {{{ */
        mr_free_regex (m->plugin_instance);
        mr_free_regex (m->type);
        mr_free_regex (m->type_instance);
+       for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next)
+       {
+               sfree (e->key);
+               mr_free_regex ((mr_regex_t *) e->value);
+       }
+       llist_destroy (m->meta);
 
-       free (m);
+       sfree (m);
 } /* }}} void mr_free_match */
 
 static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */
@@ -127,31 +137,25 @@ static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */
        return (FC_MATCH_MATCHES);
 } /* }}} int mr_match_regexen */
 
-static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
-               oconfig_item_t *ci)
+static int mr_add_regex (mr_regex_t **re_head, const char *re_str, /* {{{ */
+               const char *option)
 {
        mr_regex_t *re;
        int status;
 
-       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
-       {
-               log_warn ("`%s' needs exactly one string argument.", ci->key);
-               return (-1);
-       }
-
        re = calloc (1, sizeof (*re));
        if (re == NULL)
        {
-               log_err ("mr_config_add_regex: calloc failed.");
+               log_err ("mr_add_regex: calloc failed.");
                return (-1);
        }
        re->next = NULL;
 
-       re->re_str = strdup (ci->values[0].value.string);
+       re->re_str = strdup (re_str);
        if (re->re_str == NULL)
        {
-               free (re);
-               log_err ("mr_config_add_regex: strdup failed.");
+               sfree (re);
+               log_err ("mr_add_regex: strdup failed.");
                return (-1);
        }
 
@@ -162,9 +166,9 @@ static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
                regerror (status, &re->re, errmsg, sizeof (errmsg));
                errmsg[sizeof (errmsg) - 1] = 0;
                log_err ("Compiling regex `%s' for `%s' failed: %s.",
-                               re->re_str, ci->key, errmsg);
-               free (re->re_str);
-               free (re);
+                               re->re_str, option, errmsg);
+               sfree (re->re_str);
+               sfree (re);
                return (-1);
        }
 
@@ -184,8 +188,78 @@ static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
        }
 
        return (0);
+} /* }}} int mr_add_regex */
+
+static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
+               oconfig_item_t *ci)
+{
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+       {
+               log_warn ("`%s' needs exactly one string argument.", ci->key);
+               return (-1);
+       }
+
+       return mr_add_regex (re_head, ci->values[0].value.string, ci->key);
 } /* }}} int mr_config_add_regex */
 
+static int mr_config_add_meta_regex (llist_t **meta, /* {{{ */
+               oconfig_item_t *ci)
+{
+       char *meta_key;
+       llentry_t *entry;
+       mr_regex_t *re_head;
+       int status;
+       char buffer[1024];
+
+       if ((ci->values_num != 2)
+               || (ci->values[0].type != OCONFIG_TYPE_STRING)
+               || (ci->values[1].type != OCONFIG_TYPE_STRING))
+       {
+               log_warn ("`%s' needs exactly two string arguments.", ci->key);
+               return (-1);
+       }
+
+       if (*meta == NULL)
+       {
+               *meta = llist_create();
+               if (*meta == NULL)
+               {
+                       log_err ("mr_config_add_meta_regex: llist_create failed.");
+                       return (-1);
+               }
+       }
+
+       meta_key = ci->values[0].value.string;
+       entry = llist_search (*meta, meta_key);
+       if (entry == NULL)
+       {
+               meta_key = strdup (meta_key);
+               if (meta_key == NULL)
+               {
+                       log_err ("mr_config_add_meta_regex: strdup failed.");
+                       return (-1);
+               }
+               entry = llentry_create (meta_key, NULL);
+               if (entry == NULL)
+               {
+                       log_err ("mr_config_add_meta_regex: llentry_create failed.");
+                       sfree (meta_key);
+                       return (-1);
+               }
+               /* meta_key and entry will now be freed by mr_free_match(). */
+               llist_append (*meta, entry);
+       }
+
+       ssnprintf (buffer, sizeof (buffer), "%s `%s'", ci->key, meta_key);
+       /* Can't pass &entry->value into mr_add_regex, so copy in/out. */
+       re_head = entry->value;
+       status = mr_add_regex (&re_head, ci->values[1].value.string, buffer);
+       if (status == 0) {
+               entry->value = re_head;
+       }
+       return status;
+} /* }}} int mr_config_add_meta_regex */
+
 static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
 {
        mr_match_t *m;
@@ -216,6 +290,8 @@ static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
                        status = mr_config_add_regex (&m->type, child);
                else if (strcasecmp ("TypeInstance", child->key) == 0)
                        status = mr_config_add_regex (&m->type_instance, child);
+               else if (strcasecmp ("MetaData", child->key) == 0)
+                       status = mr_config_add_meta_regex (&m->meta, child);
                else if (strcasecmp ("Invert", child->key) == 0)
                        status = cf_util_get_boolean(child, &m->invert);
                else
@@ -236,7 +312,8 @@ static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
                                && (m->plugin == NULL)
                                && (m->plugin_instance == NULL)
                                && (m->type == NULL)
-                               && (m->type_instance == NULL))
+                               && (m->type_instance == NULL)
+                               && (m->meta == NULL))
                {
                        log_err ("No (valid) regular expressions have been configured. "
                                        "This match will be ignored.");
@@ -295,6 +372,25 @@ static int mr_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
        if (mr_match_regexen (m->type_instance,
                                vl->type_instance) == FC_MATCH_NO_MATCH)
                return (nomatch_value);
+       if (vl->meta != NULL)
+       {
+               for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next)
+               {
+                       mr_regex_t *meta_re = (mr_regex_t *) e->value;
+                       char *value;
+                       int status = meta_data_get_string (vl->meta, e->key, &value);
+                       if (status == (-ENOENT))  /* key is not present */
+                               return (nomatch_value);
+                       if (status != 0)  /* some other problem */
+                               continue;  /* error will have already been printed. */
+                       if (mr_match_regexen (meta_re, value) == FC_MATCH_NO_MATCH)
+                       {
+                               sfree (value);
+                               return (nomatch_value);
+                       }
+                       sfree (value);
+               }
+       }
 
        return (match_value);
 } /* }}} int mr_match */
index 9629b89..b72be89 100644 (file)
@@ -218,12 +218,9 @@ static int mbmon_config (const char *key, const char *value)
 static void mbmon_submit (const char *type, const char *type_instance,
                double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "mbmon", sizeof (vl.plugin));
index 44cad2e..db85c46 100644 (file)
--- a/src/md.c
+++ b/src/md.c
@@ -72,12 +72,9 @@ static int md_config (const char *key, const char *value)
 static void md_submit (const int minor, const char *type_instance,
     gauge_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "md", sizeof (vl.plugin));
index dff5546..97e75c0 100644 (file)
@@ -441,14 +441,11 @@ static int cmc_init (void) /* {{{ */
 } /* }}} int cmc_init */
 
 static void cmc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */
-    const cu_match_value_t *mv)
+    value_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0] = mv->value;
-
-  vl.values = values;
+  vl.values = &value;
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "memcachec", sizeof (vl.plugin));
@@ -496,7 +493,7 @@ static int cmc_read_page (web_page_t *wp) /* {{{ */
       continue;
     }
 
-    cmc_submit (wp, wm, mv);
+    cmc_submit (wp, wm, mv->value);
     match_value_reset (mv);
   } /* for (wm = wp->matches; wm != NULL; wm = wm->next) */
 
index 9e6e725..77cadeb 100644 (file)
@@ -262,13 +262,10 @@ static void memcached_init_vl (value_list_t *vl, memcached_t const *st)
 static void submit_derive (const char *type, const char *type_inst,
     derive_t value, memcached_t *st)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
-  memcached_init_vl (&vl, st);
-
-  values[0].derive = value;
 
-  vl.values = values;
+  memcached_init_vl (&vl, st);
+  vl.values = &(value_t) { .derive = value };
   vl.values_len = 1;
   sstrncpy (vl.type, type, sizeof (vl.type));
   if (type_inst != NULL)
@@ -280,15 +277,15 @@ static void submit_derive (const char *type, const char *type_inst,
 static void submit_derive2 (const char *type, const char *type_inst,
     derive_t value0, derive_t value1, memcached_t *st)
 {
-  value_t values[2];
   value_list_t vl = VALUE_LIST_INIT;
-  memcached_init_vl (&vl, st);
-
-  values[0].derive = value0;
-  values[1].derive = value1;
+  value_t values[] = {
+    { .derive = value0 },
+    { .derive = value1 },
+  };
 
+  memcached_init_vl (&vl, st);
   vl.values = values;
-  vl.values_len = 2;
+  vl.values_len = STATIC_ARRAY_SIZE (values);
   sstrncpy (vl.type, type, sizeof (vl.type));
   if (type_inst != NULL)
     sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
@@ -299,13 +296,10 @@ static void submit_derive2 (const char *type, const char *type_inst,
 static void submit_gauge (const char *type, const char *type_inst,
     gauge_t value, memcached_t *st)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
-  memcached_init_vl (&vl, st);
-
-  values[0].gauge = value;
 
-  vl.values = values;
+  memcached_init_vl (&vl, st);
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
   sstrncpy (vl.type, type, sizeof (vl.type));
   if (type_inst != NULL)
@@ -317,15 +311,15 @@ static void submit_gauge (const char *type, const char *type_inst,
 static void submit_gauge2 (const char *type, const char *type_inst,
     gauge_t value0, gauge_t value1, memcached_t *st)
 {
-  value_t values[2];
   value_list_t vl = VALUE_LIST_INIT;
-  memcached_init_vl (&vl, st);
-
-  values[0].gauge = value0;
-  values[1].gauge = value1;
+  value_t values[] = {
+    { .gauge = value0 },
+    { .gauge = value1 },
+  };
 
+  memcached_init_vl (&vl, st);
   vl.values = values;
-  vl.values_len = 2;
+  vl.values_len = STATIC_ARRAY_SIZE (values);
   sstrncpy (vl.type, type, sizeof (vl.type));
   if (type_inst != NULL)
     sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
@@ -554,16 +548,15 @@ static int memcached_add_read_callback (memcached_t *st)
   assert (st->name != NULL);
   ssnprintf (callback_name, sizeof (callback_name), "memcached/%s", st->name);
 
-  user_data_t ud = {
-    .data = st,
-    .free_func = memcached_free
-  };
-
   status = plugin_register_complex_read (/* group = */ "memcached",
       /* name      = */ callback_name,
       /* callback  = */ memcached_read,
       /* interval  = */ 0,
-      /* user_data = */ &ud);
+      &(user_data_t) {
+        .data = st,
+        .free_func = memcached_free,
+      });
+
   return (status);
 } /* int memcached_add_read_callback */
 
index 3e31889..5ec382b 100644 (file)
--- a/src/mic.c
+++ b/src/mic.c
@@ -150,17 +150,15 @@ static int mic_config (const char *key, const char *value) {
        return (0);
 }
 
-static void mic_submit_memory_use(int micnumber, const char *type_instance, U32 val)
+static void mic_submit_memory_use(int micnumber, const char *type_instance, U32 value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
        /* MicAccessAPI reports KB's of memory, adjust for this */
-       DEBUG("mic plugin: Memory Value Report; %u %lf",val,((gauge_t)val)*1024.0);
-       values[0].gauge = ((gauge_t)val)*1024.0;
+       DEBUG("mic plugin: Memory Value Report; %u %lf",value,((gauge_t)value)*1024.0);
 
-       vl.values=values;
-       vl.values_len=1;
+       vl.values = &(value_t) { .gauge = ((gauge_t)value) * 1024.0 };
+       vl.values_len = 1;
 
        strncpy (vl.host, hostname_g, sizeof (vl.host));
        strncpy (vl.plugin, "mic", sizeof (vl.plugin));
@@ -190,15 +188,12 @@ static int mic_read_memory(int mic)
        return (0);
 }
 
-static void mic_submit_temp(int micnumber, const char *type, gauge_t val)
+static void mic_submit_temp(int micnumber, const char *type, gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = val;
-
-       vl.values=values;
-       vl.values_len=1;
+       vl.values = &(value_t) { .gauge = value };
+       vl.values_len = 1;
 
        strncpy (vl.host, hostname_g, sizeof (vl.host));
        strncpy (vl.plugin, "mic", sizeof (vl.plugin));
@@ -237,15 +232,12 @@ static int mic_read_temps(int mic)
 }
 
 static void mic_submit_cpu(int micnumber, const char *type_instance,
-               int core, derive_t val)
+               int core, derive_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = val;
-
-       vl.values=values;
-       vl.values_len=1;
+       vl.values = &(value_t) { .derive = value };
+       vl.values_len = 1;
 
        strncpy (vl.host, hostname_g, sizeof (vl.host));
        strncpy (vl.plugin, "mic", sizeof (vl.plugin));
@@ -296,15 +288,12 @@ static int mic_read_cpu(int mic)
        return (0);
 }
 
-static void mic_submit_power(int micnumber, const char *type, const char *type_instance, gauge_t val)
+static void mic_submit_power(int micnumber, const char *type, const char *type_instance, gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = val;
-
-       vl.values=values;
-       vl.values_len=1;
+       vl.values = &(value_t) { .gauge = value };
+       vl.values_len = 1;
 
        strncpy (vl.host, hostname_g, sizeof (vl.host));
        strncpy (vl.plugin, "mic", sizeof (vl.plugin));
@@ -358,13 +347,13 @@ static int mic_read (void)
        U32 ret;
        int error;
 
-       error=0;
-       for (int i=0;i<num_mics;i++) {
+       error = 0;
+       for (int i = 0;i<num_mics;i++) {
                ret = MicInitAdapter(&mic_handle,&mics[i]);
                if (ret != MIC_ACCESS_API_SUCCESS) {
                        ERROR("mic plugin: Problem initializing MicAdapter: %s",
                                        MicGetErrorString(ret));
-                       error=1;
+                       error = 1;
                }
 
                if (error == 0 && show_memory)
@@ -383,12 +372,12 @@ static int mic_read (void)
                if (ret != MIC_ACCESS_API_SUCCESS) {
                        ERROR("mic plugin: Problem closing MicAdapter: %s",
                                        MicGetErrorString(ret));
-                       error=2;
+                       error = 2;
                        break;
                }
        }
        if (num_mics==0)
-               error=3;
+               error = 3;
        return error;
 }
 
index 82213d2..a7d1b58 100644 (file)
@@ -1003,18 +1003,17 @@ static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */
 
   if (status == 0)
   {
-    user_data_t ud;
     char name[1024];
 
-    ud.data = host;
-    ud.free_func = host_free;
-
     ssnprintf (name, sizeof (name), "modbus-%s", host->host);
 
     plugin_register_complex_read (/* group = */ NULL, name,
         /* callback = */ mb_read,
         /* interval = */ host->interval,
-        &ud);
+        &(user_data_t) {
+          .data = host,
+          .free_func = host_free,
+        });
   }
   else
   {
index ad88995..c08fd29 100644 (file)
@@ -631,11 +631,9 @@ static int mqtt_config_publisher (oconfig_item_t *ci)
     }
 
     ssnprintf (cb_name, sizeof (cb_name), "mqtt/%s", conf->name);
-    user_data_t user_data = {
-        .data = conf
-    };
-
-    plugin_register_write (cb_name, mqtt_write, &user_data);
+    plugin_register_write (cb_name, mqtt_write, &(user_data_t) {
+                .data = conf,
+            });
     return (0);
 } /* mqtt_config_publisher */
 
index 02fe1ad..2ffcc8f 100644 (file)
@@ -193,12 +193,9 @@ static int multimeter_init (void)
 
 static void multimeter_submit (double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "multimeter", sizeof (vl.plugin));
index 32b72e2..a64b0e5 100644 (file)
@@ -233,14 +233,11 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
                else
                        sstrncpy (cb_name, "mysql", sizeof (cb_name));
 
-               user_data_t ud = {
-                       .data = db,
-                       .free_func = mysql_database_free
-               };
-
                plugin_register_complex_read (/* group = */ NULL, cb_name,
-                                             mysql_read,
-                                             /* interval = */ 0, &ud);
+                               mysql_read, /* interval = */ 0, &(user_data_t) {
+                                       .data = db,
+                                       .free_func = mysql_database_free,
+                               });
        }
        else
        {
@@ -368,39 +365,24 @@ static void submit (const char *type, const char *type_instance,
        plugin_dispatch_values (&vl);
 } /* submit */
 
-static void counter_submit (const char *type, const char *type_instance,
-               derive_t value, mysql_database_t *db)
-{
-       value_t values[1];
-
-       values[0].derive = value;
-       submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
-} /* void counter_submit */
-
 static void gauge_submit (const char *type, const char *type_instance,
                gauge_t value, mysql_database_t *db)
 {
-       value_t values[1];
-
-       values[0].gauge = value;
-       submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
+       submit (type, type_instance, &(value_t) { .gauge = value }, 1, db);
 } /* void gauge_submit */
 
 static void derive_submit (const char *type, const char *type_instance,
                derive_t value, mysql_database_t *db)
 {
-       value_t values[1];
-
-       values[0].derive = value;
-       submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
+       submit (type, type_instance, &(value_t) { .derive = value }, 1, db);
 } /* void derive_submit */
 
 static void traffic_submit (derive_t rx, derive_t tx, mysql_database_t *db)
 {
-       value_t values[2];
-
-       values[0].derive = rx;
-       values[1].derive = tx;
+       value_t values[] = {
+               { .derive = rx },
+               { .derive = tx },
+       };
 
        submit ("mysql_octets", NULL, values, STATIC_ARRAY_SIZE (values), db);
 } /* void traffic_submit */
@@ -465,7 +447,7 @@ static int mysql_read_master_stats (mysql_database_t *db, MYSQL *con)
        }
 
        position = atoll (row[1]);
-       counter_submit ("mysql_log_position", "master-bin", position, db);
+       derive_submit ("mysql_log_position", "master-bin", position, db);
 
        row = mysql_fetch_row (res);
        if (row != NULL)
@@ -523,10 +505,10 @@ static int mysql_read_slave_stats (mysql_database_t *db, MYSQL *con)
                double gauge;
 
                counter = atoll (row[READ_MASTER_LOG_POS_IDX]);
-               counter_submit ("mysql_log_position", "slave-read", counter, db);
+               derive_submit ("mysql_log_position", "slave-read", counter, db);
 
                counter = atoll (row[EXEC_MASTER_LOG_POS_IDX]);
-               counter_submit ("mysql_log_position", "slave-exec", counter, db);
+               derive_submit ("mysql_log_position", "slave-exec", counter, db);
 
                if (row[SECONDS_BEHIND_MASTER_IDX] != NULL)
                {
@@ -676,7 +658,7 @@ static int mysql_read_innodb_stats (mysql_database_t *db, MYSQL *con)
 
                switch (metrics[i].ds_type) {
                        case DS_TYPE_COUNTER:
-                               counter_submit(metrics[i].type, key, (counter_t)val, db);
+                               derive_submit(metrics[i].type, key, (counter_t)val, db);
                                break;
                        case DS_TYPE_GAUGE:
                                gauge_submit(metrics[i].type, key, (gauge_t)val, db);
@@ -839,7 +821,7 @@ static int mysql_read (user_data_t *ud)
 
                        /* Ignore `prepared statements' */
                        if (strncmp (key, "Com_stmt_", strlen ("Com_stmt_")) != 0)
-                               counter_submit ("mysql_commands",
+                               derive_submit ("mysql_commands",
                                                key + strlen ("Com_"),
                                                val, db);
                }
@@ -849,7 +831,7 @@ static int mysql_read (user_data_t *ud)
                        if (val == 0ULL)
                                continue;
 
-                       counter_submit ("mysql_handler",
+                       derive_submit ("mysql_handler",
                                        key + strlen ("Handler_"),
                                        val, db);
                }
@@ -890,7 +872,7 @@ static int mysql_read (user_data_t *ud)
                else if (strncmp (key, "Table_locks_",
                                        strlen ("Table_locks_")) == 0)
                {
-                       counter_submit ("mysql_locks",
+                       derive_submit ("mysql_locks",
                                        key + strlen ("Table_locks_"),
                                        val, db);
                }
@@ -902,7 +884,7 @@ static int mysql_read (user_data_t *ud)
                        else if (strcmp (key, "Innodb_buffer_pool_pages_dirty") == 0)
                                gauge_submit ("mysql_bpool_pages", "dirty", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_pages_flushed") == 0)
-                               counter_submit ("mysql_bpool_counters", "pages_flushed", val, db);
+                               derive_submit ("mysql_bpool_counters", "pages_flushed", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_pages_free") == 0)
                                gauge_submit ("mysql_bpool_pages", "free", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_pages_misc") == 0)
@@ -910,19 +892,19 @@ static int mysql_read (user_data_t *ud)
                        else if (strcmp (key, "Innodb_buffer_pool_pages_total") == 0)
                                gauge_submit ("mysql_bpool_pages", "total", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_read_ahead_rnd") == 0)
-                               counter_submit ("mysql_bpool_counters", "read_ahead_rnd", val, db);
+                               derive_submit ("mysql_bpool_counters", "read_ahead_rnd", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_read_ahead") == 0)
-                               counter_submit ("mysql_bpool_counters", "read_ahead", val, db);
+                               derive_submit ("mysql_bpool_counters", "read_ahead", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_read_ahead_evicted") == 0)
-                               counter_submit ("mysql_bpool_counters", "read_ahead_evicted", val, db);
+                               derive_submit ("mysql_bpool_counters", "read_ahead_evicted", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_read_requests") == 0)
-                               counter_submit ("mysql_bpool_counters", "read_requests", val, db);
+                               derive_submit ("mysql_bpool_counters", "read_requests", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_reads") == 0)
-                               counter_submit ("mysql_bpool_counters", "reads", val, db);
+                               derive_submit ("mysql_bpool_counters", "reads", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_wait_free") == 0)
-                               counter_submit ("mysql_bpool_counters", "wait_free", val, db);
+                               derive_submit ("mysql_bpool_counters", "wait_free", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_write_requests") == 0)
-                               counter_submit ("mysql_bpool_counters", "write_requests", val, db);
+                               derive_submit ("mysql_bpool_counters", "write_requests", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_bytes_data") == 0)
                                gauge_submit ("mysql_bpool_bytes", "data", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_bytes_dirty") == 0)
@@ -930,80 +912,80 @@ static int mysql_read (user_data_t *ud)
 
                        /* data */
                        if (strcmp (key, "Innodb_data_fsyncs") == 0)
-                               counter_submit ("mysql_innodb_data", "fsyncs", val, db);
+                               derive_submit ("mysql_innodb_data", "fsyncs", val, db);
                        else if (strcmp (key, "Innodb_data_read") == 0)
-                               counter_submit ("mysql_innodb_data", "read", val, db);
+                               derive_submit ("mysql_innodb_data", "read", val, db);
                        else if (strcmp (key, "Innodb_data_reads") == 0)
-                               counter_submit ("mysql_innodb_data", "reads", val, db);
+                               derive_submit ("mysql_innodb_data", "reads", val, db);
                        else if (strcmp (key, "Innodb_data_writes") == 0)
-                               counter_submit ("mysql_innodb_data", "writes", val, db);
+                               derive_submit ("mysql_innodb_data", "writes", val, db);
                        else if (strcmp (key, "Innodb_data_written") == 0)
-                               counter_submit ("mysql_innodb_data", "written", val, db);
+                               derive_submit ("mysql_innodb_data", "written", val, db);
 
                        /* double write */
                        else if (strcmp (key, "Innodb_dblwr_writes") == 0)
-                               counter_submit ("mysql_innodb_dblwr", "writes", val, db);
+                               derive_submit ("mysql_innodb_dblwr", "writes", val, db);
                        else if (strcmp (key, "Innodb_dblwr_pages_written") == 0)
-                               counter_submit ("mysql_innodb_dblwr", "written", val, db);
+                               derive_submit ("mysql_innodb_dblwr", "written", val, db);
                        else if (strcmp (key, "Innodb_dblwr_page_size") == 0)
                                gauge_submit ("mysql_innodb_dblwr", "page_size", val, db);
 
                        /* log */
                        else if (strcmp (key, "Innodb_log_waits") == 0)
-                               counter_submit ("mysql_innodb_log", "waits", val, db);
+                               derive_submit ("mysql_innodb_log", "waits", val, db);
                        else if (strcmp (key, "Innodb_log_write_requests") == 0)
-                               counter_submit ("mysql_innodb_log", "write_requests", val, db);
+                               derive_submit ("mysql_innodb_log", "write_requests", val, db);
                        else if (strcmp (key, "Innodb_log_writes") == 0)
-                               counter_submit ("mysql_innodb_log", "writes", val, db);
+                               derive_submit ("mysql_innodb_log", "writes", val, db);
                        else if (strcmp (key, "Innodb_os_log_fsyncs") == 0)
-                               counter_submit ("mysql_innodb_log", "fsyncs", val, db);
+                               derive_submit ("mysql_innodb_log", "fsyncs", val, db);
                        else if (strcmp (key, "Innodb_os_log_written") == 0)
-                               counter_submit ("mysql_innodb_log", "written", val, db);
+                               derive_submit ("mysql_innodb_log", "written", val, db);
 
                        /* pages */
                        else if (strcmp (key, "Innodb_pages_created") == 0)
-                               counter_submit ("mysql_innodb_pages", "created", val, db);
+                               derive_submit ("mysql_innodb_pages", "created", val, db);
                        else if (strcmp (key, "Innodb_pages_read") == 0)
-                               counter_submit ("mysql_innodb_pages", "read", val, db);
+                               derive_submit ("mysql_innodb_pages", "read", val, db);
                        else if (strcmp (key, "Innodb_pages_written") == 0)
-                               counter_submit ("mysql_innodb_pages", "written", val, db);
+                               derive_submit ("mysql_innodb_pages", "written", val, db);
 
                        /* row lock */
                        else if (strcmp (key, "Innodb_row_lock_time") == 0)
-                               counter_submit ("mysql_innodb_row_lock", "time", val, db);
+                               derive_submit ("mysql_innodb_row_lock", "time", val, db);
                        else if (strcmp (key, "Innodb_row_lock_waits") == 0)
-                               counter_submit ("mysql_innodb_row_lock", "waits", val, db);
+                               derive_submit ("mysql_innodb_row_lock", "waits", val, db);
 
                        /* rows */
                        else if (strcmp (key, "Innodb_rows_deleted") == 0)
-                               counter_submit ("mysql_innodb_rows", "deleted", val, db);
+                               derive_submit ("mysql_innodb_rows", "deleted", val, db);
                        else if (strcmp (key, "Innodb_rows_inserted") == 0)
-                               counter_submit ("mysql_innodb_rows", "inserted", val, db);
+                               derive_submit ("mysql_innodb_rows", "inserted", val, db);
                        else if (strcmp (key, "Innodb_rows_read") == 0)
-                               counter_submit ("mysql_innodb_rows", "read", val, db);
+                               derive_submit ("mysql_innodb_rows", "read", val, db);
                        else if (strcmp (key, "Innodb_rows_updated") == 0)
-                               counter_submit ("mysql_innodb_rows", "updated", val, db);
+                               derive_submit ("mysql_innodb_rows", "updated", val, db);
                }
                else if (strncmp (key, "Select_", strlen ("Select_")) == 0)
                {
-                       counter_submit ("mysql_select", key + strlen ("Select_"),
+                       derive_submit ("mysql_select", key + strlen ("Select_"),
                                        val, db);
                }
                else if (strncmp (key, "Sort_", strlen ("Sort_")) == 0)
                {
                        if (strcmp (key, "Sort_merge_passes") == 0)
-                               counter_submit ("mysql_sort_merge_passes", NULL, val, db);
+                               derive_submit ("mysql_sort_merge_passes", NULL, val, db);
                        else if (strcmp (key, "Sort_rows") == 0)
-                               counter_submit ("mysql_sort_rows", NULL, val, db);
+                               derive_submit ("mysql_sort_rows", NULL, val, db);
                        else if (strcmp (key, "Sort_range") == 0)
-                               counter_submit ("mysql_sort", "range", val, db);
+                               derive_submit ("mysql_sort", "range", val, db);
                        else if (strcmp (key, "Sort_scan") == 0)
-                               counter_submit ("mysql_sort", "scan", val, db);
+                               derive_submit ("mysql_sort", "scan", val, db);
 
                }
                else if (strncmp (key, "Slow_queries", strlen ("Slow_queries")) == 0)
                {
-                       counter_submit ("mysql_slow_queries", NULL , val, db);
+                       derive_submit ("mysql_slow_queries", NULL , val, db);
                }
        }
        mysql_free_result (res); res = NULL;
index d739696..e83a475 100644 (file)
@@ -617,7 +617,7 @@ static data_volume_perf_t *get_volume_perf (cfg_volume_perf_t *cvp, /* {{{ */
 static int submit_values (const char *host, /* {{{ */
                const char *plugin_inst,
                const char *type, const char *type_inst,
-               value_t *values, int values_len,
+               value_t *values, size_t values_len,
                cdtime_t timestamp, cdtime_t interval)
 {
        value_list_t vl = VALUE_LIST_INIT;
@@ -649,50 +649,42 @@ static int submit_two_derive (const char *host, const char *plugin_inst, /* {{{
                const char *type, const char *type_inst, derive_t val0, derive_t val1,
                cdtime_t timestamp, cdtime_t interval)
 {
-       value_t values[2];
-
-       values[0].derive = val0;
-       values[1].derive = val1;
+       value_t values[] = {
+               { .derive = val0 },
+               { .derive = val1 },
+       };
 
        return (submit_values (host, plugin_inst, type, type_inst,
-                               values, 2, timestamp, interval));
+                               values, STATIC_ARRAY_SIZE (values), timestamp, interval));
 } /* }}} int submit_two_derive */
 
 static int submit_derive (const char *host, const char *plugin_inst, /* {{{ */
                const char *type, const char *type_inst, derive_t counter,
                cdtime_t timestamp, cdtime_t interval)
 {
-       value_t v;
-
-       v.derive = counter;
-
        return (submit_values (host, plugin_inst, type, type_inst,
-                               &v, 1, timestamp, interval));
+                               &(value_t) { .derive = counter }, 1, timestamp, interval));
 } /* }}} int submit_derive */
 
 static int submit_two_gauge (const char *host, const char *plugin_inst, /* {{{ */
                const char *type, const char *type_inst, gauge_t val0, gauge_t val1,
                cdtime_t timestamp, cdtime_t interval)
 {
-       value_t values[2];
-
-       values[0].gauge = val0;
-       values[1].gauge = val1;
+       value_t values[] = {
+               { .gauge = val0 },
+               { .gauge = val1 },
+       };
 
        return (submit_values (host, plugin_inst, type, type_inst,
-                               values, 2, timestamp, interval));
+                               values, STATIC_ARRAY_SIZE (values), timestamp, interval));
 } /* }}} int submit_two_gauge */
 
 static int submit_double (const char *host, const char *plugin_inst, /* {{{ */
                const char *type, const char *type_inst, double d,
                cdtime_t timestamp, cdtime_t interval)
 {
-       value_t v;
-
-       v.gauge = (gauge_t) d;
-
        return (submit_values (host, plugin_inst, type, type_inst,
-                               &v, 1, timestamp, interval));
+                               &(value_t) { .gauge = counter }, 1, timestamp, interval));
 } /* }}} int submit_uint64 */
 
 /* Calculate hit ratio from old and new counters and submit the resulting
@@ -707,7 +699,7 @@ static int submit_cache_ratio (const char *host, /* {{{ */
                cdtime_t timestamp,
                cdtime_t interval)
 {
-       value_t v;
+       value_t v = { .gauge = NAN };
 
        if ((new_hits >= old_hits) && (new_misses >= old_misses)) {
                uint64_t hits;
@@ -717,8 +709,6 @@ static int submit_cache_ratio (const char *host, /* {{{ */
                misses = new_misses - old_misses;
 
                v.gauge = 100.0 * ((gauge_t) hits) / ((gauge_t) (hits + misses));
-       } else {
-               v.gauge = NAN;
        }
 
        return (submit_values (host, plugin_inst, "cache_ratio", type_inst,
@@ -2879,15 +2869,13 @@ static int cna_register_host (host_config_t *host) /* {{{ */
        else
                ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
 
-       user_data_t ud = {
-               .data = host,
-               .free_func = (void (*) (void *)) free_host_config
-       };
-
        plugin_register_complex_read (/* group = */ NULL, cb_name,
                        /* callback  = */ cna_read,
                        /* interval  = */ host->interval,
-                       /* user data = */ &ud);
+                       &(user_data_t) {
+                               .data = host,
+                               .free_func = (void *) free_host_config,
+                       });
 
        return (0);
 } /* }}} int cna_register_host */
index cfca46f..786056d 100644 (file)
@@ -194,12 +194,9 @@ static int check_ignorelist (const char *dev,
 static void submit_one (const char *dev, const char *type,
     const char *type_instance, derive_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].derive = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .derive = value };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin));
@@ -216,14 +213,14 @@ static void submit_two (const char *dev, const char *type,
     const char *type_instance,
     derive_t rx, derive_t tx)
 {
-  value_t values[2];
   value_list_t vl = VALUE_LIST_INIT;
-
-  values[0].derive = rx;
-  values[1].derive = tx;
+  value_t values[] = {
+    { .derive = rx },
+    { .derive = tx },
+  };
 
   vl.values = values;
-  vl.values_len = 2;
+  vl.values_len = STATIC_ARRAY_SIZE (values);
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin));
   sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
index 16ce3d5..3850acc 100644 (file)
@@ -210,7 +210,7 @@ static void submit (const char *type, const char *inst, long long value)
     return;
 
   vl.values = values;
-  vl.values_len = 1;
+  vl.values_len = STATIC_ARRAY_SIZE (values);
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "nginx", sizeof (vl.plugin));
   sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
index 30f29c9..ccdecd9 100644 (file)
@@ -313,12 +313,9 @@ static int ntpd_config (const char *key, const char *value)
 
 static void ntpd_submit (const char *type, const char *type_inst, gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "ntpd", sizeof (vl.plugin));
index b5c6b41..29074c4 100644 (file)
--- a/src/nut.c
+++ b/src/nut.c
@@ -120,13 +120,10 @@ static int nut_config (const char *key, const char *value)
 static void nut_submit (nut_ups_t *ups, const char *type,
     const char *type_instance, gauge_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
-  vl.values_len = STATIC_ARRAY_SIZE (values);
+  vl.values = &(value_t) { .gauge = value };
+  vl.values_len = 1;
   sstrncpy (vl.host,
       (strcasecmp (ups->hostname, "localhost") == 0)
       ? hostname_g
index 899ad3e..3bf7128 100644 (file)
@@ -216,12 +216,9 @@ __attribute__ ((nonnull(2)))
 static void olsrd_submit (const char *plugin_instance, /* {{{ */
     const char *type, const char *type_instance, gauge_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
 
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
index 235eff8..0b4b6f5 100644 (file)
@@ -336,7 +336,6 @@ static int cow_load_config (const char *key, const char *value)
 static int cow_read_values (const char *path, const char *name,
     const ow_family_features_t *family_info)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
   int success = 0;
 
@@ -347,9 +346,6 @@ static int cow_read_values (const char *path, const char *name,
       return 0;
   }
 
-  vl.values = values;
-  vl.values_len = 1;
-
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "onewire", sizeof (vl.plugin));
   sstrncpy (vl.plugin_instance, name, sizeof (vl.plugin_instance));
@@ -359,6 +355,7 @@ static int cow_read_values (const char *path, const char *name,
     char *buffer;
     size_t buffer_size;
     int status;
+    char errbuf[1024];
 
     char file[4096];
     char *endptr;
@@ -373,14 +370,14 @@ static int cow_read_values (const char *path, const char *name,
     status = OW_get (file, &buffer, &buffer_size);
     if (status < 0)
     {
-      ERROR ("onewire plugin: OW_get (%s/%s) failed. status = %#x;",
-          path, family_info->features[i].filename, status);
+      ERROR ("onewire plugin: OW_get (%s/%s) failed. error = %s;",
+          path, family_info->features[i].filename, sstrerror(errno, errbuf, sizeof (errbuf)));
       return (-1);
     }
     DEBUG ("Read onewire device %s as %s", file, buffer);
 
     endptr = NULL;
-    values[0].gauge = strtod (buffer, &endptr);
+    gauge_t g = strtod (buffer, &endptr);
     if (endptr == NULL)
     {
       ERROR ("onewire plugin: Buffer is not a number: %s", buffer);
@@ -391,6 +388,9 @@ static int cow_read_values (const char *path, const char *name,
     sstrncpy (vl.type_instance, family_info->features[i].type_instance,
         sizeof (vl.type_instance));
 
+    vl.values = &(value_t) { .gauge = g };
+    vl.values_len = 1;
+
     plugin_dispatch_values (&vl);
     success++;
 
@@ -430,6 +430,7 @@ static int cow_read_bus (const char *path)
   char *buffer;
   size_t buffer_size;
   int status;
+  char errbuf[1024];
 
   char *buffer_ptr;
   char *dummy;
@@ -439,8 +440,8 @@ static int cow_read_bus (const char *path)
   status = OW_get (path, &buffer, &buffer_size);
   if (status < 0)
   {
-    ERROR ("onewire plugin: OW_get (%s) failed. status = %#x;",
-        path, status);
+    ERROR ("onewire plugin: OW_get (%s) failed. error = %s;",
+        path, sstrerror(errno, errbuf, sizeof (errbuf)));
     return (-1);
   }
   DEBUG ("onewire plugin: OW_get (%s) returned: %s",
@@ -493,20 +494,17 @@ static int cow_read_bus (const char *path)
 
 static int cow_simple_read (void)
 {
-  value_t      values[1];
   value_list_t vl = VALUE_LIST_INIT;
   char        *buffer;
   size_t       buffer_size;
   int          status;
+  char         errbuf[1024];
   char        *endptr;
   direct_access_element_t *traverse;
 
   /* traverse list and check entries */
   for (traverse = direct_list; traverse != NULL; traverse = traverse->next)
   {
-      vl.values = values;
-      vl.values_len = 1;
-
       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
       sstrncpy (vl.plugin, "onewire", sizeof (vl.plugin));
       sstrncpy (vl.plugin_instance, traverse->address, sizeof (vl.plugin_instance));
@@ -514,16 +512,15 @@ static int cow_simple_read (void)
       status = OW_get (traverse->path, &buffer, &buffer_size);
       if (status < 0)
       {
-          ERROR ("onewire plugin: OW_get (%s) failed. status = %#x;",
+          ERROR ("onewire plugin: OW_get (%s) failed. status = %s;",
                  traverse->path,
-                 status);
+                 sstrerror(errno, errbuf, sizeof (errbuf)));
           return (-1);
       }
       DEBUG ("onewire plugin: Read onewire device %s as %s", traverse->path, buffer);
 
-
       endptr = NULL;
-      values[0].gauge = strtod (buffer, &endptr);
+      gauge_t g = strtod (buffer, &endptr);
       if (endptr == NULL)
       {
           ERROR ("onewire plugin: Buffer is not a number: %s", buffer);
@@ -533,6 +530,9 @@ static int cow_simple_read (void)
       sstrncpy (vl.type, traverse->file, sizeof (vl.type));
       sstrncpy (vl.type_instance, "",   sizeof (""));
 
+      vl.values = &(value_t) { .gauge = g };
+      vl.values_len = 1;
+
       plugin_dispatch_values (&vl);
       free (buffer);
   } /* for (traverse) */
@@ -590,6 +590,7 @@ static int cow_shutdown (void)
 static int cow_init (void)
 {
   int status;
+  char errbuf[1024];
 
   if (device_g == NULL)
   {
@@ -601,7 +602,7 @@ static int cow_init (void)
   status = (int) OW_init (device_g);
   if (status != 0)
   {
-    ERROR ("onewire plugin: OW_init(%s) failed: %i.", device_g, status);
+    ERROR ("onewire plugin: OW_init(%s) failed: %s.", device_g, sstrerror(errno, errbuf, sizeof (errbuf)));
     return (1);
   }
 
index d424cb4..dd3226d 100644 (file)
@@ -192,17 +192,13 @@ static void cldap_submit_value (const char *type, const char *type_instance, /*
 static void cldap_submit_derive (const char *type, const char *type_instance, /* {{{ */
                derive_t d, cldap_t *st)
 {
-       value_t v;
-       v.derive = d;
-       cldap_submit_value (type, type_instance, v, st);
+       cldap_submit_value (type, type_instance, (value_t) { .derive = d }, st);
 } /* }}} void cldap_submit_derive */
 
 static void cldap_submit_gauge (const char *type, const char *type_instance, /* {{{ */
                gauge_t g, cldap_t *st)
 {
-       value_t v;
-       v.gauge = g;
-       cldap_submit_value (type, type_instance, v, st);
+       cldap_submit_value (type, type_instance, (value_t) { .gauge = g }, st);
 } /* }}} void cldap_submit_gauge */
 
 static int cldap_read_host (user_data_t *ud) /* {{{ */
@@ -663,15 +659,13 @@ static int cldap_config_add (oconfig_item_t *ci) /* {{{ */
                                        (st->host != NULL) ? st->host : hostname_g,
                                        (st->name != NULL) ? st->name : "default");
 
-                       user_data_t ud = {
-                               .data = st
-                       };
-
                        status = plugin_register_complex_read (/* group = */ NULL,
                                        /* name      = */ callback_name,
                                        /* callback  = */ cldap_read_host,
                                        /* interval  = */ 0,
-                                       /* user_data = */ &ud);
+                                       &(user_data_t) {
+                                               .data = st,
+                                       });
                }
        }
 
index 00ae736..81ffa89 100644 (file)
@@ -99,13 +99,10 @@ static int openvpn_strsplit (char *string, char **fields, size_t size)
 static void numusers_submit (const char *pinst, const char *tinst,
                gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
-       vl.values_len = STATIC_ARRAY_SIZE (values);
+       vl.values = &(value_t) { .gauge = value };
+       vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "openvpn", sizeof (vl.plugin));
        sstrncpy (vl.type, "users", sizeof (vl.type));
@@ -122,11 +119,11 @@ static void numusers_submit (const char *pinst, const char *tinst,
 static void iostats_submit (const char *pinst, const char *tinst,
                derive_t rx, derive_t tx)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = rx;
-       values[1].derive = tx;
+       value_t values[] = {
+    { .derive = rx },
+    { .derive = tx },
+  };
 
        /* NOTE ON THE NEW NAMING SCHEMA:
         *       using plugin_instance to identify each vpn config (and
@@ -152,11 +149,11 @@ static void iostats_submit (const char *pinst, const char *tinst,
 static void compression_submit (const char *pinst, const char *tinst,
                derive_t uncompressed, derive_t compressed)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = uncompressed;
-       values[1].derive = compressed;
+       value_t values[] = {
+    { .derive = uncompressed },
+    { .derive = compressed },
+  };
 
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
index 9eef6c1..4a11d6c 100644 (file)
@@ -22,6 +22,7 @@
  *
  * Authors:
  *   Sebastian Harl <sh at tokkee.org>
+ *   Pavel Rochnyak <pavel2000 ngs.ru>
  **/
 
 /*
@@ -77,8 +78,9 @@
 #define PLUGIN_LOG      4
 #define PLUGIN_NOTIF    5
 #define PLUGIN_FLUSH    6
+#define PLUGIN_FLUSH_ALL 7  /* For collectd-5.6 only */
 
-#define PLUGIN_TYPES    7
+#define PLUGIN_TYPES    8
 
 #define PLUGIN_CONFIG   254
 #define PLUGIN_DATASET  255
 /* this is defined in DynaLoader.a */
 void boot_DynaLoader (PerlInterpreter *, CV *);
 
+static XS (Collectd_plugin_register_read);
+static XS (Collectd_plugin_register_write);
+static XS (Collectd_plugin_register_log);
+static XS (Collectd_plugin_register_notification);
+static XS (Collectd_plugin_register_flush);
+static XS (Collectd_plugin_unregister_read);
+static XS (Collectd_plugin_unregister_write);
+static XS (Collectd_plugin_unregister_log);
+static XS (Collectd_plugin_unregister_notification);
+static XS (Collectd_plugin_unregister_flush);
 static XS (Collectd_plugin_register_ds);
 static XS (Collectd_plugin_unregister_ds);
 static XS (Collectd_plugin_dispatch_values);
@@ -113,6 +125,14 @@ static XS (Collectd_plugin_log);
 static XS (Collectd__fc_register);
 static XS (Collectd_call_by_name);
 
+static int perl_read (user_data_t *ud);
+static int perl_write (const data_set_t *ds, const value_list_t *vl,
+               user_data_t *user_data);
+static void perl_log (int level, const char *msg, user_data_t *user_data);
+static int perl_notify (const notification_t *notif, user_data_t *user_data);
+static int perl_flush (cdtime_t timeout, const char *identifier,
+               user_data_t *user_data);
+
 /*
  * private data types
  */
@@ -165,6 +185,8 @@ extern char **environ;
  * private variables
  */
 
+static _Bool register_legacy_flush = 1;
+
 /* if perl_threads != NULL perl_threads->head must
  * point to the "base" thread */
 static c_ithread_list_t *perl_threads = NULL;
@@ -182,6 +204,18 @@ static struct {
        XS ((*f));
 } api[] =
 {
+       { "Collectd::plugin_register_read",       Collectd_plugin_register_read },
+       { "Collectd::plugin_register_write",      Collectd_plugin_register_write },
+       { "Collectd::plugin_register_log",        Collectd_plugin_register_log },
+       { "Collectd::plugin_register_notification",
+               Collectd_plugin_register_notification },
+       { "Collectd::plugin_register_flush",       Collectd_plugin_register_flush },
+       { "Collectd::plugin_unregister_read",     Collectd_plugin_unregister_read },
+       { "Collectd::plugin_unregister_write",    Collectd_plugin_unregister_write },
+       { "Collectd::plugin_unregister_log",      Collectd_plugin_unregister_log },
+       { "Collectd::plugin_unregister_notification",
+               Collectd_plugin_unregister_notification },
+       { "Collectd::plugin_unregister_flush",    Collectd_plugin_unregister_flush },
        { "Collectd::plugin_register_data_set",   Collectd_plugin_register_ds },
        { "Collectd::plugin_unregister_data_set", Collectd_plugin_unregister_ds },
        { "Collectd::plugin_dispatch_values",     Collectd_plugin_dispatch_values },
@@ -1010,7 +1044,7 @@ static int call_pv_locked (pTHX_ const char* sub_name)
                return 0;
        }
 
-       ret = call_pv (sub_name, G_SCALAR);
+       ret = call_pv (sub_name, G_SCALAR|G_EVAL);
 
        t->running = old_running;
        return ret;
@@ -1019,12 +1053,13 @@ static int call_pv_locked (pTHX_ const char* sub_name)
 /*
  * Call all working functions of the given type.
  */
-static int pplugin_call_all (pTHX_ int type, ...)
+static int pplugin_call (pTHX_ int type, ...)
 {
        int retvals = 0;
 
        va_list ap;
        int ret = 0;
+       char *subname;
 
        dSP;
 
@@ -1038,9 +1073,17 @@ static int pplugin_call_all (pTHX_ int type, ...)
 
        PUSHMARK (SP);
 
-       XPUSHs (sv_2mortal (newSViv ((IV)type)));
+       if (PLUGIN_READ == type) {
+               subname = va_arg(ap, char *);
+       }
+       else if (PLUGIN_WRITE == type) {
+               data_set_t   *ds;
+               value_list_t *vl;
 
-       if (PLUGIN_WRITE == type) {
+               AV *pds = newAV ();
+               HV *pvl = newHV ();
+
+               subname = va_arg(ap, char *);
                /*
                 * $_[0] = $plugin_type;
                 *
@@ -1066,12 +1109,6 @@ static int pplugin_call_all (pTHX_ int type, ...)
                 *   type_instance   => $type_instance
                 * };
                 */
-               data_set_t   *ds;
-               value_list_t *vl;
-
-               AV *pds = newAV ();
-               HV *pvl = newHV ();
-
                ds = va_arg (ap, data_set_t *);
                vl = va_arg (ap, value_list_t *);
 
@@ -1094,6 +1131,7 @@ static int pplugin_call_all (pTHX_ int type, ...)
                XPUSHs (sv_2mortal (newRV_noinc ((SV *)pvl)));
        }
        else if (PLUGIN_LOG == type) {
+               subname = va_arg(ap, char *);
                /*
                 * $_[0] = $level;
                 *
@@ -1103,6 +1141,10 @@ static int pplugin_call_all (pTHX_ int type, ...)
                XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
        }
        else if (PLUGIN_NOTIF == type) {
+               notification_t *n;
+               HV *notif = newHV ();
+
+               subname = va_arg(ap, char *);
                /*
                 * $_[0] =
                 * {
@@ -1116,9 +1158,6 @@ static int pplugin_call_all (pTHX_ int type, ...)
                 *   type_instance   => $type_instance
                 * };
                 */
-               notification_t *n;
-               HV *notif = newHV ();
-
                n = va_arg (ap, notification_t *);
 
                if (-1 == notification2hv (aTHX_ n, notif)) {
@@ -1132,23 +1171,53 @@ static int pplugin_call_all (pTHX_ int type, ...)
        }
        else if (PLUGIN_FLUSH == type) {
                cdtime_t timeout;
+               subname = va_arg(ap, char *);
+               /*
+                * $_[0] = $timeout;
+                * $_[1] = $identifier;
+                */
+               timeout = va_arg (ap, cdtime_t);
 
+               XPUSHs (sv_2mortal (newSVnv (CDTIME_T_TO_DOUBLE (timeout))));
+               XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
+       }
+       else if (PLUGIN_FLUSH_ALL == type) {
+               cdtime_t timeout;
+               subname = "Collectd::plugin_call_all";
                /*
                 * $_[0] = $timeout;
                 * $_[1] = $identifier;
                 */
                timeout = va_arg (ap, cdtime_t);
 
+               XPUSHs (sv_2mortal (newSViv ((IV)PLUGIN_FLUSH)));
                XPUSHs (sv_2mortal (newSVnv (CDTIME_T_TO_DOUBLE (timeout))));
                XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
        }
+       else if (PLUGIN_INIT == type) {
+               subname = "Collectd::plugin_call_all";
+               XPUSHs (sv_2mortal (newSViv ((IV)type)));
+       }
+       else if (PLUGIN_SHUTDOWN == type) {
+               subname = "Collectd::plugin_call_all";
+               XPUSHs (sv_2mortal (newSViv ((IV)type)));
+       }
+       else { /* Unknown type. Run 'plugin_call_all' and make compiler happy */
+               subname = "Collectd::plugin_call_all";
+               XPUSHs (sv_2mortal (newSViv ((IV)type)));
+       }
 
        PUTBACK;
 
-       retvals = call_pv_locked (aTHX_ "Collectd::plugin_call_all");
+       retvals = call_pv_locked (aTHX_ subname);
 
        SPAGAIN;
-       if (0 < retvals) {
+       if (SvTRUE(ERRSV)) {
+               if (PLUGIN_LOG != type)
+                       ERROR ("perl: %s error: %s", subname, SvPV_nolen(ERRSV));
+               ret = -1;
+       }
+       else if (0 < retvals) {
                SV *tmp = POPs;
                if (! SvTRUE (tmp))
                        ret = -1;
@@ -1160,7 +1229,7 @@ static int pplugin_call_all (pTHX_ int type, ...)
 
        va_end (ap);
        return ret;
-} /* static int pplugin_call_all (int, ...) */
+} /* static int pplugin_call (int, ...) */
 
 /*
  * collectd's Perl interpreter based thread implementation.
@@ -1176,6 +1245,10 @@ static void c_ithread_destroy (c_ithread_t *ithread)
        assert (NULL != perl_threads);
 
        PERL_SET_CONTEXT (aTHX);
+       /* Mark as running to avoid deadlock:
+          c_ithread_destroy -> log_debug -> perl_log()
+       */
+       ithread->running = 1;
        log_debug ("Shutting down Perl interpreter %p...", aTHX);
 
 #if COLLECT_DEBUG
@@ -1399,7 +1472,11 @@ static int fc_call (pTHX_ int type, int cb_type, pfc_user_data_t *data, ...)
        }
 
        SPAGAIN;
-       if (0 < retvals) {
+       if (SvTRUE(ERRSV)) {
+               ERROR ("perl: Collectd::fc_call error: %s", SvPV_nolen(ERRSV));
+               ret = -1;
+       }
+       else if (0 < retvals) {
                SV *tmp = POPs;
 
                /* the exec callbacks return a status, while
@@ -1568,6 +1645,173 @@ static target_proc_t ptarget = {
  * Exported Perl API.
  */
 
+static void _plugin_register_generic_userdata (pTHX, int type, const char *desc)
+{
+       int ret   = 0;
+       user_data_t userdata;
+       char *pluginname;
+
+       dXSARGS;
+
+       if (2 != items) {
+               log_err ("Usage: Collectd::plugin_register_%s(pluginname, subname)",
+                                       desc);
+               XSRETURN_EMPTY;
+       }
+
+       if (! SvOK (ST (0))) {
+               log_err ("Collectd::plugin_register_%s(pluginname, subname): "
+                        "Invalid pluginname", desc);
+               XSRETURN_EMPTY;
+       }
+       if (! SvOK (ST (1))) {
+               log_err ("Collectd::plugin_register_%s(pluginname, subname): "
+                        "Invalid subname", desc);
+               XSRETURN_EMPTY;
+       }
+
+       /* Use pluginname as-is to allow flush a single perl plugin */
+       pluginname = SvPV_nolen (ST (0));
+
+       log_debug ("Collectd::plugin_register_%s: "
+                       "plugin = \"%s\", sub = \"%s\"",
+                       desc, pluginname, SvPV_nolen (ST (1)));
+
+       memset(&userdata, 0, sizeof(userdata));
+       userdata.data = strdup(SvPV_nolen (ST (1)));
+       userdata.free_func = free;
+
+       if (PLUGIN_READ == type) {
+               ret = plugin_register_complex_read(
+                       "perl",                /* group */
+                       pluginname,
+                       perl_read,
+                       plugin_get_interval(), /* Default interval */
+                       &userdata);
+       }
+       else if (PLUGIN_WRITE == type) {
+               ret = plugin_register_write(pluginname, perl_write, &userdata);
+       }
+       else if (PLUGIN_LOG == type) {
+               ret = plugin_register_log(pluginname, perl_log, &userdata);
+       }
+       else if (PLUGIN_NOTIF == type) {
+               ret = plugin_register_notification(pluginname, perl_notify, &userdata);
+       }
+       else if (PLUGIN_FLUSH == type) {
+               if (1 == register_legacy_flush) { /* For collectd-5.7 only, #1731 */
+                       register_legacy_flush = 0;
+                       ret = plugin_register_flush("perl", perl_flush, /* user_data = */ NULL);
+               }
+
+               if (0 == ret)
+                       ret = plugin_register_flush(pluginname, perl_flush, &userdata);
+       }
+       else {
+               ret = -1;
+       }
+
+       if (0 == ret)
+               XSRETURN_YES;
+       else {
+               free (userdata.data);
+               XSRETURN_EMPTY;
+       }
+} /* static void _plugin_register_generic_userdata ( ... ) */
+
+/*
+ * Collectd::plugin_register_TYPE (pluginname, subname).
+ *
+ * pluginname:
+ *   name of the perl plugin
+ *
+ * subname:
+ *   name of the plugin's subroutine that does the work
+ */
+
+static XS (Collectd_plugin_register_read) {
+       return _plugin_register_generic_userdata(aTHX, PLUGIN_READ, "read");
+}
+
+static XS (Collectd_plugin_register_write) {
+       return _plugin_register_generic_userdata(aTHX, PLUGIN_WRITE, "write");
+}
+
+static XS (Collectd_plugin_register_log) {
+       return _plugin_register_generic_userdata(aTHX, PLUGIN_LOG, "log");
+}
+
+static XS (Collectd_plugin_register_notification) {
+       return _plugin_register_generic_userdata(aTHX, PLUGIN_NOTIF, "notification");
+}
+
+static XS (Collectd_plugin_register_flush) {
+       return _plugin_register_generic_userdata(aTHX, PLUGIN_FLUSH, "flush");
+}
+
+typedef int perl_unregister_function_t(const char *name);
+
+static void _plugin_unregister_generic (pTHX,
+                               perl_unregister_function_t *unreg, const char *desc)
+{
+       dXSARGS;
+
+       if (1 != items) {
+               log_err ("Usage: Collectd::plugin_unregister_%s(pluginname)", desc);
+               XSRETURN_EMPTY;
+       }
+
+       if (! SvOK (ST (0))) {
+               log_err ("Collectd::plugin_unregister_%s(pluginname): "
+                        "Invalid pluginname", desc);
+               XSRETURN_EMPTY;
+       }
+
+       log_debug ("Collectd::plugin_unregister_%s: plugin = \"%s\"",
+                       desc, SvPV_nolen (ST (0)));
+
+       unreg(SvPV_nolen (ST (0)));
+
+       XSRETURN_EMPTY;
+
+       return;
+} /* static void _plugin_unregister_generic ( ... ) */
+
+/*
+ * Collectd::plugin_unregister_TYPE (pluginname).
+ *
+ * TYPE:
+ *   type of callback to be unregistered: read, write, log, notification, flush
+ *
+ * pluginname:
+ *   name of the perl plugin
+ */
+
+static XS (Collectd_plugin_unregister_read) {
+       return _plugin_unregister_generic(aTHX,
+                               plugin_unregister_read, "read");
+}
+
+static XS (Collectd_plugin_unregister_write) {
+       return _plugin_unregister_generic(aTHX,
+                               plugin_unregister_write, "write");
+}
+
+static XS (Collectd_plugin_unregister_log) {
+       return _plugin_unregister_generic(aTHX,
+                               plugin_unregister_log, "log");
+}
+
+static XS (Collectd_plugin_unregister_notification) {
+       return _plugin_unregister_generic(aTHX,
+                               plugin_unregister_notification, "notification");
+}
+
+static XS (Collectd_plugin_unregister_flush) {
+       return _plugin_unregister_generic(aTHX,
+                               plugin_unregister_flush, "flush");
+}
+
 /*
  * Collectd::plugin_register_data_set (type, dataset).
  *
@@ -1955,14 +2199,14 @@ static int perl_init (void)
        assert (aTHX == perl_threads->head->interp);
        pthread_mutex_lock (&perl_threads->mutex);
 
-       status = pplugin_call_all (aTHX_ PLUGIN_INIT);
+       status = pplugin_call (aTHX_ PLUGIN_INIT);
 
        pthread_mutex_unlock (&perl_threads->mutex);
 
        return status;
 } /* static int perl_init (void) */
 
-static int perl_read (void)
+static int perl_read (user_data_t *user_data)
 {
        dTHX;
 
@@ -1986,11 +2230,12 @@ static int perl_read (void)
 
        log_debug ("perl_read: c_ithread: interp = %p (active threads: %i)",
                        aTHX, perl_threads->number_of_threads);
-       return pplugin_call_all (aTHX_ PLUGIN_READ);
-} /* static int perl_read (void) */
+
+       return pplugin_call (aTHX_ PLUGIN_READ, user_data->data);
+} /* static int perl_read (user_data_t *user_data) */
 
 static int perl_write (const data_set_t *ds, const value_list_t *vl,
-               user_data_t __attribute__((unused)) *user_data)
+               user_data_t *user_data)
 {
        int status;
        dTHX;
@@ -2016,7 +2261,7 @@ static int perl_write (const data_set_t *ds, const value_list_t *vl,
 
        log_debug ("perl_write: c_ithread: interp = %p (active threads: %i)",
                        aTHX, perl_threads->number_of_threads);
-       status = pplugin_call_all (aTHX_ PLUGIN_WRITE, ds, vl);
+       status = pplugin_call (aTHX_ PLUGIN_WRITE, user_data->data, ds, vl);
 
        if (aTHX == perl_threads->head->interp)
                pthread_mutex_unlock (&perl_threads->mutex);
@@ -2025,7 +2270,7 @@ static int perl_write (const data_set_t *ds, const value_list_t *vl,
 } /* static int perl_write (const data_set_t *, const value_list_t *) */
 
 static void perl_log (int level, const char *msg,
-               user_data_t __attribute__((unused)) *user_data)
+               user_data_t *user_data)
 {
        dTHX;
 
@@ -2050,7 +2295,7 @@ static void perl_log (int level, const char *msg,
        if (aTHX == perl_threads->head->interp)
                pthread_mutex_lock (&perl_threads->mutex);
 
-       pplugin_call_all (aTHX_ PLUGIN_LOG, level, msg);
+       pplugin_call (aTHX_ PLUGIN_LOG, user_data->data, level, msg);
 
        if (aTHX == perl_threads->head->interp)
                pthread_mutex_unlock (&perl_threads->mutex);
@@ -2058,8 +2303,7 @@ static void perl_log (int level, const char *msg,
        return;
 } /* static void perl_log (int, const char *) */
 
-static int perl_notify (const notification_t *notif,
-               user_data_t __attribute__((unused)) *user_data)
+static int perl_notify (const notification_t *notif, user_data_t *user_data)
 {
        dTHX;
 
@@ -2075,11 +2319,11 @@ static int perl_notify (const notification_t *notif,
 
                aTHX = t->interp;
        }
-       return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif);
+       return pplugin_call (aTHX_ PLUGIN_NOTIF, user_data->data, notif);
 } /* static int perl_notify (const notification_t *) */
 
 static int perl_flush (cdtime_t timeout, const char *identifier,
-               user_data_t __attribute__((unused)) *user_data)
+               user_data_t *user_data)
 {
        dTHX;
 
@@ -2095,7 +2339,12 @@ static int perl_flush (cdtime_t timeout, const char *identifier,
 
                aTHX = t->interp;
        }
-       return pplugin_call_all (aTHX_ PLUGIN_FLUSH, timeout, identifier);
+
+       /* For collectd-5.6 only, #1731 */
+       if (user_data == NULL || user_data->data == NULL)
+               return pplugin_call (aTHX_ PLUGIN_FLUSH_ALL, timeout, identifier);
+
+       return pplugin_call (aTHX_ PLUGIN_FLUSH, user_data->data, timeout, identifier);
 } /* static int perl_flush (const int) */
 
 static int perl_shutdown (void)
@@ -2106,6 +2355,7 @@ static int perl_shutdown (void)
        dTHX;
 
        plugin_unregister_complex_config ("perl");
+       plugin_unregister_read_group ("perl");
 
        if (NULL == perl_threads)
                return 0;
@@ -2121,14 +2371,10 @@ static int perl_shutdown (void)
        log_debug ("perl_shutdown: c_ithread: interp = %p (active threads: %i)",
                        aTHX, perl_threads->number_of_threads);
 
-       plugin_unregister_log ("perl");
-       plugin_unregister_notification ("perl");
        plugin_unregister_init ("perl");
-       plugin_unregister_read ("perl");
-       plugin_unregister_write ("perl");
-       plugin_unregister_flush ("perl");
+       plugin_unregister_flush ("perl"); /* For collectd-5.6 only, #1731 */
 
-       ret = pplugin_call_all (aTHX_ PLUGIN_SHUTDOWN);
+       ret = pplugin_call (aTHX_ PLUGIN_SHUTDOWN);
 
        pthread_mutex_lock (&perl_threads->mutex);
        t = perl_threads->tail;
@@ -2338,15 +2584,7 @@ static int init_pi (int argc, char **argv)
 
        perl_run (aTHX);
 
-       plugin_register_log ("perl", perl_log, /* user_data = */ NULL);
-       plugin_register_notification ("perl", perl_notify,
-                       /* user_data = */ NULL);
        plugin_register_init ("perl", perl_init);
-
-       plugin_register_read ("perl", perl_read);
-
-       plugin_register_write ("perl", perl_write, /* user_data = */ NULL);
-       plugin_register_flush ("perl", perl_flush, /* user_data = */ NULL);
        plugin_register_shutdown ("perl", perl_shutdown);
        return 0;
 } /* static int init_pi (const char **, const int) */
@@ -2568,6 +2806,8 @@ static int perl_config (oconfig_item_t *ci)
                        current_status = perl_config_includedir (aTHX_ c);
                else if (0 == strcasecmp (c->key, "Plugin"))
                        current_status = perl_config_plugin (aTHX_ c);
+               else if (0 == strcasecmp (c->key, "RegisterLegacyFlush"))
+                       cf_util_get_boolean (c, &register_legacy_flush);
                else
                {
                        log_warn ("Ignoring unknown config key \"%s\".", c->key);
index 8a0902a..76b765b 100644 (file)
@@ -677,38 +677,36 @@ static int plugin_shutdown (void) /* {{{ */
 
 static int plugin_submit (const pinba_statnode_t *res) /* {{{ */
 {
-  value_t value;
   value_list_t vl = VALUE_LIST_INIT;
 
-  vl.values = &value;
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "pinba", sizeof (vl.plugin));
   sstrncpy (vl.plugin_instance, res->name, sizeof (vl.plugin_instance));
 
-  value.derive = res->req_count;
+  vl.values = &(value_t) { .derive = res->req_count };
   sstrncpy (vl.type, "total_requests", sizeof (vl.type));
   plugin_dispatch_values (&vl);
 
-  value.derive = float_counter_get (&res->req_time, /* factor = */ 1000);
+  vl.values = &(value_t) { .derive = float_counter_get (&res->req_time, /* factor = */ 1000) };
   sstrncpy (vl.type, "total_time_in_ms", sizeof (vl.type));
   plugin_dispatch_values (&vl);
 
-  value.derive = res->doc_size;
+  vl.values = &(value_t) { .derive = res->doc_size };
   sstrncpy (vl.type, "total_bytes", sizeof (vl.type));
   plugin_dispatch_values (&vl);
 
-  value.derive = float_counter_get (&res->ru_utime, /* factor = */ 100);
+  vl.values = &(value_t) { .derive = float_counter_get (&res->ru_utime, /* factor = */ 100) };
   sstrncpy (vl.type, "cpu", sizeof (vl.type));
   sstrncpy (vl.type_instance, "user", sizeof (vl.type_instance));
   plugin_dispatch_values (&vl);
 
-  value.derive = float_counter_get (&res->ru_stime, /* factor = */ 100);
+  vl.values = &(value_t) { .derive = float_counter_get (&res->ru_stime, /* factor = */ 100) };
   sstrncpy (vl.type, "cpu", sizeof (vl.type));
   sstrncpy (vl.type_instance, "system", sizeof (vl.type_instance));
   plugin_dispatch_values (&vl);
 
-  value.gauge = res->mem_peak;
+  vl.values = &(value_t) { .gauge = res->mem_peak };
   sstrncpy (vl.type, "memory", sizeof (vl.type));
   sstrncpy (vl.type_instance, "peak", sizeof (vl.type_instance));
   plugin_dispatch_values (&vl);
index 5f66aab..39e9de5 100644 (file)
@@ -615,12 +615,9 @@ static int ping_config (const char *key, const char *value) /* {{{ */
 static void submit (const char *host, const char *type, /* {{{ */
     gauge_t value)
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].gauge = value;
-
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = value };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "ping", sizeof (vl.plugin));
index f907d00..eb54180 100644 (file)
@@ -300,10 +300,10 @@ static char *local_sockpath = NULL;
 
 /* <https://doc.powerdns.com/md/recursor/stats/> */
 static void submit (const char *plugin_instance, /* {{{ */
-    const char *pdns_type, const char *value)
+    const char *pdns_type, const char *value_str)
 {
   value_list_t vl = VALUE_LIST_INIT;
-  value_t values[1];
+  value_t value;
 
   const char *type = NULL;
   const char *type_instance = NULL;
@@ -318,7 +318,7 @@ static void submit (const char *plugin_instance, /* {{{ */
   if (i >= lookup_table_length)
   {
     INFO ("powerdns plugin: submit: Not found in lookup table: %s = %s;",
-        pdns_type, value);
+        pdns_type, value_str);
     return;
   }
 
@@ -345,14 +345,14 @@ static void submit (const char *plugin_instance, /* {{{ */
     return;
   }
 
-  if (0 != parse_value (value, &values[0], ds->ds[0].type))
+  if (0 != parse_value (value_str, &value, ds->ds[0].type))
   {
     ERROR ("powerdns plugin: Cannot convert `%s' "
-        "to a number.", value);
+        "to a number.", value_str);
     return;
   }
 
-  vl.values = values;
+  vl.values = &value;
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "powerdns", sizeof (vl.plugin));
index 0513a15..f470c84 100644 (file)
@@ -660,12 +660,9 @@ static int ps_init (void)
 /* submit global state (e.g.: qty of zombies, running, etc..) */
 static void ps_submit_state (const char *state, double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
@@ -679,11 +676,10 @@ static void ps_submit_state (const char *state, double value)
 /* submit info about specific process (e.g.: memory taken, cpu usage, etc..) */
 static void ps_submit_proc_list (procstat_t *ps)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
+       value_t values[2];
 
        vl.values = values;
-       vl.values_len = 2;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
@@ -784,12 +780,9 @@ static void ps_submit_proc_list (procstat_t *ps)
 #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 = &(value_t) { .derive = value };
        vl.values_len = 1;
        sstrncpy(vl.host, hostname_g, sizeof (vl.host));
        sstrncpy(vl.plugin, "processes", sizeof (vl.plugin));
index 208da8b..ae35c42 100644 (file)
@@ -55,11 +55,11 @@ static ignorelist_t *values_list = NULL;
 static void submit (const char *protocol_name,
     const char *str_key, const char *str_value)
 {
-  value_t values[1];
+  value_t value;
   value_list_t vl = VALUE_LIST_INIT;
   int status;
 
-  status = parse_value (str_value, values, DS_TYPE_DERIVE);
+  status = parse_value (str_value, &value, DS_TYPE_DERIVE);
   if (status != 0)
   {
     ERROR ("protocols plugin: Parsing string as integer failed: %s",
@@ -67,7 +67,7 @@ static void submit (const char *protocol_name,
     return;
   }
 
-  vl.values = values;
+  vl.values = &value;
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "protocols", sizeof (vl.plugin));
index ec2317b..5274262 100644 (file)
@@ -665,12 +665,11 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObjec
        c->data = data;
        c->next = NULL;
 
-       user_data_t user_data = {
-               .data = c,
-               .free_func = cpy_destroy_user_data
-       };
+       register_function(buf, handler, &(user_data_t) {
+                               .data = c,
+                               .free_func = cpy_destroy_user_data,
+                       });
 
-       register_function(buf, handler, &user_data);
        ++cpy_num_callbacks;
        return cpy_string_to_unicode_or_bytes(buf);
 }
@@ -704,13 +703,12 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd
        c->data = data;
        c->next = NULL;
 
-       user_data_t user_data = {
-               .data = c,
-               .free_func = cpy_destroy_user_data
-       };
-
        plugin_register_complex_read(/* group = */ "python", buf,
-                       cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
+                       cpy_read_callback, DOUBLE_TO_CDTIME_T (interval),
+                       &(user_data_t) {
+                               .data = c,
+                               .free_func = cpy_destroy_user_data,
+                       });
        ++cpy_num_callbacks;
        return cpy_string_to_unicode_or_bytes(buf);
 }
index 5214ecc..7f57571 100644 (file)
@@ -252,12 +252,9 @@ static void redis_submit (char *plugin_instance,
     const char *type, const char *type_instance,
     value_t value) /* {{{ */
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0] = value;
-
-  vl.values = values;
+  vl.values = &value;
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "redis", sizeof (vl.plugin));
index a270f48..5e8a294 100644 (file)
@@ -52,11 +52,11 @@ typedef struct cr_data_s cr_data_t;
 static void cr_submit_io (cr_data_t *rd, const char *type, /* {{{ */
     const char *type_instance, derive_t rx, derive_t tx)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = rx;
-       values[1].derive = tx;
+       value_t values[] = {
+         { .derive = rx },
+         { .derive = tx },
+       };
 
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
@@ -325,7 +325,6 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */
 {
   cr_data_t *router_data;
   char read_name[128];
-  user_data_t user_data;
   int status;
 
   router_data = calloc (1, sizeof (*router_data));
@@ -409,11 +408,12 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */
   }
 
   ssnprintf (read_name, sizeof (read_name), "routeros/%s", router_data->node);
-  user_data.data = router_data;
-  user_data.free_func = (void *) cr_free_data;
   if (status == 0)
     status = plugin_register_complex_read (/* group = */ NULL, read_name,
-       cr_read, /* interval = */ 0, &user_data);
+        cr_read, /* interval = */ 0, &(user_data_t) {
+          .data = router_data,
+          .free_func = (void *) cr_free_data,
+        });
 
   if (status != 0)
     cr_free_data (router_data);
index 0425419..07eac7b 100644 (file)
@@ -292,8 +292,9 @@ static int rc_read (void)
   int status;
   rrdc_stats_t *head;
 
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
+  vl.values = &(value_t) { .gauge = NAN };
+  vl.values_len = 1;
 
   if (daemon_address == NULL)
     return (-1);
@@ -301,9 +302,6 @@ static int rc_read (void)
   if (!config_collect_stats)
     return (-1);
 
-  vl.values = values;
-  vl.values_len = 1;
-
   if ((strncmp ("unix:", daemon_address, strlen ("unix:")) == 0)
       || (daemon_address[0] == '/'))
     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -330,9 +328,9 @@ static int rc_read (void)
   for (rrdc_stats_t *ptr = head; ptr != NULL; ptr = ptr->next)
   {
     if (ptr->type == RRDC_STATS_TYPE_GAUGE)
-      values[0].gauge = (gauge_t) ptr->value.gauge;
+      vl.values[0].gauge = (gauge_t) ptr->value.gauge;
     else if (ptr->type == RRDC_STATS_TYPE_COUNTER)
-      values[0].counter = (counter_t) ptr->value.counter;
+      vl.values[0].counter = (counter_t) ptr->value.counter;
     else
       continue;
 
index 4f3d0d6..f13b3ea 100644 (file)
@@ -481,12 +481,11 @@ static int sensors_shutdown (void)
 
 static void sensors_submit (const char *plugin_instance,
                const char *type, const char *type_instance,
-               double val)
+               double value)
 {
        char match_key[1024];
        int status;
 
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
        status = ssnprintf (match_key, sizeof (match_key), "%s/%s-%s",
@@ -501,9 +500,7 @@ static void sensors_submit (const char *plugin_instance,
                        return;
        }
 
-       values[0].gauge = val;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
 
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
index cf7ad2a..4822320 100644 (file)
 static void serial_submit (const char *type_instance,
                derive_t rx, derive_t tx)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = rx;
-       values[1].derive = tx;
+       value_t values[] = {
+               { .derive = rx },
+               { .derive = tx },
+       };
 
        vl.values = values;
-       vl.values_len = 2;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "serial", sizeof (vl.plugin));
        sstrncpy (vl.type, "serial_octets", sizeof (vl.type));
index 4006455..5b85004 100644 (file)
@@ -161,7 +161,6 @@ static void sigrok_feed_callback(const struct sr_dev_inst *sdi,
 {
        const struct sr_datafeed_analog *analog;
        struct config_device *cfdev;
-       value_t value;
        value_list_t vl = VALUE_LIST_INIT;
 
        /* Find this device's configuration. */
@@ -199,8 +198,7 @@ static void sigrok_feed_callback(const struct sr_dev_inst *sdi,
 
        /* Ignore all but the first sample on the first probe. */
        analog = packet->payload;
-       value.gauge = analog->data[0];
-       vl.values = &value;
+       vl.values = &(value_t) { .gauge = analog->data[0] };
        vl.values_len = 1;
        sstrncpy(vl.host, hostname_g, sizeof(vl.host));
        sstrncpy(vl.plugin, "sigrok", sizeof(vl.plugin));
index 752cb74..52e78a1 100644 (file)
@@ -86,12 +86,9 @@ static int smart_config (const char *key, const char *value)
 static void smart_submit (const char *dev, const char *type,
                const char *type_inst, double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "smart", sizeof (vl.plugin));
@@ -106,17 +103,20 @@ static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedD
                                         void* userdata)
 {
   const char *dev = userdata;
-  value_t values[4];
-  value_list_t vl = VALUE_LIST_INIT;
 
-  if (!a->current_value_valid || !a->worst_value_valid) return;
-  values[0].gauge = a->current_value;
-  values[1].gauge = a->worst_value;
-  values[2].gauge = a->threshold_valid?a->threshold:0;
-  values[3].gauge = a->pretty_value;
+  if (!a->current_value_valid || !a->worst_value_valid)
+    return;
+
+  value_list_t vl = VALUE_LIST_INIT;
+  value_t values[] = {
+    { .gauge = a->current_value },
+    { .gauge = a->worst_value },
+    { .gauge = a->threshold_valid ? a->threshold : 0 },
+    { .gauge = a->pretty_value },
+  };
 
   vl.values = values;
-  vl.values_len = 4;
+  vl.values_len = STATIC_ARRAY_SIZE (values);
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "smart", sizeof (vl.plugin));
   sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
index abeda43..d80ee92 100644 (file)
@@ -764,13 +764,11 @@ static int csnmp_config_add_host (oconfig_item_t *ci)
 
   ssnprintf (cb_name, sizeof (cb_name), "snmp-%s", hd->name);
 
-  user_data_t ud = {
-    .data = hd,
-    .free_func = csnmp_host_definition_destroy
-  };
-
   status = plugin_register_complex_read (/* group = */ NULL, cb_name,
-      csnmp_read_host, hd->interval, /* user_data = */ &ud);
+      csnmp_read_host, hd->interval, &(user_data_t) {
+        .data = hd,
+        .free_func = csnmp_host_definition_destroy,
+      });
   if (status != 0)
   {
     ERROR ("snmp plugin: Registering complex read function failed.");
index 9c138f9..82ae387 100644 (file)
@@ -752,10 +752,9 @@ static int statsd_metric_clear_set_unsafe (statsd_metric_t *metric) /* {{{ */
 /* Must hold metrics_lock when calling this function. */
 static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metric) /* {{{ */
 {
-  value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  vl.values = values;
+  vl.values = &(value_t) { .gauge = NAN };
   vl.values_len = 1;
   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
   sstrncpy (vl.plugin, "statsd", sizeof (vl.plugin));
@@ -772,7 +771,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
   sstrncpy (vl.type_instance, name, sizeof (vl.type_instance));
 
   if (metric->type == STATSD_GAUGE)
-    values[0].gauge = (gauge_t) metric->value;
+    vl.values[0].gauge = (gauge_t) metric->value;
   else if (metric->type == STATSD_TIMER)
   {
     _Bool have_events = (metric->updates_num > 0);
@@ -782,7 +781,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
 
     ssnprintf (vl.type_instance, sizeof (vl.type_instance),
         "%s-average", name);
-    values[0].gauge = have_events
+    vl.values[0].gauge = have_events
       ? CDTIME_T_TO_DOUBLE (latency_counter_get_average (metric->latency))
       : NAN;
     plugin_dispatch_values (&vl);
@@ -790,7 +789,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
     if (conf_timer_lower) {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-lower", name);
-      values[0].gauge = have_events
+      vl.values[0].gauge = have_events
         ? CDTIME_T_TO_DOUBLE (latency_counter_get_min (metric->latency))
         : NAN;
       plugin_dispatch_values (&vl);
@@ -799,7 +798,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
     if (conf_timer_upper) {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-upper", name);
-      values[0].gauge = have_events
+      vl.values[0].gauge = have_events
         ? CDTIME_T_TO_DOUBLE (latency_counter_get_max (metric->latency))
         : NAN;
       plugin_dispatch_values (&vl);
@@ -808,7 +807,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
     if (conf_timer_sum) {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-sum", name);
-      values[0].gauge = have_events
+      vl.values[0].gauge = have_events
         ? CDTIME_T_TO_DOUBLE (latency_counter_get_sum (metric->latency))
         : NAN;
       plugin_dispatch_values (&vl);
@@ -818,7 +817,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
     {
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-percentile-%.0f", name, conf_timer_percentile[i]);
-      values[0].gauge = have_events
+      vl.values[0].gauge = have_events
         ? CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (metric->latency, conf_timer_percentile[i]))
         : NAN;
       plugin_dispatch_values (&vl);
@@ -830,7 +829,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
       sstrncpy (vl.type, "gauge", sizeof (vl.type));
       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
           "%s-count", name);
-      values[0].gauge = latency_counter_get_num (metric->latency);
+      vl.values[0].gauge = latency_counter_get_num (metric->latency);
       plugin_dispatch_values (&vl);
     }
 
@@ -840,9 +839,9 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
   else if (metric->type == STATSD_SET)
   {
     if (metric->set == NULL)
-      values[0].gauge = 0.0;
+      vl.values[0].gauge = 0.0;
     else
-      values[0].gauge = (gauge_t) c_avl_size (metric->set);
+      vl.values[0].gauge = (gauge_t) c_avl_size (metric->set);
   }
   else { /* STATSD_COUNTER */
     gauge_t delta = nearbyint (metric->value);
@@ -854,7 +853,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
     if (conf_counter_sum)
     {
       sstrncpy (vl.type, "count", sizeof (vl.type));
-      values[0].gauge = delta;
+      vl.values[0].gauge = delta;
       plugin_dispatch_values (&vl);
 
       /* restore vl.type */
@@ -866,7 +865,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri
     metric->value   -= delta;
     metric->counter += (derive_t) delta;
 
-    values[0].derive = metric->counter;
+    vl.values[0].derive = metric->counter;
   }
 
   return (plugin_dispatch_values (&vl));
index 9c63e9b..3cc9516 100644 (file)
@@ -194,11 +194,10 @@ 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;
 
-       vl.values = v;
-       vl.values_len = STATIC_ARRAY_SIZE (v);
+       vl.values = &(value_t) { .gauge = NAN };
+       vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
        if (plugin_instance != NULL)
@@ -222,12 +221,9 @@ static void swap_submit_derive (char const *type_instance, /* {{{ */
                derive_t value)
 {
        value_list_t vl = VALUE_LIST_INIT;
-       value_t v[1];
 
-       v[0].derive = value;
-
-       vl.values = v;
-       vl.values_len = STATIC_ARRAY_SIZE (v);
+       vl.values = &(value_t) { .derive = value };
+       vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
        sstrncpy (vl.type, "swap_io", sizeof (vl.type));
index e8cde1e..74fdf84 100644 (file)
@@ -339,11 +339,10 @@ static int ctail_init (void)
   {
     ssnprintf(str, sizeof(str), "tail-%zu", i);
 
-    user_data_t ud = {
-     .data = tail_match_list[i]
-    };
-
-    plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], &ud);
+    plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i],
+        &(user_data_t) {
+          .data = tail_match_list[i],
+        });
   }
 
   return (0);
index 1bdf8b2..faeb56f 100644 (file)
@@ -482,13 +482,11 @@ static int tcsv_config_add_file(oconfig_item_t *ci)
 
     ssnprintf (cb_name, sizeof (cb_name), "tail_csv/%s", id->path);
 
-    user_data_t ud = {
-        .data = id,
-        .free_func = tcsv_instance_definition_destroy
-    };
-
-    status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &ud);
-
+    status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval,
+            &(user_data_t) {
+                .data = id,
+                .free_func = tcsv_instance_definition_destroy,
+            });
     if (status != 0){
         ERROR("tail_csv plugin: Registering complex read function failed.");
         tcsv_instance_definition_destroy(id);
index 52da2bc..8ec9bf2 100644 (file)
@@ -61,14 +61,14 @@ static void tape_submit (const char *plugin_instance,
                const char *type,
                derive_t read, derive_t write)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = read;
-       values[1].derive = write;
+       value_t values[] = {
+               { .derive = read },
+               { .derive = write },
+       };
 
        vl.values = values;
-       vl.values_len = 2;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "tape", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, plugin_instance,
index 40a6fec..dba3a8c 100644 (file)
@@ -38,11 +38,22 @@ struct tr_action_s
 {
   regex_t re;
   char *replacement;
-  int may_be_empty;
+  _Bool may_be_empty;
 
   tr_action_t *next;
 };
 
+struct tr_meta_data_action_s;
+typedef struct tr_meta_data_action_s tr_meta_data_action_t;
+struct tr_meta_data_action_s
+{
+  char *key;
+  regex_t re;
+  char *replacement;
+
+  tr_meta_data_action_t *next;
+};
+
 struct tr_data_s
 {
   tr_action_t *host;
@@ -50,6 +61,7 @@ struct tr_data_s
   tr_action_t *plugin_instance;
   /* tr_action_t *type; */
   tr_action_t *type_instance;
+  tr_meta_data_action_t *meta;
 };
 typedef struct tr_data_s tr_data_t;
 
@@ -85,8 +97,23 @@ static void tr_action_destroy (tr_action_t *act) /* {{{ */
   sfree (act);
 } /* }}} void tr_action_destroy */
 
+static void tr_meta_data_action_destroy (tr_meta_data_action_t *act) /* {{{ */
+{
+  if (act == NULL)
+    return;
+
+  sfree (act->key);
+  regfree (&act->re);
+  sfree (act->replacement);
+
+  if (act->next != NULL)
+    tr_meta_data_action_destroy (act->next);
+
+  sfree (act);
+} /* }}} void tr_meta_data_action_destroy */
+
 static int tr_config_add_action (tr_action_t **dest, /* {{{ */
-    const oconfig_item_t *ci, int may_be_empty)
+    const oconfig_item_t *ci, _Bool may_be_empty)
 {
   tr_action_t *act;
   int status;
@@ -131,8 +158,7 @@ static int tr_config_add_action (tr_action_t **dest, /* {{{ */
   if (act->replacement == NULL)
   {
     ERROR ("tr_config_add_action: tr_strdup failed.");
-    regfree (&act->re);
-    sfree (act);
+    tr_action_destroy (act);
     return (-ENOMEM);
   }
 
@@ -153,8 +179,108 @@ static int tr_config_add_action (tr_action_t **dest, /* {{{ */
   return (0);
 } /* }}} int tr_config_add_action */
 
+static int tr_config_add_meta_action (tr_meta_data_action_t **dest, /* {{{ */
+    const oconfig_item_t *ci, _Bool should_delete)
+{
+  tr_meta_data_action_t *act;
+  int status;
+
+  if (dest == NULL)
+    return (-EINVAL);
+
+  if (should_delete)
+  {
+    if ((ci->values_num != 2)
+        || (ci->values[0].type != OCONFIG_TYPE_STRING)
+        || (ci->values[1].type != OCONFIG_TYPE_STRING))
+    {
+      ERROR ("Target `replace': The `%s' option requires exactly two string "
+          "arguments.", ci->key);
+      return (-1);
+    }
+  }
+  else
+  {
+    if ((ci->values_num != 3)
+        || (ci->values[0].type != OCONFIG_TYPE_STRING)
+        || (ci->values[1].type != OCONFIG_TYPE_STRING)
+        || (ci->values[2].type != OCONFIG_TYPE_STRING))
+    {
+      ERROR ("Target `replace': The `%s' option requires exactly three string "
+          "arguments.", ci->key);
+      return (-1);
+    }
+  }
+
+  if (strlen (ci->values[0].value.string) == 0)
+  {
+    ERROR ("Target `replace': The `%s' option does not accept empty string as "
+        "first argument.", ci->key);
+    return (-1);
+  }
+
+  act = calloc (1, sizeof (*act));
+  if (act == NULL)
+  {
+    ERROR ("tr_config_add_meta_action: calloc failed.");
+    return (-ENOMEM);
+  }
+
+  act->key = NULL;
+  act->replacement = NULL;
+
+  status = regcomp (&act->re, ci->values[1].value.string, REG_EXTENDED);
+  if (status != 0)
+  {
+    char errbuf[1024] = "";
+
+    /* regerror assures null termination. */
+    regerror (status, &act->re, errbuf, sizeof (errbuf));
+    ERROR ("Target `replace': Compiling the regular expression `%s' "
+        "failed: %s.",
+        ci->values[1].value.string, errbuf);
+    sfree (act->key);
+    sfree (act);
+    return (-EINVAL);
+  }
+
+  act->key = tr_strdup (ci->values[0].value.string);
+  if (act->key == NULL)
+  {
+    ERROR ("tr_config_add_meta_action: tr_strdup failed.");
+    tr_meta_data_action_destroy (act);
+    return (-ENOMEM);
+  }
+
+  if (!should_delete) {
+    act->replacement = tr_strdup (ci->values[2].value.string);
+    if (act->replacement == NULL)
+    {
+      ERROR ("tr_config_add_meta_action: tr_strdup failed.");
+      tr_meta_data_action_destroy (act);
+      return (-ENOMEM);
+    }
+  }
+
+  /* Insert action at end of list. */
+  if (*dest == NULL)
+    *dest = act;
+  else
+  {
+    tr_meta_data_action_t *prev;
+
+    prev = *dest;
+    while (prev->next != NULL)
+      prev = prev->next;
+
+    prev->next = act;
+  }
+
+  return (0);
+} /* }}} int tr_config_add_meta_action */
+
 static int tr_action_invoke (tr_action_t *act_head, /* {{{ */
-    char *buffer_in, size_t buffer_in_size, int may_be_empty)
+    char *buffer_in, size_t buffer_in_size, _Bool may_be_empty)
 {
   int status;
   char buffer[DATA_MAX_NAME_LEN];
@@ -215,6 +341,119 @@ static int tr_action_invoke (tr_action_t *act_head, /* {{{ */
   return (0);
 } /* }}} int tr_action_invoke */
 
+static int tr_meta_data_action_invoke ( /* {{{ */
+    tr_meta_data_action_t *act_head, meta_data_t **dest)
+{
+  int status;
+  regmatch_t matches[8] = { [0] = { 0 } };
+
+  if (act_head == NULL)
+    return (-EINVAL);
+
+  if ((*dest) == NULL)  /* nothing to do */
+    return (0);
+
+  for (tr_meta_data_action_t *act = act_head; act != NULL; act = act->next)
+  {
+    char temp[DATA_MAX_NAME_LEN];
+    char *subst_status;
+    int value_type;
+    int meta_data_status;
+    char *value;
+    meta_data_t *result;
+
+    value_type = meta_data_type (*dest, act->key);
+    if (value_type == 0)  /* not found */
+      continue;
+    if (value_type != MD_TYPE_STRING)
+    {
+      WARNING ("Target `replace': Attempting replace on metadata key `%s', "
+          "which isn't a string.",
+          act->key);
+      continue;
+    }
+
+    meta_data_status = meta_data_get_string (*dest, act->key, &value);
+    if (meta_data_status != 0)
+    {
+      ERROR ("Target `replace': Unable to retrieve metadata value for `%s'.",
+          act->key);
+      return (meta_data_status);
+    }
+
+    DEBUG ("target_replace plugin: tr_meta_data_action_invoke: `%s' "
+        "old value = `%s'", act->key, value);
+
+    status = regexec (&act->re, value,
+        STATIC_ARRAY_SIZE (matches), matches,
+        /* flags = */ 0);
+    if (status == REG_NOMATCH)
+    {
+      sfree (value);
+      continue;
+    }
+    else if (status != 0)
+    {
+      char errbuf[1024] = "";
+
+      regerror (status, &act->re, errbuf, sizeof (errbuf));
+      ERROR ("Target `replace': Executing a regular expression failed: %s.",
+          errbuf);
+      sfree (value);
+      continue;
+    }
+
+    if (act->replacement == NULL)
+    {
+      /* no replacement; delete the key */
+      DEBUG ("target_replace plugin: tr_meta_data_action_invoke: "
+          "deleting `%s'", act->key);
+      meta_data_delete (*dest, act->key);
+      sfree (value);
+      continue;
+    }
+
+    subst_status = subst (temp, sizeof (temp), value,
+        (size_t) matches[0].rm_so, (size_t) matches[0].rm_eo, act->replacement);
+    if (subst_status == NULL)
+    {
+      ERROR ("Target `replace': subst (value = %s, start = %zu, end = %zu, "
+          "replacement = %s) failed.",
+          value, (size_t) matches[0].rm_so, (size_t) matches[0].rm_eo,
+          act->replacement);
+      sfree (value);
+      continue;
+    }
+
+    DEBUG ("target_replace plugin: tr_meta_data_action_invoke: `%s' "
+        "value `%s' -> `%s'", act->key, value, temp);
+
+    if ((result = meta_data_create()) == NULL)
+    {
+      ERROR ("Target `replace': failed to create metadata for `%s'.",
+          act->key);
+      sfree (value);
+      return (-ENOMEM);
+    }
+
+    meta_data_status = meta_data_add_string (result, act->key, temp);
+    if (meta_data_status != 0)
+    {
+      ERROR ("Target `replace': Unable to set metadata value for `%s'.",
+          act->key);
+      meta_data_destroy (result);
+      sfree (value);
+      return (meta_data_status);
+    }
+
+    meta_data_clone_merge (dest, result);
+    meta_data_destroy (result);
+    sfree (value);
+  } /* for (act = act_head; act != NULL; act = act->next) */
+
+  return (0);
+} /* }}} int tr_meta_data_action_invoke */
+
 static int tr_destroy (void **user_data) /* {{{ */
 {
   tr_data_t *data;
@@ -231,6 +470,7 @@ static int tr_destroy (void **user_data) /* {{{ */
   tr_action_destroy (data->plugin_instance);
   /* tr_action_destroy (data->type); */
   tr_action_destroy (data->type_instance);
+  tr_meta_data_action_destroy (data->meta);
   sfree (data);
 
   return (0);
@@ -253,6 +493,7 @@ static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
   data->plugin_instance = NULL;
   /* data->type = NULL; */
   data->type_instance = NULL;
+  data->meta = NULL;
 
   status = 0;
   for (int i = 0; i < ci->children_num; i++)
@@ -277,6 +518,12 @@ static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
     else if (strcasecmp ("TypeInstance", child->key) == 0)
       status = tr_config_add_action (&data->type_instance, child,
           /* may be empty = */ 1);
+    else if (strcasecmp ("MetaData", child->key) == 0)
+      status = tr_config_add_meta_action (&data->meta, child,
+          /* should delete = */ 0);
+    else if (strcasecmp ("DeleteMetaData", child->key) == 0)
+      status = tr_config_add_meta_action (&data->meta, child,
+          /* should delete = */ 1);
     else
     {
       ERROR ("Target `replace': The `%s' configuration option is not understood "
@@ -295,7 +542,8 @@ static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
         && (data->plugin == NULL)
         && (data->plugin_instance == NULL)
         /* && (data->type == NULL) */
-        && (data->type_instance == NULL))
+        && (data->type_instance == NULL)
+        && (data->meta == NULL))
     {
       ERROR ("Target `replace': You need to set at least one of `Host', "
           "`Plugin', `PluginInstance' or `TypeInstance'.");
@@ -330,13 +578,18 @@ static int tr_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
     return (-EINVAL);
   }
 
+  if (data->meta != NULL)
+  {
+    tr_meta_data_action_invoke (data->meta, &(vl->meta));
+  }
+
 #define HANDLE_FIELD(f,e) \
   if (data->f != NULL) \
     tr_action_invoke (data->f, vl->f, sizeof (vl->f), e)
   HANDLE_FIELD (host, 0);
   HANDLE_FIELD (plugin, 0);
   HANDLE_FIELD (plugin_instance, 1);
-  /* HANDLE_FIELD (type); */
+  /* HANDLE_FIELD (type, 0); */
   HANDLE_FIELD (type_instance, 1);
 
   return (FC_TARGET_CONTINUE);
index 4f00cbb..3de86e4 100644 (file)
 
 #include "common.h"
 #include "filter_chain.h"
+#include "meta_data.h"
+#include "utils_subst.h"
+
+struct ts_key_list_s
+{
+  char *key;
+  struct ts_key_list_s *next;
+};
+typedef struct ts_key_list_s ts_key_list_t;
+
+static void ts_key_list_free (ts_key_list_t *l) /* {{{ */
+{
+  if (l == NULL)
+    return;
+
+  sfree (l->key);
+
+  if (l->next != NULL)
+    ts_key_list_free (l->next);
+
+  sfree (l);
+} /* }}} void ts_name_list_free */
 
 struct ts_data_s
 {
@@ -37,6 +59,7 @@ struct ts_data_s
   /* char *type; */
   char *type_instance;
   meta_data_t *meta;
+  ts_key_list_t *meta_delete;
 };
 typedef struct ts_data_s ts_data_t;
 
@@ -47,7 +70,7 @@ static int ts_util_get_key_and_string_wo_strdup (const oconfig_item_t *ci, char
       || (ci->values[1].type != OCONFIG_TYPE_STRING))
   {
     ERROR ("ts_util_get_key_and_string_wo_strdup: The %s option requires "
-        "exactly two string argument.", ci->key);
+        "exactly two string arguments.", ci->key);
     return (-1);
   }
 
@@ -92,31 +115,105 @@ static int ts_config_add_meta (meta_data_t **dest, /* {{{ */
 
   if (strlen (key) == 0)
   {
-    ERROR ("Target `set': The `%s' option does not accept empty string as first argument.",
-        ci->key);
+    ERROR ("Target `set': The `%s' option does not accept empty string as "
+        "first argument.", ci->key);
     return (-1);
   }
 
   if (!may_be_empty && (strlen (string) == 0))
   {
-    ERROR ("Target `set': The `%s' option does not accept empty string as second argument.",
-        ci->key);
+    ERROR ("Target `set': The `%s' option does not accept empty string as "
+        "second argument.", ci->key);
     return (-1);
   }
 
   if ((*dest) == NULL)
   {
-    // Create a new meta_data_t
+    /* Create a new meta_data_t */
     if ((*dest = meta_data_create()) == NULL)
     {
       ERROR ("Target `set': failed to create a meta data for `%s'.", ci->key);
-      return (-1);
+      return (-ENOMEM);
     }
   }
 
   return (meta_data_add_string (*dest, key, string));
 } /* }}} int ts_config_add_meta */
 
+static int ts_config_add_meta_delete (ts_key_list_t **dest, /* {{{ */
+    const oconfig_item_t *ci)
+{
+  ts_key_list_t *entry = NULL;
+
+  entry = calloc (1, sizeof (*entry));
+  if (entry == NULL)
+  {
+    ERROR ("ts_config_add_meta_delete: calloc failed.");
+    return (-ENOMEM);
+  }
+
+  if (cf_util_get_string (ci, &entry->key) != 0)
+  {
+    ts_key_list_free (entry);
+    return (-1);  /* An error has already been reported. */
+  }
+
+  if (strlen (entry->key) == 0)
+  {
+    ERROR ("Target `set': The `%s' option does not accept empty string as "
+        "first argument.", ci->key);
+    ts_key_list_free (entry);
+    return (-1);
+  }
+
+  entry->next = *dest;
+  *dest = entry;
+
+  return (0);
+} /* }}} int ts_config_add_meta_delete */
+
+static void ts_subst (char *dest, size_t size, const char *string, /* {{{ */
+    const value_list_t *vl)
+{
+  char temp[DATA_MAX_NAME_LEN];
+
+  /* Initialize the field with the template. */
+  sstrncpy (dest, string, size);
+
+  if (strchr (dest, '%') == NULL)
+    return;
+
+#define REPLACE_FIELD(t, v) \
+  if (subst_string (temp, sizeof (temp), dest, t, v) != NULL) \
+    sstrncpy (dest, temp, size);
+  REPLACE_FIELD ("%{host}", vl->host);
+  REPLACE_FIELD ("%{plugin}", vl->plugin);
+  REPLACE_FIELD ("%{plugin_instance}", vl->plugin_instance);
+  REPLACE_FIELD ("%{type}", vl->type);
+  REPLACE_FIELD ("%{type_instance}", vl->type_instance);
+
+  if (vl->meta != NULL)
+  {
+    char **meta_toc;
+    int meta_entries = meta_data_toc (vl->meta, &meta_toc);
+    for (int i = 0; i < meta_entries; i++)
+    {
+      char meta_name[DATA_MAX_NAME_LEN];
+      char *value_str;
+      const char *key = meta_toc[i];
+
+      ssnprintf (meta_name, sizeof (meta_name), "%%{meta:%s}", key);
+      if (meta_data_as_string (vl->meta, key, &value_str) != 0)
+        continue;
+
+      REPLACE_FIELD (meta_name, value_str);
+      sfree (value_str);
+    }
+
+    strarray_free (meta_toc, (size_t) meta_entries);
+  }
+} /* }}} int ts_subst */
+
 static int ts_destroy (void **user_data) /* {{{ */
 {
   ts_data_t *data;
@@ -134,6 +231,7 @@ static int ts_destroy (void **user_data) /* {{{ */
   /* free (data->type); */
   free (data->type_instance);
   meta_data_destroy(data->meta);
+  ts_key_list_free (data->meta_delete);
   free (data);
 
   return (0);
@@ -157,6 +255,7 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
   /* data->type = NULL; */
   data->type_instance = NULL;
   data->meta = NULL;
+  data->meta_delete = NULL;
 
   status = 0;
   for (int i = 0; i < ci->children_num; i++)
@@ -184,6 +283,8 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
     else if (strcasecmp ("MetaData", child->key) == 0)
       status = ts_config_add_meta (&data->meta, child,
           /* may be empty = */ 1);
+    else if (strcasecmp ("DeleteMetaData", child->key) == 0)
+      status = ts_config_add_meta_delete (&data->meta_delete, child);
     else
     {
       ERROR ("Target `set': The `%s' configuration option is not understood "
@@ -203,13 +304,30 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
         && (data->plugin_instance == NULL)
         /* && (data->type == NULL) */
         && (data->type_instance == NULL)
-        && (data->meta == NULL))
+        && (data->meta == NULL)
+        && (data->meta_delete == NULL))
     {
       ERROR ("Target `set': You need to set at least one of `Host', "
-          "`Plugin', `PluginInstance', `TypeInstance', `MetaData'.");
+          "`Plugin', `PluginInstance', `TypeInstance', "
+          "`MetaData', or `DeleteMetaData'.");
       status = -1;
     }
 
+    if (data->meta != NULL)
+    {
+      /* If data->meta_delete is NULL, this loop is a no-op. */
+      for (ts_key_list_t *l=data->meta_delete; l != NULL; l = l->next)
+      {
+        if (meta_data_type (data->meta, l->key) != 0)
+        {
+          /* MetaData and DeleteMetaData for the same key. */
+          ERROR ("Target `set': Can only have one of `MetaData' or "
+              "`DeleteMetaData' for any given key.");
+          status = -1;
+        }
+      }
+    }
+
     break;
   }
 
@@ -227,6 +345,8 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
     notification_meta_t __attribute__((unused)) **meta, void **user_data)
 {
   ts_data_t *data;
+  value_list_t orig;
+  meta_data_t *new_meta = NULL;
 
   if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
     return (-EINVAL);
@@ -238,17 +358,79 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
     return (-EINVAL);
   }
 
+  orig = *vl;
+
   if (data->meta != NULL)
   {
-    meta_data_clone_merge(&(vl->meta), data->meta);
+    char temp[DATA_MAX_NAME_LEN*2];
+    int meta_entries;
+    char **meta_toc;
+
+    if ((new_meta = meta_data_create()) == NULL)
+    {
+      ERROR ("Target `set': failed to create replacement metadata.");
+      return (-ENOMEM);
+    }
+
+    meta_entries = meta_data_toc (data->meta, &meta_toc);
+    for (int i = 0; i < meta_entries; i++)
+    {
+      const char *key = meta_toc[i];
+      char *string;
+      int status;
+
+      status = meta_data_get_string (data->meta, key, &string);
+      if (status)
+      {
+        ERROR ("Target `set': Unable to get replacement metadata value `%s'.",
+            key);
+        strarray_free (meta_toc, (size_t) meta_entries);
+        return (status);
+      }
+
+      ts_subst (temp, sizeof (temp), string, &orig);
+
+      DEBUG ("target_set: ts_invoke: setting metadata value for key `%s': "
+          "`%s'.", key, temp);
+
+      status = meta_data_add_string (new_meta, key, temp);
+
+      if (status)
+      {
+        ERROR ("Target `set': Unable to set metadata value `%s'.", key);
+        strarray_free (meta_toc, (size_t) meta_entries);
+        return (status);
+      }
+    }
+
+    strarray_free (meta_toc, (size_t) meta_entries);
+  }
+
+#define SUBST_FIELD(f) \
+  if (data->f != NULL) { \
+    ts_subst (vl->f, sizeof (vl->f), data->f, &orig); \
+    DEBUG ("target_set: ts_invoke: setting "#f": `%s'.", vl->f); \
+  }
+  SUBST_FIELD (host);
+  SUBST_FIELD (plugin);
+  SUBST_FIELD (plugin_instance);
+  /* SUBST_FIELD (type); */
+  SUBST_FIELD (type_instance);
+
+  /* Need to merge the metadata in now, because of the shallow copy. */
+  if (new_meta != NULL)
+  {
+    meta_data_clone_merge(&(vl->meta), new_meta);
+    meta_data_destroy(new_meta);
   }
 
-#define SET_FIELD(f) if (data->f != NULL) { sstrncpy (vl->f, data->f, sizeof (vl->f)); }
-  SET_FIELD (host);
-  SET_FIELD (plugin);
-  SET_FIELD (plugin_instance);
-  /* SET_FIELD (type); */
-  SET_FIELD (type_instance);
+  /* If data->meta_delete is NULL, this loop is a no-op. */
+  for (ts_key_list_t *l=data->meta_delete; l != NULL; l = l->next)
+  {
+    DEBUG ("target_set: ts_invoke: deleting metadata value for key `%s'.",
+        l->key);
+    meta_data_delete(vl->meta, l->key);
+  }
 
   return (FC_TARGET_CONTINUE);
 } /* }}} int ts_invoke */
index f7baa3a..3f2c958 100644 (file)
@@ -53,7 +53,6 @@ static void v5_swap_instances (value_list_t *vl) /* {{{ */
 static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */
 {
   value_list_t new_vl;
-  value_t new_value;
 
   /* Can't upgrade if both instances have been set. */
   if ((vl->plugin_instance[0] != 0)
@@ -64,7 +63,7 @@ static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */
   memcpy (&new_vl, vl, sizeof (new_vl));
 
   /* Reset data we can't simply copy */
-  new_vl.values = &new_value;
+  new_vl.values = &(value_t) { .gauge = NAN };
   new_vl.values_len = 1;
   new_vl.meta = NULL;
 
@@ -113,7 +112,6 @@ static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */
 static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
 {
   value_list_t new_vl;
-  value_t new_value;
 
   if (vl->values_len != 5)
     return (FC_TARGET_STOP);
@@ -122,7 +120,7 @@ static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
   memcpy (&new_vl, vl, sizeof (new_vl));
 
   /* Reset data we can't simply copy */
-  new_vl.values = &new_value;
+  new_vl.values = &(value_t) { .gauge = NAN };
   new_vl.values_len = 1;
   new_vl.meta = NULL;
 
@@ -171,7 +169,6 @@ static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
 static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
 {
   value_list_t new_vl;
-  value_t new_value;
 
   if (vl->values_len != 4)
     return (FC_TARGET_STOP);
@@ -180,7 +177,7 @@ static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
   memcpy (&new_vl, vl, sizeof (new_vl));
 
   /* Reset data we can't simply copy */
-  new_vl.values = &new_value;
+  new_vl.values = &(value_t) { .gauge = NAN };
   new_vl.values_len = 1;
   new_vl.meta = NULL;
 
@@ -224,7 +221,6 @@ static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
 static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
 {
   value_list_t new_vl;
-  value_t new_value;
   _Bool is_hits;
 
   if (vl->values_len != 4)
@@ -241,7 +237,7 @@ static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
   memcpy (&new_vl, vl, sizeof (new_vl));
 
   /* Reset data we can't simply copy */
-  new_vl.values = &new_value;
+  new_vl.values = &(value_t) { .gauge = NAN };
   new_vl.values_len = 1;
   new_vl.meta = NULL;
 
@@ -285,7 +281,6 @@ static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
 static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ */
 {
   value_list_t new_vl;
-  value_t new_values[2];
 
   if (vl->values_len != 2)
     return (FC_TARGET_STOP);
@@ -294,8 +289,6 @@ static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ *
   memcpy (&new_vl, vl, sizeof (new_vl));
 
   /* Reset data we can't simply copy */
-  new_vl.values = new_values;
-  new_vl.values_len = 2;
   new_vl.meta = NULL;
 
   /* Change the type/-instance to "io_octets-L2" */
@@ -303,8 +296,12 @@ static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ *
   sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
 
   /* Copy the actual values. */
-  new_vl.values[0].derive = (derive_t) vl->values[0].counter;
-  new_vl.values[1].derive = (derive_t) vl->values[1].counter;
+  value_t values[] = {
+    { .derive = (derive_t) vl->values[0].counter },
+    { .derive = (derive_t) vl->values[1].counter },
+  };
+  new_vl.values = values;
+  new_vl.values_len = STATIC_ARRAY_SIZE (values);
 
   /* Dispatch new value lists instead of this one */
   plugin_dispatch_values (&new_vl);
@@ -322,7 +319,6 @@ static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ *
 static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
 {
   value_list_t new_vl;
-  value_t new_value;
 
   if (vl->values_len != 1)
     return (FC_TARGET_STOP);
@@ -331,7 +327,7 @@ static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
   memcpy (&new_vl, vl, sizeof (new_vl));
 
   /* Reset data we can't simply copy */
-  new_vl.values = &new_value;
+  new_vl.values = &(value_t) { .gauge = NAN };
   new_vl.values_len = 1;
   new_vl.meta = NULL;
 
@@ -359,7 +355,6 @@ static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
 static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */
 {
   value_list_t new_vl;
-  value_t new_value;
 
   if (vl->values_len != 1)
     return (FC_TARGET_STOP);
@@ -368,7 +363,7 @@ static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */
   memcpy (&new_vl, vl, sizeof (new_vl));
 
   /* Reset data we can't simply copy */
-  new_vl.values = &new_value;
+  new_vl.values = &(value_t) { .gauge = NAN };
   new_vl.values_len = 1;
   new_vl.meta = NULL;
 
@@ -397,7 +392,6 @@ static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */
 static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
 {
   value_list_t new_vl;
-  value_t new_value;
 
   if (vl->values_len != 4)
     return (FC_TARGET_STOP);
@@ -406,7 +400,7 @@ static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
   memcpy (&new_vl, vl, sizeof (new_vl));
 
   /* Reset data we can't simply copy */
-  new_vl.values = &new_value;
+  new_vl.values = &(value_t) { .gauge = NAN };
   new_vl.values_len = 1;
   new_vl.meta = NULL;
 
index a1cde32..a709e79 100644 (file)
@@ -121,12 +121,9 @@ static void tss2_submit_gauge (const char *plugin_instance,
        /*
         * Submits a gauge value to the collectd daemon
         */
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values     = values;
+       vl.values     = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "teamspeak2", sizeof (vl.plugin));
@@ -150,14 +147,14 @@ static void tss2_submit_io (const char *plugin_instance, const char *type,
        /*
         * Submits the io rx/tx tuple to the collectd daemon
         */
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = rx;
-       values[1].derive = tx;
+       value_t values[] = {
+               { .derive = rx },
+               { .derive = tx },
+       };
 
        vl.values     = values;
-       vl.values_len = 2;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "teamspeak2", sizeof (vl.plugin));
 
index 5ed6c27..f167546 100644 (file)
--- a/src/ted.c
+++ b/src/ted.c
@@ -263,12 +263,9 @@ static int ted_open_device (void)
 
 static void ted_submit (const char *type, double value)
 {
-    value_t values[1];
     value_list_t vl = VALUE_LIST_INIT;
 
-    values[0].gauge = value;
-
-    vl.values = values;
+    vl.values = &(value_t) { .gauge = value };
     vl.values_len = 1;
     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
     sstrncpy (vl.plugin, "ted", sizeof (vl.plugin));
index e001a62..aa95dac 100644 (file)
@@ -47,14 +47,11 @@ enum dev_type {
 };
 
 static void thermal_submit (const char *plugin_instance, enum dev_type dt,
-               gauge_t value)
+               value_t value)
 {
        value_list_t vl = VALUE_LIST_INIT;
-       value_t v;
-
-       v.gauge = value;
-       vl.values = &v;
 
+       vl.values = &value;
        vl.values_len = 1;
 
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -72,52 +69,26 @@ static void thermal_submit (const char *plugin_instance, enum dev_type dt,
 static int thermal_sysfs_device_read (const char __attribute__((unused)) *dir,
                const char *name, void __attribute__((unused)) *user_data)
 {
-       char filename[256];
-       char data[1024];
-       int len;
+       char filename[PATH_MAX];
        _Bool success = 0;
+       value_t value;
 
        if (device_list && ignorelist_match (device_list, name))
                return -1;
 
-       len = ssnprintf (filename, sizeof (filename),
-                       "%s/%s/temp", dirname_sysfs, name);
-       if ((len < 0) || ((size_t) len >= sizeof (filename)))
-               return -1;
-
-       len = (ssize_t) read_file_contents (filename, data, sizeof(data));
-       if (len > 1 && data[--len] == '\n') {
-               char *endptr = NULL;
-               double temp;
-
-               data[len] = 0;
-               errno = 0;
-               temp = strtod (data, &endptr) / 1000.0;
-
-               if (endptr == data + len && errno == 0) {
-                       thermal_submit(name, TEMP, temp);
-                       success = 1;
-               }
+       ssnprintf (filename, sizeof (filename), "%s/%s/temp", dirname_sysfs, name);
+       if (parse_value_file (filename, &value, DS_TYPE_GAUGE) == 0)
+       {
+               value.gauge /= 1000.0;
+               thermal_submit(name, TEMP, value);
+               success = 1;
        }
 
-       len = ssnprintf (filename, sizeof (filename),
-                       "%s/%s/cur_state", dirname_sysfs, name);
-       if ((len < 0) || ((size_t) len >= sizeof (filename)))
-               return -1;
-
-       len = (ssize_t) read_file_contents (filename, data, sizeof(data));
-       if (len > 1 && data[--len] == '\n') {
-               char *endptr = NULL;
-               double state;
-
-               data[len] = 0;
-               errno = 0;
-               state = strtod (data, &endptr);
-
-               if (endptr == data + len && errno == 0) {
-                       thermal_submit(name, COOLING_DEV, state);
-                       success = 1;
-               }
+       ssnprintf (filename, sizeof (filename), "%s/%s/cur_state", dirname_sysfs, name);
+       if (parse_value_file (filename, &value, DS_TYPE_GAUGE) == 0)
+       {
+               thermal_submit(name, COOLING_DEV, value);
+               success = 1;
        }
 
        return (success ? 0 : -1);
@@ -176,7 +147,7 @@ static int thermal_procfs_device_read (const char __attribute__((unused)) *dir,
                temp = (strtod (data + len, &endptr) + add) * factor;
 
                if (endptr != data + len && errno == 0) {
-                       thermal_submit(name, TEMP, temp);
+                       thermal_submit(name, TEMP, (value_t) { .gauge = temp });
                        return 0;
                }
        }
index 7c6d912..154215f 100644 (file)
@@ -86,15 +86,12 @@ static void printerr (void)
                        ecode, tcrdberrmsg(ecode));
 }
 
-static void tt_submit (gauge_t val, const char* type)
+static void tt_submit (gauge_t value, const char* type)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = val;
-
-       vl.values = values;
-       vl.values_len = STATIC_ARRAY_SIZE (values);
+       vl.values = &(value_t) { .gauge = value };
+       vl.values_len = 1;
 
        sstrncpy (vl.host, config_host, sizeof (vl.host));
        sstrncpy (vl.plugin, "tokyotyrant", sizeof (vl.plugin));
index 2d8a08e..e74cba2 100644 (file)
@@ -524,10 +524,8 @@ turbostat_submit (const char *plugin_instance,
        gauge_t value)
 {
        value_list_t vl = VALUE_LIST_INIT;
-       value_t v;
 
-       v.gauge = value;
-       vl.values = &v;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, PLUGIN_NAME, sizeof (vl.plugin));
@@ -1018,8 +1016,7 @@ parse_int_file(const char *fmt, ...)
 {
        va_list args;
        char path[PATH_MAX];
-       FILE *filep;
-       int len, value;
+       int len;
 
        va_start(args, fmt);
        len = vsnprintf(path, sizeof(path), fmt, args);
@@ -1029,18 +1026,13 @@ parse_int_file(const char *fmt, ...)
                return -1;
        }
 
-       filep = fopen(path, "r");
-       if (!filep) {
-               ERROR("turbostat plugin: Failed to open '%s'", path);
-               return -1;
-       }
-       if (fscanf(filep, "%d", &value) != 1) {
-               ERROR("turbostat plugin: Failed to parse number from '%s'", path);
-               fclose(filep);
+       value_t v;
+       if (parse_value_file (path, &v, DS_TYPE_DERIVE) != 0) {
+               ERROR ("turbostat plugin: Parsing \"%s\" failed.", path);
                return -1;
        }
-       fclose(filep);
-       return value;
+
+       return (int) v.derive;
 }
 
 static int
index 6ec7812..4f8d31c 100644 (file)
@@ -94,7 +94,6 @@ hash_collisions         value:DERIVE:0:U
 http_request_methods    value:DERIVE:0:U
 http_requests           value:DERIVE:0:U
 http_response_codes     value:DERIVE:0:U
-hugepages               free:GAUGE:0:4294967295, used:GAUGE:0:4294967295
 humidity                value:GAUGE:0:100
 if_collisions           value:DERIVE:0:U
 if_dropped              rx:DERIVE:0:U, tx:DERIVE:0:U
index cbe2f8c..34c3e85 100644 (file)
@@ -58,14 +58,11 @@ static time_t boottime;
 extern kstat_ctl_t *kc;
 #endif /* #endif HAVE_LIBKSTAT */
 
-static void uptime_submit (gauge_t uptime)
+static void uptime_submit (gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = uptime;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
 
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
index 30e0dbe..ce626ae 100644 (file)
 
 static void users_submit (gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "users", sizeof (vl.plugin));
index e523420..0af586f 100644 (file)
@@ -150,18 +150,29 @@ static int gr_format_name (char *ret, int ret_len,
         sstrncpy (tmp_plugin, n_plugin, sizeof (tmp_plugin));
 
     if (n_type_instance[0] != '\0')
-        ssnprintf (tmp_type, sizeof (tmp_type), "%s%c%s",
-            n_type,
-            (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
-            n_type_instance);
+    {
+        if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(n_plugin, n_type) == 0)
+            sstrncpy (tmp_type, n_type_instance, sizeof (tmp_type));
+        else
+            ssnprintf (tmp_type, sizeof (tmp_type), "%s%c%s",
+                n_type,
+                (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
+                n_type_instance);
+    }
     else
         sstrncpy (tmp_type, n_type, sizeof (tmp_type));
 
     /* Assert always_append_ds -> ds_name */
     assert (!(flags & GRAPHITE_ALWAYS_APPEND_DS) || (ds_name != NULL));
     if (ds_name != NULL)
-        ssnprintf (ret, ret_len, "%s%s%s.%s.%s.%s",
-            prefix, n_host, postfix, tmp_plugin, tmp_type, ds_name);
+    {
+        if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(tmp_plugin, tmp_type) == 0)
+            ssnprintf (ret, ret_len, "%s%s%s.%s.%s",
+                prefix, n_host, postfix, tmp_plugin, ds_name);
+        else
+            ssnprintf (ret, ret_len, "%s%s%s.%s.%s.%s",
+                prefix, n_host, postfix, tmp_plugin, tmp_type, ds_name);
+    }
     else
         ssnprintf (ret, ret_len, "%s%s%s.%s.%s",
             prefix, n_host, postfix, tmp_plugin, tmp_type);
index 60576da..5165f9e 100644 (file)
@@ -29,6 +29,7 @@
 #define GRAPHITE_STORE_RATES        0x01
 #define GRAPHITE_SEPARATE_INSTANCES 0x02
 #define GRAPHITE_ALWAYS_APPEND_DS   0x04
+#define GRAPHITE_DROP_DUPE_FIELDS   0x08
 
 int format_graphite (char *buffer,
     size_t buffer_size, const data_set_t *ds,
index 6cc092c..18f5902 100644 (file)
@@ -117,22 +117,16 @@ static int varnish_submit_gauge (const char *plugin_instance, /* {{{ */
                const char *category, const char *type, const char *type_instance,
                uint64_t gauge_value)
 {
-       value_t value;
-
-       value.gauge = (gauge_t) gauge_value;
-
-       return (varnish_submit (plugin_instance, category, type, type_instance, value));
+       return (varnish_submit (plugin_instance, category, type, type_instance,
+                               (value_t) { .gauge = (gauge_t) gauge_value }));
 } /* }}} int varnish_submit_gauge */
 
 static int varnish_submit_derive (const char *plugin_instance, /* {{{ */
                const char *category, const char *type, const char *type_instance,
                uint64_t derive_value)
 {
-       value_t value;
-
-       value.derive = (derive_t) derive_value;
-
-       return (varnish_submit (plugin_instance, category, type, type_instance, value));
+       return (varnish_submit (plugin_instance, category, type, type_instance,
+                               (value_t) { .derive = (derive_t) derive_value }));
 } /* }}} int varnish_submit_derive */
 
 #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
@@ -951,16 +945,14 @@ static int varnish_init (void) /* {{{ */
 
        varnish_config_apply_default (conf);
 
-       user_data_t ud = {
-               .data = conf,
-               .free_func = varnish_config_free
-       };
-
        plugin_register_complex_read (/* group = */ "varnish",
                        /* name      = */ "varnish/localhost",
                        /* callback  = */ varnish_read,
                        /* interval  = */ 0,
-                       /* user data = */ &ud);
+                       &(user_data_t) {
+                               .data = conf,
+                               .free_func = varnish_config_free,
+                       });
 
        return (0);
 } /* }}} int varnish_init */
@@ -968,7 +960,6 @@ static int varnish_init (void) /* {{{ */
 static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
 {
        user_config_t *conf;
-       user_data_t ud;
        char callback_name[DATA_MAX_NAME_LEN];
 
        conf = calloc (1, sizeof (*conf));
@@ -1132,14 +1123,14 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
        ssnprintf (callback_name, sizeof (callback_name), "varnish/%s",
                        (conf->instance == NULL) ? "localhost" : conf->instance);
 
-       ud.data = conf;
-       ud.free_func = varnish_config_free;
-
        plugin_register_complex_read (/* group = */ "varnish",
                        /* name      = */ callback_name,
                        /* callback  = */ varnish_read,
                        /* interval  = */ 0,
-                       /* user data = */ &ud);
+                       &(user_data_t) {
+                               .data = conf,
+                               .free_func = varnish_config_free,
+                       });
 
        have_instance = 1;
 
index c1c77bc..99fe42d 100644 (file)
@@ -223,103 +223,71 @@ init_value_list (value_list_t *vl, virDomainPtr dom)
 
 } /* void init_value_list */
 
-static void
-memory_submit (gauge_t memory, virDomainPtr dom)
+static void submit (virDomainPtr dom,
+                    char const *type, char const *type_instance,
+                    value_t *values, size_t values_len)
 {
-    value_t values[1];
     value_list_t vl = VALUE_LIST_INIT;
-
     init_value_list (&vl, dom);
 
-    values[0].gauge = memory;
-
     vl.values = values;
-    vl.values_len = 1;
+    vl.values_len = values_len;
 
-    sstrncpy (vl.type, "memory", sizeof (vl.type));
-    sstrncpy (vl.type_instance, "total", sizeof (vl.type_instance));
+    sstrncpy (vl.type, type, sizeof (vl.type));
+    if (type_instance != NULL)
+        sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 
     plugin_dispatch_values (&vl);
 }
 
 static void
-memory_stats_submit (gauge_t memory, virDomainPtr dom, int tag_index)
+memory_submit (gauge_t value, virDomainPtr dom)
+{
+    submit (dom, "memory", "total", &(value_t) { .gauge = value }, 1);
+}
+
+static void
+memory_stats_submit (gauge_t value, virDomainPtr dom, int tag_index)
 {
     static const char *tags[] = { "swap_in", "swap_out", "major_fault", "minor_fault",
                                     "unused", "available", "actual_balloon", "rss"};
 
-    value_t values[1];
-    value_list_t vl = VALUE_LIST_INIT;
-
-    init_value_list (&vl, dom);
-
-    values[0].gauge = memory;
-
-    vl.values = values;
-    vl.values_len = 1;
-
-    sstrncpy (vl.type, "memory", sizeof (vl.type));
-    sstrncpy (vl.type_instance, tags[tag_index], sizeof (vl.type_instance));
+    if ((tag_index < 0) || (tag_index >= STATIC_ARRAY_SIZE (tags))) {
+        ERROR ("virt plugin: Array index out of bounds: tag_index = %d", tag_index);
+        return;
+    }
 
-    plugin_dispatch_values (&vl);
+    submit (dom, "memory", tags[tag_index], &(value_t) { .gauge = value }, 1);
 }
 
 static void
-cpu_submit (unsigned long long cpu_time,
+cpu_submit (unsigned long long value,
             virDomainPtr dom, const char *type)
 {
-    value_t values[1];
-    value_list_t vl = VALUE_LIST_INIT;
-
-    init_value_list (&vl, dom);
-
-    values[0].derive = cpu_time;
-
-    vl.values = values;
-    vl.values_len = 1;
-
-    sstrncpy (vl.type, type, sizeof (vl.type));
-
-    plugin_dispatch_values (&vl);
+    submit (dom, type, NULL, &(value_t) { .derive = (derive_t) value }, 1);
 }
 
 static void
-vcpu_submit (derive_t cpu_time,
+vcpu_submit (derive_t value,
              virDomainPtr dom, int vcpu_nr, const char *type)
 {
-    value_t values[1];
-    value_list_t vl = VALUE_LIST_INIT;
+    char type_instance[DATA_MAX_NAME_LEN];
 
-    init_value_list (&vl, dom);
+    ssnprintf (type_instance, sizeof (type_instance), "%d", vcpu_nr);
 
-    values[0].derive = cpu_time;
-    vl.values = values;
-    vl.values_len = 1;
-
-    sstrncpy (vl.type, type, sizeof (vl.type));
-    ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr);
-
-    plugin_dispatch_values (&vl);
+    submit (dom, type, type_instance, &(value_t) { .derive = value }, 1);
 }
 
 static void
 submit_derive2 (const char *type, derive_t v0, derive_t v1,
              virDomainPtr dom, const char *devname)
 {
-    value_t values[2];
-    value_list_t vl = VALUE_LIST_INIT;
-
-    init_value_list (&vl, dom);
+    value_t values[] = {
+        { .derive = v0 },
+        { .derive = v1 },
+    };
 
-    values[0].derive = v0;
-    values[1].derive = v1;
-    vl.values = values;
-    vl.values_len = 2;
-
-    sstrncpy (vl.type, type, sizeof (vl.type));
-    sstrncpy (vl.type_instance, devname, sizeof (vl.type_instance));
-
-    plugin_dispatch_values (&vl);
+    submit (dom, type, devname, values, STATIC_ARRAY_SIZE (values));
 } /* void submit_derive2 */
 
 static int
index 46ffa13..027f7bd 100644 (file)
@@ -65,12 +65,13 @@ static void submit (const char *plugin_instance, const char *type,
 static void submit_two (const char *plugin_instance, const char *type,
     const char *type_instance, derive_t c0, derive_t c1)
 {
-  value_t values[2];
+  value_t values[] = {
+    { .derive = c0 },
+    { .derive = c1 },
+  };
 
-  values[0].derive = c0;
-  values[1].derive = c1;
-
-  submit (plugin_instance, type, type_instance, values, 2);
+  submit (plugin_instance, type, type_instance,
+      values, STATIC_ARRAY_SIZE (values));
 } /* void submit_one */
 
 static void submit_one (const char *plugin_instance, const char *type,
index a730593..f3a2b5a 100644 (file)
@@ -56,11 +56,11 @@ static int vserver_init (void)
 static void traffic_submit (const char *plugin_instance,
                const char *type_instance, derive_t rx, derive_t tx)
 {
-       value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].derive = rx;
-       values[1].derive = tx;
+       value_t values[] = {
+               { .derive = rx },
+               { .derive = tx },
+       };
 
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
@@ -76,12 +76,12 @@ static void traffic_submit (const char *plugin_instance,
 static void load_submit (const char *plugin_instance,
                gauge_t snum, gauge_t mnum, gauge_t lnum)
 {
-       value_t values[3];
        value_list_t vl = VALUE_LIST_INIT;
-
-       values[0].gauge = snum;
-       values[1].gauge = mnum;
-       values[2].gauge = lnum;
+       value_t values[] = {
+               { .gauge = snum },
+               { .gauge = mnum },
+               { .gauge = lnum },
+       };
 
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
@@ -97,13 +97,10 @@ static void submit_gauge (const char *plugin_instance, const char *type,
                const char *type_instance, gauge_t value)
 
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
-       vl.values_len = STATIC_ARRAY_SIZE (values);
+       vl.values = &(value_t) { .gauge = value };
+       vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
index b998462..7d57fea 100644 (file)
@@ -54,12 +54,9 @@ static double wireless_dbm_to_watt (double dbm)
 static void wireless_submit (const char *plugin_instance, const char *type,
                double value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "wireless", sizeof (vl.plugin));
index fe2376a..ebc5ce2 100644 (file)
@@ -548,6 +548,9 @@ static int wg_config_node (oconfig_item_t *ci)
         else if (strcasecmp ("AlwaysAppendDS", child->key) == 0)
             cf_util_get_flag (child, &cb->format_flags,
                     GRAPHITE_ALWAYS_APPEND_DS);
+        else if (strcasecmp ("DropDuplicateFields", child->key) == 0)
+            cf_util_get_flag (child, &cb->format_flags,
+                    GRAPHITE_DROP_DUPE_FIELDS);
         else if (strcasecmp ("EscapeCharacter", child->key) == 0)
             config_set_char (&cb->escape_char, child);
         else
@@ -575,15 +578,13 @@ static int wg_config_node (oconfig_item_t *ci)
         ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s",
                 cb->name);
 
-    user_data_t ud = {
-        .data = cb,
-        .free_func = wg_callback_free
-    };
-
-    plugin_register_write (callback_name, wg_write, &ud);
+    plugin_register_write (callback_name, wg_write,
+            &(user_data_t) {
+                .data = cb,
+                .free_func = wg_callback_free,
+            });
 
-    ud.free_func = NULL;
-    plugin_register_flush (callback_name, wg_flush, &ud);
+    plugin_register_flush (callback_name, wg_flush, &(user_data_t) { .data = cb });
 
     return (0);
 }
index 9fda2df..75da6aa 100644 (file)
@@ -383,12 +383,11 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
     ssnprintf(callback_name, sizeof(callback_name),
               "write_kafka/%s", tctx->topic_name);
 
-    user_data_t ud = {
-        .data = tctx,
-        .free_func = kafka_topic_context_free
-    };
-
-    status = plugin_register_write (callback_name, kafka_write, &ud);
+    status = plugin_register_write (callback_name, kafka_write,
+            &(user_data_t) {
+                .data = tctx,
+                .free_func = kafka_topic_context_free,
+            });
     if (status != 0) {
         WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
                 "failed with status %i.",
index b0dc6f1..e10a912 100644 (file)
 #include "plugin.h"
 
 #include "utils_format_graphite.h"
+#include "utils_format_json.h"
 
 #include <netdb.h>
 
-#define WL_BUF_SIZE 8192
+#define WL_BUF_SIZE 16384
 
-static int wl_write_messages (const data_set_t *ds, const value_list_t *vl)
+#define WL_FORMAT_GRAPHITE 1
+#define WL_FORMAT_JSON 2
+
+/* Plugin:WriteLog has to also operate without a config, so use a global. */
+int wl_format = WL_FORMAT_GRAPHITE;
+
+static int wl_write_graphite (const data_set_t *ds, const value_list_t *vl)
 {
     char buffer[WL_BUF_SIZE] = { 0 };
     int status;
 
     if (0 != strcmp (ds->type, vl->type))
     {
-        ERROR ("write_log plugin: DS type does not match "
-                "value list type");
+        ERROR ("write_log plugin: DS type does not match value list type");
         return -1;
     }
 
@@ -56,20 +62,95 @@ static int wl_write_messages (const data_set_t *ds, const value_list_t *vl)
     INFO ("write_log values:\n%s", buffer);
 
     return (0);
-} /* int wl_write_messages */
+} /* int wl_write_graphite */
+
+static int wl_write_json (const data_set_t *ds, const value_list_t *vl)
+{
+    char buffer[WL_BUF_SIZE] = { 0 };
+    size_t bfree = sizeof(buffer);
+    size_t bfill = 0;
+
+    if (0 != strcmp (ds->type, vl->type))
+    {
+        ERROR ("write_log plugin: DS type does not match value list type");
+        return -1;
+    }
+
+    format_json_initialize(buffer, &bfill, &bfree);
+    format_json_value_list(buffer, &bfill, &bfree, ds, vl,
+                           /* store rates = */ 0);
+    format_json_finalize(buffer, &bfill, &bfree);
+
+    INFO ("write_log values:\n%s", buffer);
+
+    return (0);
+} /* int wl_write_json */
 
 static int wl_write (const data_set_t *ds, const value_list_t *vl,
         __attribute__ ((unused)) user_data_t *user_data)
 {
-    int status;
+    int status = 0;
 
-    status = wl_write_messages (ds, vl);
+    if (wl_format == WL_FORMAT_GRAPHITE)
+    {
+        status = wl_write_graphite (ds, vl);
+    }
+    else if (wl_format == WL_FORMAT_JSON)
+    {
+        status = wl_write_json (ds, vl);
+    }
 
     return (status);
 }
 
+static int wl_config (oconfig_item_t *ci) /* {{{ */
+{
+    _Bool format_seen = 0;
+
+    for (int i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if (strcasecmp ("Format", child->key) == 0)
+        {
+            char str[16];
+
+            if (cf_util_get_string_buffer (child, str, sizeof (str)) != 0)
+                continue;
+
+            if (format_seen)
+            {
+                WARNING ("write_log plugin: Redefining option `%s'.",
+                    child->key);
+            }
+            format_seen = 1;
+
+            if (strcasecmp ("Graphite", str) == 0)
+                wl_format = WL_FORMAT_GRAPHITE;
+            else if (strcasecmp ("JSON", str) == 0)
+                wl_format = WL_FORMAT_JSON;
+            else
+            {
+                ERROR ("write_log plugin: Unknown format `%s' for option `%s'.",
+                    str, child->key);
+                return (-EINVAL);
+            }
+        }
+        else
+        {
+            ERROR ("write_log plugin: Invalid configuration option: `%s'.",
+                child->key);
+            return (-EINVAL);
+        }
+    }
+
+    return (0);
+} /* }}} int wl_config */
+
 void module_register (void)
 {
+    plugin_register_complex_config ("write_log", wl_config);
+    /* If config is supplied, the global wl_format will be set. */
     plugin_register_write ("write_log", wl_write, NULL);
 }
 
index 6d5f379..796574e 100644 (file)
@@ -339,12 +339,11 @@ static int wm_config_node (oconfig_item_t *ci) /* {{{ */
 
     ssnprintf (cb_name, sizeof (cb_name), "write_mongodb/%s", node->name);
 
-    user_data_t ud = {
-      .data = node,
-      .free_func = wm_config_free
-    };
-
-    status = plugin_register_write (cb_name, wm_write, &ud);
+    status = plugin_register_write (cb_name, wm_write,
+                   &(user_data_t) {
+                           .data = node,
+                           .free_func = wm_config_free,
+                   });
     INFO ("write_mongodb plugin: registered write plugin %s %d",cb_name,status);
   }
 
index 4722416..def3d9c 100644 (file)
@@ -234,12 +234,11 @@ static int wr_config_node (oconfig_item_t *ci) /* {{{ */
 
     ssnprintf (cb_name, sizeof (cb_name), "write_redis/%s", node->name);
 
-    user_data_t ud = {
-      .data = node,
-      .free_func = wr_config_free
-    };
-
-    status = plugin_register_write (cb_name, wr_write, &ud);
+    status = plugin_register_write (cb_name, wr_write,
+        &(user_data_t) {
+          .data = node,
+          .free_func = wr_config_free,
+        });
   }
 
   if (status != 0)
index f1cd938..93575df 100644 (file)
@@ -108,14 +108,11 @@ static int xencpu_shutdown (void)
     return 0;
 } /* static int xencpu_shutdown */
 
-static void submit_value (int cpu_num, gauge_t percent)
+static void submit_value (int cpu_num, gauge_t value)
 {
-    value_t values[1];
     value_list_t vl = VALUE_LIST_INIT;
 
-    values[0].gauge = percent;
-
-    vl.values = values;
+    vl.values = &(value_t) { .gauge = value };
     vl.values_len = 1;
 
     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
@@ -145,9 +142,10 @@ static int xencpu_read (void)
     int status;
     for (int cpu = 0; cpu < nr_cpus; cpu++) {
         gauge_t rate = NAN;
-        value_t value = {.derive = cpu_info[cpu].idletime};
 
-        status = value_to_rate (&rate, value, DS_TYPE_DERIVE, now, &cpu_states[cpu]);
+        status = value_to_rate (&rate,
+                                (value_t) { .derive = cpu_info[cpu].idletime }, DS_TYPE_DERIVE,
+                                now, &cpu_states[cpu]);
         if (status == 0) {
             submit_value(cpu, 100 - rate/10000000);
         }
index 3535995..2ba3082 100644 (file)
@@ -35,12 +35,9 @@ static gint xmms_session;
 
 static void cxmms_submit (const char *type, gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = value;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "xmms", sizeof (vl.plugin));
index 8261282..e411085 100644 (file)
@@ -138,7 +138,7 @@ static long long get_zfs_value(kstat_t *dummy __attribute__((unused)),
 }
 #endif
 
-static void za_submit (const char* type, const char* type_instance, value_t* values, int values_len)
+static void za_submit (const char* type, const char* type_instance, value_t* values, size_t values_len)
 {
        value_list_t vl = VALUE_LIST_INIT;
 
@@ -155,45 +155,34 @@ static void za_submit (const char* type, const char* type_instance, value_t* val
 
 static void za_submit_gauge (const char* type, const char* type_instance, gauge_t value)
 {
-       value_t vv;
-
-       vv.gauge = value;
-       za_submit (type, type_instance, &vv, 1);
+       za_submit (type, type_instance, &(value_t) { .gauge = value }, 1);
 }
 
 static int za_read_derive (kstat_t *ksp, const char *kstat_value,
     const char *type, const char *type_instance)
 {
-  long long tmp;
-  value_t v;
-
-  tmp = get_zfs_value (ksp, (char *)kstat_value);
+  long long tmp = get_zfs_value (ksp, (char *)kstat_value);
   if (tmp == -1LL)
   {
     WARNING ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
     return (-1);
   }
 
-  v.derive = (derive_t) tmp;
-  za_submit (type, type_instance, /* values = */ &v, /* values_num = */ 1);
+  za_submit (type, type_instance, &(value_t) { .derive = (derive_t) tmp }, /* values_num = */ 1);
   return (0);
 }
 
 static int za_read_gauge (kstat_t *ksp, const char *kstat_value,
     const char *type, const char *type_instance)
 {
-  long long tmp;
-  value_t v;
-
-  tmp = get_zfs_value (ksp, (char *)kstat_value);
+  long long tmp = get_zfs_value (ksp, (char *)kstat_value);
   if (tmp == -1LL)
   {
     WARNING ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
     return (-1);
   }
 
-  v.gauge = (gauge_t) tmp;
-  za_submit (type, type_instance, /* values = */ &v, /* values_num = */ 1);
+  za_submit (type, type_instance, &(value_t) { .gauge = (gauge_t) tmp }, /* values_num = */ 1);
   return (0);
 }
 
@@ -215,7 +204,6 @@ static void za_submit_ratio (const char* type_instance, gauge_t hits, gauge_t mi
 static int za_read (void)
 {
        gauge_t  arc_hits, arc_misses, l2_hits, l2_misses;
-       value_t  l2_io[2];
        kstat_t  *ksp   = NULL;
 
 #if defined(KERNEL_LINUX)
@@ -331,10 +319,11 @@ static int za_read (void)
        za_submit_ratio ("L2", l2_hits, l2_misses);
 
        /* I/O */
-       l2_io[0].derive = get_zfs_value(ksp, "l2_read_bytes");
-       l2_io[1].derive = get_zfs_value(ksp, "l2_write_bytes");
-
-       za_submit ("io_octets", "L2", l2_io, /* num values = */ 2);
+       value_t  l2_io[] = {
+               { .derive = (derive_t) get_zfs_value(ksp, "l2_read_bytes") },
+               { .derive = (derive_t) get_zfs_value(ksp, "l2_write_bytes") },
+       };
+       za_submit ("io_octets", "L2", l2_io, STATIC_ARRAY_SIZE (l2_io));
 
 #if defined(KERNEL_LINUX)
        free_zfs_values (ksp);
index 8417485..7e55191 100644 (file)
@@ -66,14 +66,11 @@ static int zookeeper_config(const char *key, const char *value)
        return 0;
 }
 
-static void zookeeper_submit_gauge (const char * type, const char * type_inst, gauge_t val)
+static void zookeeper_submit_gauge (const char * type, const char * type_inst, gauge_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].gauge = val;
-
-       vl.values = values;
+       vl.values = &(value_t) { .gauge = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "zookeeper", sizeof (vl.plugin));
@@ -84,14 +81,11 @@ static void zookeeper_submit_gauge (const char * type, const char * type_inst, g
        plugin_dispatch_values (&vl);
 } /* zookeeper_submit_gauge */
 
-static void zookeeper_submit_derive (const char * type, const char * type_inst, derive_t val)
+static void zookeeper_submit_derive (const char * type, const char * type_inst, derive_t value)
 {
-       value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
 
-       values[0].derive = val;
-
-       vl.values = values;
+       vl.values = &(value_t) { .derive = value };
        vl.values_len = 1;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "zookeeper", sizeof (vl.plugin));
index 70b8c26..2ef5279 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-DEFAULT_VERSION="5.5.2.git"
+DEFAULT_VERSION="5.6.0.git"
 
 if [ -d .git ]; then
        VERSION="`git describe --dirty=+ --abbrev=7 2> /dev/null | grep collectd | sed -e 's/^collectd-//' -e 's/-/./g'`"