author | Florian Forster <octo@noris.net> | |
Fri, 10 Oct 2008 07:01:54 +0000 (09:01 +0200) | ||
committer | Florian Forster <octo@noris.net> | |
Fri, 10 Oct 2008 07:01:54 +0000 (09:01 +0200) |
107 files changed:
index 7f92d55cb99c339def827ab4225010fe36c934c5..234d431e0762fcc69f471d83b2097222dde3b273 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
-This package was written by:
- Florian octo Forster <octo at verplant.org>
+Permanent project members
+=========================
-apcups plugin by:
- Anthony Gialluca <tonyabg at charter.net>
+Florian "octo" Forster <octo at verplant.org>
+ - Initial author.
-cpufreq, multimeter and irq plugin, as well as some bugfixes in the exec plugin
-by:
- Peter Holik <peter at holik.at>
+Sebastian "tokkee" Harl <sh at tokkee.org>
+ - Bugfixes and enhancments in many places all around the project.
+ - perl plugin.
+ - users plugin.
+ - vserver plugin.
+ - Debian package.
-hddtemp plugin by:
- Vincent Stehlé <vincent.stehle at free.fr>
-iptables plugin by:
- Sjoerd van der Berg <harekiet at gmail.com>
+Contributors (sorted alphabetically)
+====================================
-libvirt plugin by:
- Richard W. M. Jones <rjones at redhat.com>
+Alessandro Iurlano <alessandro.iurlano at gmail.com>
+ - Initial filecount plugin.
-mbmon plugin by:
- Flavio Stanchina <flavio at stanchina.net>
+Alvaro Barcellos <alvaro.barcellos at gmail.com>
+ - Don't-fork patch.
-memcached plugin by:
- Antony Dovgal <tony at daylessday.org>
+Anthony Gialluca <tonyabg at charter.net>
+ - apcups plugin.
-nfs plugin by:
- Jason Pepas <cell at ices.utexas.edu>
+Antony Dovgal <tony at daylessday.org>
+ - memcached plugin.
-perl plugin by:
- Sebastian Harl <sh at tokkee.org>
+Christophe Kalt <collectd at klb.taranis.org>
+ - The version 3 `log' mode.
+ - Many Solaris related hints and fixes.
-powerdns plugin and initial `tail' subsystem by:
- Luke Herberling <collectd at c-ware.com>
+Dan Berrange <berrange at redhat.com>
+ - uuid plugin.
-processes plugin by:
- Lyonel Vincent <lyonel at ezix.org>
+David Bacher <drbacher at gmail.com>
+ - serial plugin.
-sensors plugin has been improved by:
- Luboš Staněk <kolektor at atlas.cz>
+Flavio Stanchina <flavio at stanchina.net>
+ - mbmon plugin.
-serial plugin by:
- David Bacher <drbacher at gmail.com>
+Jason Pepas <cell at ices.utexas.edu>
+ - nfs plugin.
-tape plugin by:
- Scott Garrett <sgarrett at technomancer.com>
+Luboš Staněk <kolektor at atlas.cz>
+ - sensors plugin improvements.
+ - Time and effort to find a nasty bug in the ntpd-plugin.
-teamspeak2 plugin by:
- Stefan Hacker <stefan.hacker at web.de>
+Luke Herberling <collectd at c-ware.com>
+ - powerdns plugin.
+ - Initial `tail' subsystem by:
-users plugin by:
- Sebastian Harl <sh at tokkee.org>
+Lyonel Vincent <lyonel at ezix.org>
+ - processes plugin.
-uuid plugin by:
- Dan Berrange <berrange at redhat.com>
- Richard W.M. Jones <rjones at redhat.com>
+Michael Stapelberg <michael+git@stapelberg.de>
+ - OpenBSD port of the tcpconns plugin.
-vserver plugin by:
- Sebastian Harl <sh at tokkee.org>
+Niki W. Waibel <niki.waibel at newlogic.com>
+ - Initial autotools fixes.
+ - libltdl code.
+ - getmnt-wizardry.
-PID-file patch by:
- Tommie Gannert <d00-tga at d.kth.se>
+Oleg King <king2 at kaluga.ru>
+ - Added support for the statgrab library to
+ + the cpu plugin,
+ + the disk plugin, and
+ + the users plugin.
-Don't-fork-patch by:
- Alvaro Barcellos <alvaro.barcellos at gmail.com>
+Peter Holik <peter at holik.at>
+ - cpufreq plugin.
+ - multimeter plugin.
+ - irq plugin.
+ - Some bugfixes in the exec plugin.
+ - Notifications in the ipmi plugin.
-Many autotools related fixes, libltdl code, getmnt-wizardry and much help has
-contributed:
- Niki W. Waibel <niki.waibel at newlogic.com>
+Richard W. M. Jones <rjones at redhat.com>
+ - libvirt plugin.
+ - uuid plugin.
-The `log' mode has been written by:
- Christophe Kalt <collectd at klb.taranis.org>
+Scott Garrett <sgarrett at technomancer.com>
+ - tape plugin.
-Much time and effort to find a nasty bug in the ntpd-plugin has been
-contributed by:
- Luboš Staněk <lubek at users.sourceforge.net>
+Sjoerd van der Berg <harekiet at gmail.com>
+ - iptables plugin.
-Support for the statgrab library has been added to the cpu, disk and users
-plugins by
- Oleg King <king2 at kaluga.ru>
+Stefan Hacker <stefan.hacker at web.de>
+ - teamspeak2 plugin.
+
+Tommie Gannert <d00-tga at d.kth.se>
+ - PID-file patch.
+
+Vincent Stehlé <vincent.stehle at free.fr>
+ - hddtemp plugin.
collectd is available at:
<http://collectd.org/>
diff --git a/ChangeLog b/ChangeLog
index 6a1ec5e7e9a832fe0ca60f8cc343773ea9918621..00a04add0303557e4a5f328c8494703236d39bca 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+2008-09-04, Version 4.5.0
+ * collectd: Added the ability to flush certain identifiers.
+ * collectd: The concept of `notification meta data' has been
+ introduced.
+ * filecount plugin: The new filecount plugin counts the number of
+ files in a directory and its subdirectories.
+ * ipmi plugin: Sensor names have been changed to ensure unique names.
+ Notifications upon added and removed sensors can now be generated.
+ * notify_desktop plugin: This new plugin sends notifications to the
+ X desktop using the structure defined in the `Desktop Notification
+ Specification'.
+ * notify_email plugin: This new plugin sends out notifications via
+ email, using the `esmtp' library.
+ * onewire plugin: The new experimental(!) onewire plugin reads values,
+ such as temperatures, from sensors connected to the computer via the
+ onewire bus.
+ * perl plugin: Improved synchronized access to internal data structures
+ and fixed a possible dead-lock.
+ * perl plugin: Added the ability to flush certain identifiers and marked
+ plugin_flush_all() and plugin_flush_one() as deprecated in favor of
+ plugin_flush().
+ * perl plugin: Added the ability to configure Perl plugins.
+ * postgresql plugin: The new postgresql plugin collects statistics
+ about or from a PostgreSQL database.
+ * processes plugin: The `ProcessMatch' option has been added.
+ * rrdtool plugin: Implement throttling of the `update queue' to lessen
+ IO load.
+ * tcpconns plugin: This plugin has been ported to OpenBSD.
+ * thermal plugin: The new thermal plugin collects system temperatures
+ using Linux ACPI thermal zone data.
+
2008-09-01, Version 4.4.3
* collectd: Fix a memory leak in the threshold checking code.
* memcached plugin: Fix a too short timeout and a related file
index 97b66f7902a7d0d130623440b2e6b3f9950f3264..e698786a1cb86baafacbc838375d334875e3b10a 100644 (file)
--- a/README
+++ b/README
Values gathered by a custom program or script.
See collectd-exec(5).
+ - filecount
+ Count the number of files in directories.
+
- hddtemp
Harddisk temperatures using hddtempd.
Network UPS tools: UPS current, voltage, power, charge, utilisation,
temperature, etc. See upsd(8).
+ - onewire (EXPERIMENTAL!)
+ Read onewire sensors using the owcapu library of the owfs project.
+ Please read in collectd.conf(5) why this plugin is experimental.
+
- perl
The perl plugin implements a Perl-interpreter into collectd. You can
write your own plugins in Perl and return arbitrary values using this
Network latency: Time to reach the default gateway or another given
host.
+ - postgresql
+ PostgreSQL database statistics: active server connections, transaction
+ numbers, block IO, table row manipulations.
+
- processes
Process counts: Number of running, sleeping, zombie, ... processes.
* Notifications can be handled by the following plugins:
+ - notify_desktop
+ Send a desktop notification to a notification daemon, as defined in
+ the Desktop Notification Specification. To actually display the
+ notifications, notification-daemon is required.
+ See http://www.galago-project.org/specs/notification/.
+
+ - notify_email
+ Send an E-mail with the notification message to the configured
+ recipients.
+
- exec
Execute a program or script to handle the notification.
See collectd-exec(5).
used and should be found in various implementations for hopefully all
platforms.
+ * CoreFoundation.framework and IOKit.framework (optional)
+ For compiling on Darwin in general and the `apple_sensors' plugin in
+ particular.
+
* libcurl (optional)
If you want to use the `apache', `ascent', or `nginx' plugin.
+ * libesmtp (optional)
+ For the `notify_email' plugin.
+
* libhal (optional)
If present, the uuid plugin will check for UUID from HAL.
* libnetsnmp (optional)
For the `snmp' plugin.
+ * libnotify (optional)
+ For the `notify_desktop' plugin.
+
* liboping (optional, if not found a version shipped with this distribution
can be used)
Used by the `ping' plugin to send and receive ICMP packets.
+ * libowcapi (optional)
+ Used by the `onewire' plugin to read values from onewire sensors (or the
+ owserver(1) daemon).
+
* libpcap (optional)
Used to capture packets by the `dns' plugin.
Obviously used by the `perl' plugin. The library has to be compiled with
ithread support (introduced in Perl 5.6.0).
+ * libpq (optional)
+ The PostgreSQL C client library used by the `postgresql' plugin.
+
* librrd (optional; headers and library; rrdtool 1.0 and 1.2 both work fine)
If built without `librrd' the resulting binary will be `client only', i.e.
will send its values via multicast and not create any RRD files itself.
Alternatively you can chose to write CSV-files (Comma Separated Values)
instead.
+ * librt, libsocket, libkstat, libdevinfo (optional)
+ Various standard Solaris libraries which provide system functions.
+
* libsensors (optional)
To read from `lm_sensors', see the `sensors' plugin.
- * libstatgrab may be used to collect statistics on systems other than Linux
- and/or Solaris. Note that CPU- and disk-statistics, while being provided
- by this library, are not supported in collectd right now..
+ * libstatgrab (optional) may be used to collect statistics on systems other
+ than Linux and/or Solaris. Note that CPU- and disk-statistics, while being
+ provided by this library, are not supported in collectd right now..
<http://www.i-scream.org/libstatgrab/>
* libupsclient/nut (optional)
For the `nut' plugin which queries nut's `upsd'.
- * libxmms (optional)
-
- * librt, libsocket, libkstat, libdevinfo
- Various standard Solaris libraries which provide system functions.
-
- * CoreFoundation.framework and IOKit.framework
- For compiling on Darwin in general and the `apple_sensors' plugin in
- particular.
-
* libvirt (optional)
Collect statistics from virtual machines.
* libxml2 (optional)
Parse XML data. This is needed for the `ascent' and `libvirt' plugins.
+ * libxmms (optional)
+
Configuring / Compiling / Installing
------------------------------------
index 08fcec1ee70c568810959e445cf103bc669348a4..b5cd6b50154de7461475dc7a0741477916480060 100644 (file)
--- a/TODO
+++ b/TODO
-For version 4.4:
-* PowerDNS plugin
-
-For version 4.3:
-* unixsock plugin: Remove the custom cache if possible.
+* Parse options/identifiers with spaces in them correctly.
+* Figure out what to do with the onewire plugin.
+* Custom notification messages?
src/battery.c: commend not working code.
index cca349ec7a2c60e9a43dfa4b7030ce2299837d79..738206bbbd9f581173befdbab8a8b9413ee00375 100644 (file)
TYPE_LOG
TYPE_NOTIF
TYPE_FLUSH
+ TYPE_CONFIG
TYPE_DATASET
) ],
'ds_types' => [ qw(
Exporter::export_ok_tags ('all');
my @plugins : shared = ();
+my %cf_callbacks : shared = ();
my %types = (
TYPE_INIT, "init",
sub plugin_call_all {
my $type = shift;
+ my %plugins;
+
our $cb_name = undef;
if (! defined $type) {
return;
}
- lock @plugins;
- foreach my $plugin (keys %{$plugins[$type]}) {
- my $p = $plugins[$type]->{$plugin};
+ {
+ lock %{$plugins[$type]};
+ %plugins = %{$plugins[$type]};
+ }
+
+ foreach my $plugin (keys %plugins) {
+ my $p = $plugins{$plugin};
my $status = 0;
return;
}
- if ((! defined $plugins[$type]) && (TYPE_DATASET != $type)) {
+ if ((! defined $plugins[$type]) && (TYPE_DATASET != $type)
+ && (TYPE_CONFIG != $type)) {
ERROR ("Collectd::plugin_register: Invalid type \"$type\"");
return;
}
if ((TYPE_DATASET == $type) && ("ARRAY" eq ref $data)) {
return plugin_register_data_set ($name, $data);
}
+ elsif ((TYPE_CONFIG == $type) && (! ref $data)) {
+ my $pkg = scalar caller;
+
+ if ($data !~ m/^$pkg\:\:/) {
+ $data = $pkg . "::" . $data;
+ }
+
+ lock %cf_callbacks;
+ $cf_callbacks{$name} = $data;
+ }
elsif ((TYPE_DATASET != $type) && (! ref $data)) {
my $pkg = scalar caller;
cb_name => $data,
);
- lock @plugins;
+ lock %{$plugins[$type]};
$plugins[$type]->{$name} = \%p;
}
else {
if (TYPE_DATASET == $type) {
return plugin_unregister_data_set ($name);
}
+ elsif (TYPE_CONFIG == $type) {
+ lock %cf_callbacks;
+ delete $cf_callbacks{$name};
+ }
elsif (defined $plugins[$type]) {
- lock @plugins;
+ lock %{$plugins[$type]};
delete $plugins[$type]->{$name};
}
else {
my %args = @_;
my $timeout = -1;
+ my @plugins = ();
+ my @ids = ();
DEBUG ("Collectd::plugin_flush:"
. (defined ($args{'timeout'}) ? " timeout = $args{'timeout'}" : "")
- . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : ""));
+ . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : "")
+ . (defined ($args{'identifiers'})
+ ? " identifiers = $args{'identifiers'}" : ""));
if (defined ($args{'timeout'}) && ($args{'timeout'} > 0)) {
$timeout = $args{'timeout'};
}
- if (! defined $args{'plugins'}) {
- plugin_flush_all ($timeout);
+ if (defined ($args{'plugins'})) {
+ if ("ARRAY" eq ref ($args{'plugins'})) {
+ @plugins = @{$args{'plugins'}};
+ }
+ else {
+ @plugins = ($args{'plugins'});
+ }
}
else {
- if ("ARRAY" eq ref ($args{'plugins'})) {
- foreach my $plugin (@{$args{'plugins'}}) {
- plugin_flush_one ($timeout, $plugin);
- }
+ @plugins = (undef);
+ }
+
+ if (defined ($args{'identifiers'})) {
+ if ("ARRAY" eq ref ($args{'identifiers'})) {
+ @ids = @{$args{'identifiers'}};
}
else {
- plugin_flush_one ($timeout, $args{'plugins'});
+ @ids = ($args{'identifiers'});
}
}
+ else {
+ @ids = (undef);
+ }
+
+ foreach my $plugin (@plugins) {
+ foreach my $id (@ids) {
+ _plugin_flush($plugin, $timeout, $id);
+ }
+ }
+}
+
+sub plugin_flush_one {
+ my $timeout = shift;
+ my $name = shift;
+
+ WARNING ("Collectd::plugin_flush_one is deprecated - "
+ . "use Collectd::plugin_flush instead.");
+
+ if (! (defined ($timeout) && defined ($name))) {
+ ERROR ("Usage: Collectd::plugin_flush_one(timeout, name)");
+ return;
+ }
+
+ plugin_flush (plugins => $name, timeout => $timeout);
+}
+
+sub plugin_flush_all {
+ my $timeout = shift;
+
+ WARNING ("Collectd::plugin_flush_all is deprecated - "
+ . "use Collectd::plugin_flush instead.");
+
+ if (! defined ($timeout)) {
+ ERROR ("Usage: Collectd::plugin_flush_all(timeout)");
+ return;
+ }
+
+ plugin_flush (timeout => $timeout);
+}
+
+sub _plugin_dispatch_config {
+ my $plugin = shift;
+ my $config = shift;
+
+ our $cb_name = undef;
+
+ if (! (defined ($plugin) && defined ($config))) {
+ return;
+ }
+
+ if (! defined $cf_callbacks{$plugin}) {
+ WARNING ("Found a configuration for the \"$plugin\" plugin, but "
+ . "the plugin isn't loaded or didn't register "
+ . "a configuration callback.");
+ return;
+ }
+
+ {
+ lock %cf_callbacks;
+ $cb_name = $cf_callbacks{$plugin};
+ }
+ call_by_name ($config);
}
1;
index 29fac3e9d2638414dabd17a5d28b0f746d275172..eb6e389e34b823d1df792f61f854c3ae183688eb 100644 (file)
use IO::Socket::UNIX;
use Regexp::Common (qw(number));
+our $Debug = 0;
+
return (1);
+sub _debug
+{
+ if (!$Debug)
+ {
+ return;
+ }
+ print @_;
+}
+
sub _create_socket
{
my $path = shift;
return ($sock);
} # _create_socket
-=head1 VALUE IDENTIFIER
+=head1 VALUE IDENTIFIERS
The values in the collectd are identified using an five-tuple (host, plugin,
plugin-instance, type, type-instance) where only plugin-instance and
return ($ident);
} # _parse_identifier
+sub _escape_argument
+{
+ my $string = shift;
+
+ if ($string =~ m/^\w+$/)
+ {
+ return ("$string");
+ }
+
+ $string =~ s#\\#\\\\#g;
+ $string =~ s#"#\\"#g;
+ $string = "\"$string\"";
+
+ return ($string);
+}
+
=head1 PUBLIC METHODS
=over 4
my %args = @_;
my $status;
- my $fh = $obj->{'sock'} or confess;
+ my $fh = $obj->{'sock'} or confess ('object has no filehandle');
my $msg;
my $identifier;
$identifier = _create_identifier (\%args) or return;
- $msg = "GETVAL $identifier\n";
- #print "-> $msg";
- send ($fh, $msg, 0) or confess ("send: $!");
+ $msg = 'GETVAL ' . _escape_argument ($identifier) . "\n";
+ _debug "-> $msg";
+ print $fh $msg;
- $msg = undef;
- recv ($fh, $msg, 1024, 0) or confess ("recv: $!");
- #print "<- $msg";
+ $msg = <$fh>;
+ chomp ($msg);
+ _debug "<- $msg\n";
($status, $msg) = split (' ', $msg, 2);
if ($status <= 0)
return;
}
- for (split (' ', $msg))
+ for (my $i = 0; $i < $status; $i++)
{
- my $entry = $_;
+ my $entry = <$fh>;
+ chomp ($entry);
+ _debug "<- $entry\n";
+
if ($entry =~ m/^(\w+)=NaN$/)
{
$ret->{$1} = undef;
Submits a value-list to the daemon. If the B<time> argument is omitted
C<time()> is used. The required argument B<values> is a reference to an array
of values that is to be submitted. The number of values must match the number
-of values expected for the given B<type> (see L<VALUE IDENTIFIER>), though this
-is checked by the daemon, not the Perl module. Also, gauge data-sources
+of values expected for the given B<type> (see L<VALUE IDENTIFIERS>), though
+this is checked by the daemon, not the Perl module. Also, gauge data-sources
(e.E<nbsp>g. system-load) may be C<undef>. Returns true upon success and false
otherwise.
if (defined $args{'interval'})
{
- $interval = ' interval=' . $args{'interval'};
+ $interval = ' interval='
+ . _escape_argument ($args{'interval'});
}
$identifier = _create_identifier (\%args) or return;
$values = join (':', $time, map { defined ($_) ? $_ : 'U' } (@{$args{'values'}}));
}
- $msg = "PUTVAL $identifier$interval $values\n";
- #print "-> $msg";
- send ($fh, $msg, 0) or confess ("send: $!");
- $msg = undef;
- recv ($fh, $msg, 1024, 0) or confess ("recv: $!");
- #print "<- $msg";
+ $msg = 'PUTVAL '
+ . _escape_argument ($identifier)
+ . $interval
+ . ' ' . _escape_argument ($values) . "\n";
+ _debug "-> $msg";
+ print $fh $msg;
+
+ $msg = <$fh>;
+ chomp ($msg);
+ _debug "<- $msg\n";
($status, $msg) = split (' ', $msg, 2);
return (1) if ($status == 0);
my $status;
my $fh = $obj->{'sock'} or confess;
- $msg = "LISTVAL\n";
- send ($fh, $msg, 0) or confess ("send: $!");
+ _debug "LISTVAL\n";
+ print $fh "LISTVAL\n";
$msg = <$fh>;
+ chomp ($msg);
+ _debug "<- $msg\n";
($status, $msg) = split (' ', $msg, 2);
if ($status < 0)
{
$msg = <$fh>;
chomp ($msg);
+ _debug "<- $msg\n";
($time, $ident) = split (' ', $msg, 2);
my $fh = $obj->{'sock'} or confess;
my $msg; # message sent to the socket
- my $opt_msg; # message of the notification
if (!$args{'message'})
{
$args{'time'} = time ();
}
- $opt_msg = $args{'message'};
- delete ($args{'message'});
-
$msg = 'PUTNOTIF '
- . join (' ', map { $_ . '=' . $args{$_} } (keys %args))
- . " message=$opt_msg\n";
+ . join (' ', map { $_ . '=' . _escape_argument ($args{$_}) } (keys %args))
+ . "\n";
- send ($fh, $msg, 0) or confess ("send: $!");
- $msg = undef;
- recv ($fh, $msg, 1024, 0) or confess ("recv: $!");
+ _debug "-> $msg";
+ print $fh $msg;
+
+ $msg = <$fh>;
+ chomp ($msg);
+ _debug "<- $msg\n";
($status, $msg) = split (' ', $msg, 2);
return (1) if ($status == 0);
return;
} # putnotif
-=item I<$obj>-E<gt>B<flush> (B<timeout> =E<gt> I<$timeout>, B<plugins> =E<gt> [...]);
+=item I<$obj>-E<gt>B<flush> (B<timeout> =E<gt> I<$timeout>, B<plugins> =E<gt> [...], B<identifier> =E<gt> [...]);
Flush cached data.
=item B<plugins>
-If this option is specified, only the selected plugins will be flushed.
+If this option is specified, only the selected plugins will be flushed. The
+argument is a reference to an array of strings.
+
+=item B<identifier>
+
+If this option is specified, only the given identifier(s) will be flushed. The
+argument is a reference to an array of identifiers. Identifiers, in this case,
+are hash references and have the members as outlined in L<VALUE IDENTIFIERS>.
=back
my $status = 0;
my $msg = "FLUSH";
- if ($args{'timeout'})
+ if (defined ($args{'timeout'}))
{
$msg .= " timeout=" . $args{'timeout'};
}
}
}
+ if ($args{'identifier'})
+ {
+ for (@{$args{'identifier'}})
+ {
+ my $identifier = $_;
+ my $ident_str;
+
+ if (ref ($identifier) ne 'HASH')
+ {
+ cluck ("The argument of the `identifier' "
+ . "option must be an array reference "
+ . "of hash references.");
+ return;
+ }
+
+ $ident_str = _create_identifier ($identifier);
+ if (!$ident_str)
+ {
+ return;
+ }
+
+ $msg .= ' identifier=' . _escape_argument ($ident_str);
+ }
+ }
+
$msg .= "\n";
- send ($fh, $msg, 0) or confess ("send: $!");
- $msg = undef;
- recv ($fh, $msg, 1024, 0) or confess ("recv: $!");
+ _debug "-> $msg";
+ print $fh $msg;
+
+ $msg = <$fh>;
+ chomp ($msg);
+ _debug "<- $msg\n";
($status, $msg) = split (' ', $msg, 2);
return (1) if ($status == 0);
return;
}
+sub error
+{
+ my $obj = shift;
+ if ($obj->{'error'})
+ {
+ return ($obj->{'error'});
+ }
+ return;
+}
+
=item I<$obj>-E<gt>destroy ();
Closes the socket before the object is destroyed. This function is also
diff --git a/configure.in b/configure.in
index bc4d3213b3bde7f5cd4ce5cecf3ba597ac1c9618..c71cfa4ef20bbef51b794077047b60256f8c63b3 100644 (file)
--- a/configure.in
+++ b/configure.in
*darwin*)
ac_system="Darwin"
;;
+ *openbsd*)
+ ac_system="OpenBSD"
+ ;;
*)
ac_system="unknown"
esac
AC_HEADER_SYS_WAIT
AC_HEADER_DIRENT
-AC_CHECK_HEADERS(stdint.h stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h)
+AC_CHECK_HEADERS(stdio.h stdint.h stdbool.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h)
# For ping library
AC_CHECK_HEADERS(netinet/in_systm.h, [], [],
fi
with_libkvm="no"
+AC_CHECK_LIB(kvm, kvm_getprocs, [with_kvm_getprocs="yes"], [with_kvm_getprocs="no"])
+if test "x$with_kvm_getprocs" = "xyes"
+then
+ AC_DEFINE(HAVE_LIBKVM_GETPROCS, 1,
+ [Define to 1 if you have the 'kvm' library with the 'kvm_getprocs' symbol (-lkvm)])
+ with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETPROCS, test "x$with_kvm_getprocs" = "xyes")
+
AC_CHECK_LIB(kvm, kvm_getswapinfo, [with_kvm_getswapinfo="yes"], [with_kvm_getswapinfo="no"])
if test "x$with_kvm_getswapinfo" = "xyes"
then
fi
AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETSWAPINFO, test "x$with_kvm_getswapinfo" = "xyes")
+AC_CHECK_LIB(kvm, kvm_nlist, [with_kvm_nlist="yes"], [with_kvm_nlist="no"])
+if test "x$with_kvm_nlist" = "xyes"
+then
+ AC_DEFINE(HAVE_LIBKVM_NLIST, 1,
+ [Define to 1 if you have the 'kvm' library with the 'kvm_nlist' symbol (-lkvm)])
+ with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_NLIST, test "x$with_kvm_nlist" = "xyes")
+
with_sensors_cflags=""
with_sensors_ldflags=""
AC_ARG_WITH(lm-sensors, [AS_HELP_STRING([--with-lm-sensors@<:@=PREFIX@:>@], [Path to lm_sensors.])],
AM_CONDITIONAL(BUILD_WITH_LIBOPING, test "x$with_liboping" = "xyes")
AM_CONDITIONAL(BUILD_WITH_OWN_LIBOPING, test "x$with_own_liboping" = "xyes")
+with_libowcapi_cppflags=""
+with_libowcapi_libs="-lowcapi"
+AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path to libowcapi.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libowcapi_cppflags="-I$withval/include"
+ with_libowcapi_libs="-L$withval/lib -lowcapi"
+ with_libowcapi="yes"
+ else
+ with_libowcapi="$withval"
+ fi
+],
+[
+ with_libowcapi="yes"
+])
+if test "x$with_libowcapi" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$with_libowcapi_cppflags"
+
+ AC_CHECK_HEADERS(owcapi.h, [with_libowcapi="yes"], [with_libowcapi="no (owcapi.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libowcapi" = "xyes"
+then
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ LDFLAGS="$with_libowcapi_libs"
+ CPPFLAGS="$with_libowcapi_cppflags"
+
+ AC_CHECK_LIB(owcapi, OW_get, [with_libowcapi="yes"], [with_libowcapi="no (libowcapi not found)"])
+
+ LDFLAGS="$SAVE_LDFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libowcapi" = "xyes"
+then
+ BUILD_WITH_LIBOWCAPI_CPPFLAGS="$with_libowcapi_cppflags"
+ BUILD_WITH_LIBOWCAPI_LIBS="$with_libowcapi_libs"
+ AC_SUBST(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBOWCAPI_LIBS)
+fi
+
+
AC_ARG_WITH(libpcap, [AS_HELP_STRING([--with-libpcap@<:@=PREFIX@:>@], [Path to libpcap.])],
[
if test "x$withval" != "xno" && test "x$withval" != "xyes"
[Wether or not to use the pcap library])
AM_CONDITIONAL(BUILD_WITH_LIBPCAP, test "x$with_libpcap" = "xyes")
+AC_ARG_WITH(libesmtp, [AS_HELP_STRING([--with-libesmtp@<:@=PREFIX@:>@], [Path to libesmtp.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ CPPFLAGS="$CPPFLAGS -I$withval/include -D_THREAD_SAFE"
+ with_libesmtp="yes"
+ else
+ with_libesmtp="$withval"
+ fi
+],
+[
+ with_libesmtp="yes"
+])
+if test "x$with_libesmtp" = "xyes"
+then
+ AC_CHECK_LIB(esmtp, smtp_create_session,
+ [
+ AC_DEFINE(HAVE_LIBESMTP, 1, [Define to 1 if you have the esmtp library (-lesmtp).])
+ ], [with_libesmtp="no (libesmtp not found)"])
+fi
+if test "x$with_libesmtp" = "xyes"
+then
+ AC_CHECK_HEADERS(libesmtp.h,
+ [
+ AC_DEFINE(HAVE_LIBESMTP_H, 1, [Define to 1 if you have the <libesmtp.h> header file.])
+ ], [with_libesmtp="no (libesmtp.h not found)"])
+fi
+if test "x$with_libesmtp" = "xyes"
+then
+ collect_libesmtp=1
+else
+ collect_libesmtp=0
+fi
+AC_DEFINE_UNQUOTED(COLLECT_LIBESMTP, [$collect_libesmtp],
+ [Wether or not to use the esmtp library])
+AM_CONDITIONAL(BUILD_WITH_LIBESMTP, test "x$with_libesmtp" = "xyes")
+
perl_interpreter="perl"
AC_ARG_WITH(libperl, [AS_HELP_STRING([--with-libperl@<:@=PREFIX@:>@], [Path to libperl.])],
[
- if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ if test -x "$withval"
+ then
+ perl_interpreter="$withval"
+ with_libperl="yes"
+ else if test "x$withval" != "xno" && test "x$withval" != "xyes"
then
LDFLAGS="$LDFLAGS -L$withval/lib"
CPPFLAGS="$CPPFLAGS -I$withval/include"
@@ -1519,7 +1628,7 @@ AC_ARG_WITH(libperl, [AS_HELP_STRING([--with-libperl@<:@=PREFIX@:>@], [Path to l
with_libperl="yes"
else
with_libperl="$withval"
- fi
+ fi; fi
],
[
with_libperl="yes"
perl_interpreter=`which "$perl_interpreter" 2> /dev/null`
if test -x "$perl_interpreter"
then
- AC_MSG_RESULT([yes])
+ AC_MSG_RESULT([yes ($perl_interpreter)])
else
perl_interpreter=""
AC_MSG_RESULT([no])
AC_LINK_IFELSE(
AC_LANG_PROGRAM(
[[
+#define PERL_NO_GET_CONTEXT
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
]],
[[
- PerlInterpreter *perl = NULL;
- Perl_load_module (perl, PERL_LOADMOD_NOIMPORT,
+ dTHX;
+ load_module (PERL_LOADMOD_NOIMPORT,
newSVpv ("Collectd::Plugin::FooBar", 24),
Nullsv);
]]),
fi
AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes")
+PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
+ [with_libnotify="yes"],
+ [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"])
+
with_libupsclient="no (pkg-config isn't available)"
with_libupsclient_cflags=""
with_libupsclient_libs=""
AC_SUBST(BUILD_WITH_OPENIPMI_LIBS)
fi
+dnl Check for libpq.
+with_pg_config="pg_config"
+with_libpq_includedir=""
+with_libpq_libdir=""
+with_libpq_cppflags=""
+with_libpq_ldflags=""
+AC_ARG_WITH(libpq, [AS_HELP_STRING([--with-libpq@<:@=PREFIX@:>@],
+ [Path to libpq.])],
+[
+ if test "x$withval" = "xno"
+ then
+ with_libpq="no"
+ else if test "x$withval" = "xyes"
+ then
+ with_libpq="yes"
+ else
+ if test -f "$withval" && test -x "$withval";
+ then
+ with_pg_config="$withval"
+ else if test -x "$withval/bin/pg_config"
+ then
+ with_pg_config="$withval/bin/pg_config"
+ fi; fi
+ with_libpq="yes"
+ fi; fi
+],
+[
+ with_libpq="yes"
+])
+if test "x$with_libpq" = "xyes"
+then
+ with_libpq_includedir=`$with_pg_config --includedir 2> /dev/null`
+ pg_config_status=$?
+
+ if test $pg_config_status -eq 0
+ then
+ if test -n "$with_libpq_includedir"; then
+ for dir in $with_libpq_includedir; do
+ with_libpq_cppflags="$with_libpq_cppflags -I$dir"
+ done
+ fi
+ else
+ AC_MSG_WARN([$with_pg_config returned with status $pg_config_status])
+ fi
+
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libpq_cppflags"
+
+ AC_CHECK_HEADERS(libpq-fe.h, [],
+ [with_libpq="no (libpq-fe.h not found)"], [])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libpq" = "xyes"
+then
+ with_libpq_libdir=`$with_pg_config --libdir 2> /dev/null`
+ pg_config_status=$?
+
+ if test $pg_config_status -eq 0
+ then
+ if test -n "$with_libpq_libdir"; then
+ for dir in $with_libpq_libdir; do
+ with_libpq_ldflags="$with_libpq_ldflags -L$dir"
+ done
+ fi
+ else
+ AC_MSG_WARN([$with_pg_config returned with status $pg_config_status])
+ fi
+
+ SAVE_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $with_libpq_ldflags"
+
+ AC_CHECK_LIB(pq, PQconnectdb,
+ [with_libpq="yes"],
+ [with_libpq="no (symbol 'PQconnectdb' not found)"])
+
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libpq" = "xyes"
+then
+ BUILD_WITH_LIBPQ_CPPFLAGS="$with_libpq_cppflags"
+ BUILD_WITH_LIBPQ_LDFLAGS="$with_libpq_ldflags"
+ AC_SUBST(BUILD_WITH_LIBPQ_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBPQ_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes")
+
dnl Check for libvirt and libxml2 libraries.
with_libxml2="no (pkg-config isn't available)"
with_libxml2_cflags=""
plugin_swap="no"
plugin_tape="no"
plugin_tcpconns="no"
+plugin_thermal="no"
plugin_users="no"
plugin_vmem="no"
plugin_vserver="no"
plugin_serial="yes"
plugin_swap="yes"
plugin_tcpconns="yes"
+ plugin_thermal="yes"
plugin_vmem="yes"
plugin_vserver="yes"
plugin_wireless="yes"
fi
fi
+if test "x$ac_system" = "xOpenBSD"
+then
+ plugin_tcpconns="yes"
+fi
+
# Mac OS X devices
if test "x$with_libiokit" = "xyes"
then
plugin_processes="yes"
fi
+if test "x$with_kvm_getprocs" = "xyes"
+then
+ plugin_processes="yes"
+fi
+
if test "x$with_kvm_getswapinfo" = "xyes"
then
plugin_swap="yes"
fi
+if test "x$with_kvm_nlist" = "xyes"
+then
+ plugin_tcpconns="yes"
+fi
+
if test "x$have_getutent" = "xyes"
then
plugin_users="yes"
AC_PLUGIN([cpu], [$plugin_cpu], [CPU usage statistics])
AC_PLUGIN([cpufreq], [$plugin_cpufreq], [CPU frequency statistics])
AC_PLUGIN([csv], [yes], [CSV output plugin])
+AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
AC_PLUGIN([df], [$plugin_df], [Filesystem usage statistics])
AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics])
AC_PLUGIN([dns], [$with_libpcap], [DNS traffic analysis])
AC_PLUGIN([email], [yes], [EMail statistics])
AC_PLUGIN([entropy], [$plugin_entropy], [Entropy statistics])
AC_PLUGIN([exec], [yes], [Execution of external programs])
+AC_PLUGIN([filecount], [yes], [Count files in directories])
AC_PLUGIN([hddtemp], [yes], [Query hddtempd])
AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics])
AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters])
AC_PLUGIN([network], [yes], [Network communication plugin])
AC_PLUGIN([nfs], [$plugin_nfs], [NFS statistics])
AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics])
+AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier])
AC_PLUGIN([ntpd], [yes], [NTPd statistics])
AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
+AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics])
AC_PLUGIN([perl], [$plugin_perl], [Embed a Perl interpreter])
AC_PLUGIN([ping], [$with_liboping], [Network latency statistics])
+AC_PLUGIN([postgresql], [$with_libpq], [PostgreSQL database statistics])
AC_PLUGIN([powerdns], [yes], [PowerDNS statistics])
AC_PLUGIN([processes], [$plugin_processes], [Process statistics])
AC_PLUGIN([rrdtool], [$with_rrdtool], [RRDTool output plugin])
AC_PLUGIN([tape], [$plugin_tape], [Tape drive statistics])
AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics])
AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics])
+AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI thermal zone statistics])
AC_PLUGIN([unixsock], [yes], [Unixsock communication plugin])
AC_PLUGIN([users], [$plugin_users], [User statistics])
AC_PLUGIN([uuid], [yes], [UUID as hostname plugin])
Configuration:
Libraries:
- libcurl . . . . . . $with_libcurl
- libiokit . . . . . $with_libiokit
- libiptc . . . . . . $with_libiptc
- libkstat . . . . . $with_kstat
- libkvm . . . . . . $with_libkvm
- libmysql . . . . . $with_libmysql
- libnetlink . . . . $with_libnetlink
- libnetsnmp . . . . $with_libnetsnmp
- liboconfig . . . . $with_liboconfig
- libopenipmi . . . . $with_libopenipmipthread
- liboping . . . . . $with_liboping
- libpcap . . . . . . $with_libpcap
- libperl . . . . . . $with_libperl
- libpthread . . . . $with_libpthread
- librrd . . . . . . $with_rrdtool
- libsensors . . . . $with_lm_sensors
- libstatgrab . . . . $with_libstatgrab
- libupsclient . . . $with_libupsclient
- libvirt . . . . . . $with_libvirt
- libxml2 . . . . . . $with_libxml2
- libxmms . . . . . . $with_libxmms
+ libcurl . . . . . . . $with_libcurl
+ libesmtp . . . . . . $with_libesmtp
+ libiokit . . . . . . $with_libiokit
+ libiptc . . . . . . . $with_libiptc
+ libkstat . . . . . . $with_kstat
+ libkvm . . . . . . . $with_libkvm
+ libmysql . . . . . . $with_libmysql
+ libnetlink . . . . . $with_libnetlink
+ libnetsnmp . . . . . $with_libnetsnmp
+ libnotify . . . . . . $with_libnotify
+ liboconfig . . . . . $with_liboconfig
+ libopenipmi . . . . . $with_libopenipmipthread
+ liboping . . . . . . $with_liboping
+ libpcap . . . . . . . $with_libpcap
+ libperl . . . . . . . $with_libperl
+ libpthread . . . . . $with_libpthread
+ libpq . . . . . . . . $with_libpq
+ librrd . . . . . . . $with_rrdtool
+ libsensors . . . . . $with_lm_sensors
+ libstatgrab . . . . . $with_libstatgrab
+ libupsclient . . . . $with_libupsclient
+ libvirt . . . . . . . $with_libvirt
+ libxml2 . . . . . . . $with_libxml2
+ libxmms . . . . . . . $with_libxmms
Features:
- daemon mode . . . . $enable_daemon
- debug . . . . . . . $enable_debug
+ daemon mode . . . . . $enable_daemon
+ debug . . . . . . . . $enable_debug
Bindings:
- perl . . . . . . . $with_perl_bindings
+ perl . . . . . . . . $with_perl_bindings
Modules:
- apache . . . . . . $enable_apache
- apcups . . . . . . $enable_apcups
- apple_sensors . . . $enable_apple_sensors
- ascent . . . . . . $enable_ascent
- battery . . . . . . $enable_battery
- cpu . . . . . . . . $enable_cpu
- cpufreq . . . . . . $enable_cpufreq
- csv . . . . . . . . $enable_csv
- df . . . . . . . . $enable_df
- disk . . . . . . . $enable_disk
- dns . . . . . . . . $enable_dns
- email . . . . . . . $enable_email
- entropy . . . . . . $enable_entropy
- exec . . . . . . . $enable_exec
- hddtemp . . . . . . $enable_hddtemp
- interface . . . . . $enable_interface
- iptables . . . . . $enable_iptables
- ipmi . . . . . . . $enable_ipmi
- ipvs . . . . . . . $enable_ipvs
- irq . . . . . . . . $enable_irq
- libvirt . . . . . . $enable_libvirt
- load . . . . . . . $enable_load
- logfile . . . . . . $enable_logfile
- mbmon . . . . . . . $enable_mbmon
- memcached . . . . . $enable_memcached
- memory . . . . . . $enable_memory
- multimeter . . . . $enable_multimeter
- mysql . . . . . . . $enable_mysql
- netlink . . . . . . $enable_netlink
- network . . . . . . $enable_network
- nfs . . . . . . . . $enable_nfs
- nginx . . . . . . . $enable_nginx
- ntpd . . . . . . . $enable_ntpd
- nut . . . . . . . . $enable_nut
- perl . . . . . . . $enable_perl
- ping . . . . . . . $enable_ping
- powerdns . . . . . $enable_powerdns
- processes . . . . . $enable_processes
- rrdtool . . . . . . $enable_rrdtool
- sensors . . . . . . $enable_sensors
- serial . . . . . . $enable_serial
- snmp . . . . . . . $enable_snmp
- swap . . . . . . . $enable_swap
- syslog . . . . . . $enable_syslog
- tail . . . . . . . $enable_tail
- tape . . . . . . . $enable_tape
- tcpconns . . . . . $enable_tcpconns
- teamspeak2 . . . . $enable_teamspeak2
- unixsock . . . . . $enable_unixsock
- users . . . . . . . $enable_users
- uuid . . . . . . . $enable_uuid
- vmem . . . . . . . $enable_vmem
- vserver . . . . . . $enable_vserver
- wireless . . . . . $enable_wireless
- xmms . . . . . . . $enable_xmms
+ apache . . . . . . . $enable_apache
+ apcups . . . . . . . $enable_apcups
+ apple_sensors . . . . $enable_apple_sensors
+ ascent . . . . . . . $enable_ascent
+ battery . . . . . . . $enable_battery
+ cpu . . . . . . . . . $enable_cpu
+ cpufreq . . . . . . . $enable_cpufreq
+ csv . . . . . . . . . $enable_csv
+ df . . . . . . . . . $enable_df
+ disk . . . . . . . . $enable_disk
+ dns . . . . . . . . . $enable_dns
+ email . . . . . . . . $enable_email
+ entropy . . . . . . . $enable_entropy
+ exec . . . . . . . . $enable_exec
+ filecount . . . . . . $enable_filecount
+ hddtemp . . . . . . . $enable_hddtemp
+ interface . . . . . . $enable_interface
+ iptables . . . . . . $enable_iptables
+ ipmi . . . . . . . . $enable_ipmi
+ ipvs . . . . . . . . $enable_ipvs
+ irq . . . . . . . . . $enable_irq
+ libvirt . . . . . . . $enable_libvirt
+ load . . . . . . . . $enable_load
+ logfile . . . . . . . $enable_logfile
+ mbmon . . . . . . . . $enable_mbmon
+ memcached . . . . . . $enable_memcached
+ memory . . . . . . . $enable_memory
+ multimeter . . . . . $enable_multimeter
+ mysql . . . . . . . . $enable_mysql
+ netlink . . . . . . . $enable_netlink
+ network . . . . . . . $enable_network
+ nfs . . . . . . . . . $enable_nfs
+ nginx . . . . . . . . $enable_nginx
+ notify_desktop . . . $enable_notify_desktop
+ notify_email . . . . $enable_notify_email
+ ntpd . . . . . . . . $enable_ntpd
+ nut . . . . . . . . . $enable_nut
+ onewire . . . . . . . $enable_onewire
+ perl . . . . . . . . $enable_perl
+ ping . . . . . . . . $enable_ping
+ postgresql . . . . . $enable_postgresql
+ powerdns . . . . . . $enable_powerdns
+ processes . . . . . . $enable_processes
+ rrdtool . . . . . . . $enable_rrdtool
+ sensors . . . . . . . $enable_sensors
+ serial . . . . . . . $enable_serial
+ snmp . . . . . . . . $enable_snmp
+ swap . . . . . . . . $enable_swap
+ syslog . . . . . . . $enable_syslog
+ tail . . . . . . . . $enable_tail
+ tape . . . . . . . . $enable_tape
+ tcpconns . . . . . . $enable_tcpconns
+ teamspeak2 . . . . . $enable_teamspeak2
+ thermal . . . . . . . $enable_thermal
+ unixsock . . . . . . $enable_unixsock
+ users . . . . . . . . $enable_users
+ uuid . . . . . . . . $enable_uuid
+ vmem . . . . . . . . $enable_vmem
+ vserver . . . . . . . $enable_vserver
+ wireless . . . . . . $enable_wireless
+ xmms . . . . . . . . $enable_xmms
EOF
diff --git a/contrib/collection.cgi b/contrib/collection.cgi
index 753b56e43a878efde2dfc28863502118b13b88ab..fb4947dcc529f7cba32701b05a7f5f1857617c16 100755 (executable)
--- a/contrib/collection.cgi
+++ b/contrib/collection.cgi
'GPRINT:ping_avg:AVERAGE:%4.1lf ms Avg,',
'GPRINT:ping_max:MAX:%4.1lf ms Max,',
'GPRINT:ping_avg:LAST:%4.1lf ms Last'],
+ pg_blks => ['DEF:pg_blks_avg={file}:value:AVERAGE',
+ 'DEF:pg_blks_min={file}:value:MIN',
+ 'DEF:pg_blks_max={file}:value:MAX',
+ "AREA:pg_blks_max#$HalfBlue",
+ "AREA:pg_blks_min#$Canvas",
+ "LINE1:pg_blks_avg#$FullBlue:Blocks",
+ 'GPRINT:pg_blks_min:MIN:%4.1lf%s Min,',
+ 'GPRINT:pg_blks_avg:AVERAGE:%4.1lf%s Avg,',
+ 'GPRINT:pg_blks_max:MAX:%4.1lf%s Max,',
+ 'GPRINT:pg_blks_avg:LAST:%4.1lf%s Last'],
+ pg_db_size => ['DEF:pg_db_size_avg={file}:value:AVERAGE',
+ 'DEF:pg_db_size_min={file}:value:MIN',
+ 'DEF:pg_db_size_max={file}:value:MAX',
+ "AREA:pg_db_size_max#$HalfBlue",
+ "AREA:pg_db_size_min#$Canvas",
+ "LINE1:pg_db_size_avg#$FullBlue:Bytes",
+ 'GPRINT:pg_db_size_min:MIN:%4.1lf%s Min,',
+ 'GPRINT:pg_db_size_avg:AVERAGE:%4.1lf%s Avg,',
+ 'GPRINT:pg_db_size_max:MAX:%4.1lf%s Max,',
+ 'GPRINT:pg_db_size_avg:LAST:%4.1lf%s Last'],
+ pg_n_tup_c => ['DEF:pg_n_tup_avg={file}:value:AVERAGE',
+ 'DEF:pg_n_tup_min={file}:value:MIN',
+ 'DEF:pg_n_tup_max={file}:value:MAX',
+ "AREA:pg_n_tup_max#$HalfBlue",
+ "AREA:pg_n_tup_min#$Canvas",
+ "LINE1:pg_n_tup_avg#$FullBlue:Tuples",
+ 'GPRINT:pg_n_tup_min:MIN:%4.1lf%s Min,',
+ 'GPRINT:pg_n_tup_avg:AVERAGE:%4.1lf%s Avg,',
+ 'GPRINT:pg_n_tup_max:MAX:%4.1lf%s Max,',
+ 'GPRINT:pg_n_tup_avg:LAST:%4.1lf%s Last'],
+ pg_n_tup_g => ['DEF:pg_n_tup_avg={file}:value:AVERAGE',
+ 'DEF:pg_n_tup_min={file}:value:MIN',
+ 'DEF:pg_n_tup_max={file}:value:MAX',
+ "AREA:pg_n_tup_max#$HalfBlue",
+ "AREA:pg_n_tup_min#$Canvas",
+ "LINE1:pg_n_tup_avg#$FullBlue:Tuples",
+ 'GPRINT:pg_n_tup_min:MIN:%4.1lf%s Min,',
+ 'GPRINT:pg_n_tup_avg:AVERAGE:%4.1lf%s Avg,',
+ 'GPRINT:pg_n_tup_max:MAX:%4.1lf%s Max,',
+ 'GPRINT:pg_n_tup_avg:LAST:%4.1lf%s Last'],
+ pg_numbackends => ['DEF:pg_numbackends_avg={file}:value:AVERAGE',
+ 'DEF:pg_numbackends_min={file}:value:MIN',
+ 'DEF:pg_numbackends_max={file}:value:MAX',
+ "AREA:pg_numbackends_max#$HalfBlue",
+ "AREA:pg_numbackends_min#$Canvas",
+ "LINE1:pg_numbackends_avg#$FullBlue:Backends",
+ 'GPRINT:pg_numbackends_min:MIN:%4.1lf%s Min,',
+ 'GPRINT:pg_numbackends_avg:AVERAGE:%4.1lf%s Avg,',
+ 'GPRINT:pg_numbackends_max:MAX:%4.1lf%s Max,',
+ 'GPRINT:pg_numbackends_avg:LAST:%4.1lf%s Last'],
+ pg_scan => ['DEF:pg_scan_avg={file}:value:AVERAGE',
+ 'DEF:pg_scan_min={file}:value:MIN',
+ 'DEF:pg_scan_max={file}:value:MAX',
+ "AREA:pg_scan_max#$HalfBlue",
+ "AREA:pg_scan_min#$Canvas",
+ "LINE1:pg_scan_avg#$FullBlue:Scans",
+ 'GPRINT:pg_scan_min:MIN:%4.1lf%s Min,',
+ 'GPRINT:pg_scan_avg:AVERAGE:%4.1lf%s Avg,',
+ 'GPRINT:pg_scan_max:MAX:%4.1lf%s Max,',
+ 'GPRINT:pg_scan_avg:LAST:%4.1lf%s Last'],
+ pg_xact => ['DEF:pg_xact_avg={file}:value:AVERAGE',
+ 'DEF:pg_xact_min={file}:value:MIN',
+ 'DEF:pg_xact_max={file}:value:MAX',
+ "AREA:pg_xact_max#$HalfBlue",
+ "AREA:pg_xact_min#$Canvas",
+ "LINE1:pg_xact_avg#$FullBlue:Transactions",
+ 'GPRINT:pg_xact_min:MIN:%4.1lf%s Min,',
+ 'GPRINT:pg_xact_avg:AVERAGE:%4.1lf%s Avg,',
+ 'GPRINT:pg_xact_max:MAX:%4.1lf%s Max,',
+ 'GPRINT:pg_xact_avg:LAST:%4.1lf%s Last'],
power => ['-v', 'Watt',
'DEF:avg={file}:value:AVERAGE',
'DEF:min={file}:value:MIN',
diff --git a/contrib/cussh.pl b/contrib/cussh.pl
index f95d54d2010eac76bd1e0a134d17b23fdd9fe383..2ec6308bd90ae130be1de8907cb163139c55de67 100755 (executable)
--- a/contrib/cussh.pl
+++ b/contrib/cussh.pl
elsif ($option eq "timeout") {
$args{"timeout"} = $value;
}
+ elsif ($option eq "identifier") {
+ my $id = getid (\$value);
+ if (!$id)
+ {
+ print STDERR "Not a valid identifier: \"$value\"\n";
+ next;
+ }
+ push @{$args{"identifier"}}, $id;
+ }
else {
print STDERR "Invalid option \"$option\".\n";
return;
index 240c6c3a8932cd0f8c31e485edf202ca96e93d38..f68cc1ac85c090792efa1bfe9433272327b378fa 100644 (file)
vl.values = values;
vl.values_len = 1;
vl.time = time (NULL);
- strcpy (vl.host, hostname_g);
- strcpy (vl.plugin, "myplugin");
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "myplugin", sizeof (vl.plugin));
/* optionally set vl.plugin_instance and vl.type_instance to reasonable
* values (default: "") */
diff --git a/src/Makefile.am b/src/Makefile.am
index 67a79b80ccd714213b6536b57c9d7c2a0b3fb950..f93c5065f5c17c7e2474ee5d0a1c66f2d7004211 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
AM_CPPFLAGS += -DPIDFILE='"${localstatedir}/run/${PACKAGE_NAME}.pid"'
endif
AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
+AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
sbin_PROGRAMS = collectd collectdmon
bin_PROGRAMS = collectd-nagios
plugin.c plugin.h \
utils_avltree.c utils_avltree.h \
utils_cache.c utils_cache.h \
+ utils_complain.c utils_complain.h \
utils_ignorelist.c utils_ignorelist.h \
utils_llist.c utils_llist.h \
utils_tail_match.c utils_tail_match.h \
types_list.c types_list.h
collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
-collectd_CFLAGS =
+collectd_CFLAGS = $(AM_CFLAGS)
collectd_LDFLAGS = -export-dynamic
collectd_LDADD =
collectd_DEPENDENCIES =
pkglib_LTLIBRARIES += apache.la
apache_la_SOURCES = apache.c
apache_la_LDFLAGS = -module -avoid-version
-apache_la_CFLAGS =
+apache_la_CFLAGS = $(AM_CFLAGS)
apache_la_LIBADD =
collectd_LDADD += "-dlopen" apache.la
if BUILD_WITH_LIBCURL
pkglib_LTLIBRARIES += ascent.la
ascent_la_SOURCES = ascent.c
ascent_la_LDFLAGS = -module -avoid-version
-ascent_la_CFLAGS = $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+ascent_la_CFLAGS = $(AM_CFLAGS) \
+ $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
ascent_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
collectd_LDADD += "-dlopen" apache.la
collectd_DEPENDENCIES += ascent.la
if BUILD_PLUGIN_CPU
pkglib_LTLIBRARIES += cpu.la
cpu_la_SOURCES = cpu.c
-cpu_la_CFLAGS =
+cpu_la_CFLAGS = $(AM_CFLAGS)
cpu_la_LDFLAGS = -module -avoid-version
cpu_la_LIBADD =
if BUILD_WITH_LIBKSTAT
if BUILD_PLUGIN_DISK
pkglib_LTLIBRARIES += disk.la
disk_la_SOURCES = disk.c
-disk_la_CFLAGS =
+disk_la_CFLAGS = $(AM_CFLAGS)
disk_la_LDFLAGS = -module -avoid-version
disk_la_LIBADD =
if BUILD_WITH_LIBKSTAT
if BUILD_PLUGIN_EXEC
pkglib_LTLIBRARIES += exec.la
exec_la_SOURCES = exec.c \
+ utils_parse_option.h utils_parse_option.c \
utils_cmd_putnotif.c utils_cmd_putnotif.h \
utils_cmd_putval.c utils_cmd_putval.h
exec_la_LDFLAGS = -module -avoid-version
collectd_DEPENDENCIES += exec.la
endif
+if BUILD_PLUGIN_FILECOUNT
+pkglib_LTLIBRARIES += filecount.la
+filecount_la_SOURCES = filecount.c
+filecount_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" filecount.la
+collectd_DEPENDENCIES += filecount.la
+endif
+
if BUILD_PLUGIN_HDDTEMP
pkglib_LTLIBRARIES += hddtemp.la
hddtemp_la_SOURCES = hddtemp.c
if BUILD_PLUGIN_INTERFACE
pkglib_LTLIBRARIES += interface.la
interface_la_SOURCES = interface.c
-interface_la_CFLAGS =
+interface_la_CFLAGS = $(AM_CFLAGS)
interface_la_LDFLAGS = -module -avoid-version
interface_la_LIBADD =
collectd_LDADD += "-dlopen" interface.la
if BUILD_PLUGIN_IPMI
pkglib_LTLIBRARIES += ipmi.la
ipmi_la_SOURCES = ipmi.c
-ipmi_la_CFLAGS = $(BUILD_WITH_OPENIPMI_CFLAGS)
+ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS)
ipmi_la_LDFLAGS = -module -avoid-version
ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS)
collectd_LDADD += "-dlopen" ipmi.la
if BUILD_PLUGIN_LIBVIRT
pkglib_LTLIBRARIES += libvirt.la
libvirt_la_SOURCES = libvirt.c
-libvirt_la_CFLAGS = $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+libvirt_la_CFLAGS = $(AM_CFLAGS) \
+ $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
libvirt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
libvirt_la_LDFLAGS = -module -avoid-version
collectd_LDADD += "-dlopen" libvirt.la
if BUILD_PLUGIN_LOAD
pkglib_LTLIBRARIES += load.la
load_la_SOURCES = load.c
-load_la_CFLAGS =
+load_la_CFLAGS = $(AM_CFLAGS)
load_la_LDFLAGS = -module -avoid-version
load_la_LIBADD =
collectd_LDADD += "-dlopen" load.la
pkglib_LTLIBRARIES += memcached.la
memcached_la_SOURCES = memcached.c
memcached_la_LDFLAGS = -module -avoid-version
-memcached_la_CFLAGS =
memcached_la_LIBADD =
if BUILD_WITH_LIBSOCKET
memcached_la_LDFLAGS += -lsocket
if BUILD_PLUGIN_MEMORY
pkglib_LTLIBRARIES += memory.la
memory_la_SOURCES = memory.c
-memory_la_CFLAGS =
+memory_la_CFLAGS = $(AM_CFLAGS)
memory_la_LDFLAGS = -module -avoid-version
memory_la_LIBADD =
collectd_LDADD += "-dlopen" memory.la
pkglib_LTLIBRARIES += mysql.la
mysql_la_SOURCES = mysql.c
mysql_la_LDFLAGS = -module -avoid-version
-mysql_la_CFLAGS =
+mysql_la_CFLAGS = $(AM_CFLAGS)
mysql_la_LIBADD =
collectd_LDADD += "-dlopen" mysql.la
if BUILD_WITH_LIBMYSQL
pkglib_LTLIBRARIES += netlink.la
netlink_la_SOURCES = netlink.c
netlink_la_LDFLAGS = -module -avoid-version
-netlink_la_CFLAGS = $(BUILD_WITH_LIBNETLINK_CFLAGS)
+netlink_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBNETLINK_CFLAGS)
netlink_la_LIBADD = $(BUILD_WITH_LIBNETLINK_LIBS)
collectd_LDADD += "-dlopen" netlink.la
collectd_DEPENDENCIES += netlink.la
collectd_DEPENDENCIES += nginx.la
endif
+if BUILD_PLUGIN_NOTIFY_DESKTOP
+pkglib_LTLIBRARIES += notify_desktop.la
+notify_desktop_la_SOURCES = notify_desktop.c
+notify_desktop_la_CFLAGS = $(AM_CFLAGS) $(LIBNOTIFY_CFLAGS)
+notify_desktop_la_LDFLAGS = -module -avoid-version $(LIBNOTIFY_LIBS)
+collectd_LDADD += "-dlopen" notify_desktop.la
+collectd_DEPENDENCIES += notify_desktop.la
+endif
+
+if BUILD_PLUGIN_NOTIFY_EMAIL
+pkglib_LTLIBRARIES += notify_email.la
+notify_email_la_SOURCES = notify_email.c
+notify_email_la_LDFLAGS = -L/usr/local/lib -lesmtp -lssl -lcrypto -pthread -module -avoid-version
+collectd_LDADD += "-dlopen" notify_email.la
+collectd_DEPENDENCIES += notify_email.la
+endif
+
if BUILD_PLUGIN_NTPD
pkglib_LTLIBRARIES += ntpd.la
ntpd_la_SOURCES = ntpd.c
collectd_DEPENDENCIES += nut.la
endif
+if BUILD_PLUGIN_ONEWIRE
+pkglib_LTLIBRARIES += onewire.la
+onewire_la_SOURCES = onewire.c
+onewire_la_CFLAGS = $(AM_CFLAGS)
+onewire_la_CPPFLAGS = $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
+onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
+onewire_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" onewire.la
+collectd_DEPENDENCIES += onewire.la
+endif
+
if BUILD_PLUGIN_PERL
pkglib_LTLIBRARIES += perl.la
perl_la_SOURCES = perl.c
+# Despite C99 providing the "bool" type thru stdbool.h, Perl defines its own
+# version of that type if HAS_BOOL is not defined... *sigh*
+perl_la_CPPFLAGS = $(AM_CPPFLAGS) -DHAS_BOOL=1
perl_la_CFLAGS = $(AM_CFLAGS) \
- $(PERL_CFLAGS) \
- -DXS_VERSION=\"$(VERSION)\" -DVERSION=\"$(VERSION)\"
+ $(PERL_CFLAGS) \
+ -DXS_VERSION=\"$(VERSION)\" -DVERSION=\"$(VERSION)\"
perl_la_LDFLAGS = -module -avoid-version \
- $(PERL_LDFLAGS)
+ $(PERL_LDFLAGS)
collectd_LDADD += "-dlopen" perl.la
collectd_DEPENDENCIES += perl.la
endif
collectd_DEPENDENCIES += ping.la
endif
+if BUILD_PLUGIN_POSTGRESQL
+pkglib_LTLIBRARIES += postgresql.la
+postgresql_la_SOURCES = postgresql.c
+postgresql_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBPQ_CPPFLAGS)
+postgresql_la_LDFLAGS = -module -avoid-version \
+ $(BUILD_WITH_LIBPQ_LDFLAGS) -lpq
+collectd_LDADD += "-dlopen" postgresql.la
+collectd_DEPENDENCIES += postgresql.la
+endif
+
if BUILD_PLUGIN_POWERDNS
pkglib_LTLIBRARIES += powerdns.la
powerdns_la_SOURCES = powerdns.c
pkglib_LTLIBRARIES += processes.la
processes_la_SOURCES = processes.c
processes_la_LDFLAGS = -module -avoid-version
+processes_la_LIBADD =
collectd_LDADD += "-dlopen" processes.la
collectd_DEPENDENCIES += processes.la
+if BUILD_WITH_LIBKVM_GETPROCS
+processes_la_LIBADD += -lkvm
+endif
endif
if BUILD_PLUGIN_RRDTOOL
pkglib_LTLIBRARIES += rrdtool.la
rrdtool_la_SOURCES = rrdtool.c
rrdtool_la_LDFLAGS = -module -avoid-version
-rrdtool_la_CFLAGS = $(BUILD_WITH_LIBRRD_CFLAGS)
+rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
collectd_LDADD += "-dlopen" rrdtool.la
collectd_DEPENDENCIES += rrdtool.la
if BUILD_PLUGIN_SENSORS
pkglib_LTLIBRARIES += sensors.la
sensors_la_SOURCES = sensors.c
-sensors_la_CFLAGS = $(BUILD_WITH_LIBSENSORS_CFLAGS)
+sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS)
sensors_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBSENSORS_LDFLAGS)
sensors_la_LIBADD = -lsensors
collectd_LDADD += "-dlopen" sensors.la
pkglib_LTLIBRARIES += snmp.la
snmp_la_SOURCES = snmp.c
snmp_la_LDFLAGS = -module -avoid-version
-snmp_la_CFLAGS =
+snmp_la_CFLAGS = $(AM_CFLAGS)
snmp_la_LIBADD =
if BUILD_WITH_LIBNETSNMP
snmp_la_CFLAGS += $(BUILD_WITH_LIBSNMP_CFLAGS)
if BUILD_PLUGIN_SWAP
pkglib_LTLIBRARIES += swap.la
swap_la_SOURCES = swap.c
-swap_la_CFLAGS =
+swap_la_CFLAGS = $(AM_CFLAGS)
swap_la_LDFLAGS = -module -avoid-version
swap_la_LIBADD =
collectd_LDADD += "-dlopen" swap.la
pkglib_LTLIBRARIES += tcpconns.la
tcpconns_la_SOURCES = tcpconns.c
tcpconns_la_LDFLAGS = -module -avoid-version
+tcpconns_la_LIBADD =
collectd_LDADD += "-dlopen" tcpconns.la
collectd_DEPENDENCIES += tcpconns.la
+if BUILD_WITH_LIBKVM_NLIST
+tcpconns_la_LIBADD += -lkvm
+endif
endif
if BUILD_PLUGIN_TEAMSPEAK2
collectd_DEPENDENCIES += teamspeak2.la
endif
+if BUILD_PLUGIN_THERMAL
+pkglib_LTLIBRARIES += thermal.la
+thermal_la_SOURCES = thermal.c
+thermal_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" thermal.la
+collectd_DEPENDENCIES += thermal.la
+endif
+
if BUILD_PLUGIN_UNIXSOCK
pkglib_LTLIBRARIES += unixsock.la
unixsock_la_SOURCES = unixsock.c \
+ utils_parse_option.h utils_parse_option.c \
utils_cmd_flush.h utils_cmd_flush.c \
utils_cmd_getval.h utils_cmd_getval.c \
utils_cmd_listval.h utils_cmd_listval.c \
if BUILD_PLUGIN_USERS
pkglib_LTLIBRARIES += users.la
users_la_SOURCES = users.c
-users_la_CFLAGS =
+users_la_CFLAGS = $(AM_CFLAGS)
users_la_LDFLAGS = -module -avoid-version
users_la_LIBADD =
if BUILD_WITH_LIBSTATGRAB
EXTRA_DIST += collectd-email.pod collectd-exec.pod collectd-nagios.pod \
collectd-perl.pod collectd-snmp.pod collectd-unixsock.pod \
- collectd.conf.pod collectd.pod collectdmon.pod types.db.pod
+ collectd.conf.pod collectd.pod collectdmon.pod types.db.pod \
+ postgresql_default.conf
.pod.1:
- pod2man --release=$(VERSION) --center=$(PACKAGE) $< >.pod2man.tmp 2>/dev/null && mv -f .pod2man.tmp $@ || true
+ pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
+ >.pod2man.tmp 2>/dev/null && mv -f .pod2man.tmp $@ || true
+ if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
+ then \
+ echo "$@ has some POD errors!"; false; \
+ fi
.pod.5:
- pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< >.pod2man.tmp 2>/dev/null && mv -f .pod2man.tmp $@ || true
+ pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< \
+ >.pod2man.tmp 2>/dev/null && mv -f .pod2man.tmp $@ || true
+ if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
+ then \
+ echo "$@ has some POD errors!"; false; \
+ fi
install-exec-hook:
$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
$(INSTALL) -m 0640 collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf; \
fi; \
cp -f $(srcdir)/types.db $(DESTDIR)$(pkglibdir)/;
+ $(INSTALL) -D -m 0644 $(srcdir)/postgresql_default.conf \
+ $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
diff --git a/src/apache.c b/src/apache.c
index a2f41f4bdab52f017827073d5373ae64c08ea5ca..c6bf8addfed4d6918c7345e5839b3a92105a4c3f 100644 (file)
--- a/src/apache.c
+++ b/src/apache.c
{
int status;
- status = snprintf (credentials, sizeof (credentials), "%s:%s",
+ status = ssnprintf (credentials, sizeof (credentials), "%s:%s",
user, (pass == NULL) ? "" : pass);
if (status >= sizeof (credentials))
{
"truncated.");
return (-1);
}
- credentials[sizeof (credentials) - 1] = '\0';
curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
}
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "apache", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_instance != NULL)
- {
- strncpy (vl.type_instance, type_instance,
+ sstrncpy (vl.type_instance, type_instance,
sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- }
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void submit_counter */
static void submit_gauge (const char *type, const char *type_instance,
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "apache", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_instance != NULL)
- {
- strncpy (vl.type_instance, type_instance,
+ sstrncpy (vl.type_instance, type_instance,
sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- }
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void submit_counter */
static void submit_scoreboard (char *buf)
diff --git a/src/apcups.c b/src/apcups.c
index c948f5a165b8b5f14d298601de99c90a4cc045e2..227c703c558fef41b8b338079c27321b281f5f48 100644 (file)
--- a/src/apcups.c
+++ b/src/apcups.c
assert ((port > 0x00000000) && (port <= 0x0000FFFF));
/* Convert the port to a string */
- snprintf (port_str, 8, "%i", port);
- port_str[7] = '\0';
+ ssnprintf (port_str, sizeof (port_str), "%i", port);
/* Resolve name */
memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "apcups", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
- strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
}
static void apc_submit (struct apc_detail_s *apcups_detail)
diff --git a/src/apple_sensors.c b/src/apple_sensors.c
index 5e957b6f88a9e9b302634b6aa0f053118c6db020..d312027670a2b34c68bd2974d90095a93201b168 100644 (file)
--- a/src/apple_sensors.c
+++ b/src/apple_sensors.c
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "apple_sensors", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
}
static int as_read (void)
if (CFGetTypeID (property) != CFStringGetTypeID ())
continue;
if (!CFStringGetCString (property,
- type, 128,
+ type, sizeof (type),
kCFStringEncodingASCII))
continue;
- type[127] = '\0';
+ type[sizeof (type) - 1] = '\0';
/* Copy the sensor location. This will be used as `instance'. */
property = NULL;
if (CFGetTypeID (property) != CFStringGetTypeID ())
continue;
if (!CFStringGetCString (property,
- inst, 128,
+ inst, sizeof (inst),
kCFStringEncodingASCII))
continue;
- inst[127] = '\0';
+ inst[sizeof (inst) - 1] = '\0';
for (i = 0; i < 128; i++)
{
if (inst[i] == '\0')
diff --git a/src/ascent.c b/src/ascent.c
index 8c0bbec600152aee448cd34a7008eae4dadabcc0..2ad641dfede55d98b9a3cf92ebd288dd20881ed4 100644 (file)
--- a/src/ascent.c
+++ b/src/ascent.c
typedef struct player_info_s player_info_t;
#define PLAYER_INFO_STATIC_INIT { -1, -1, -1, -1, -1 }
-static char *url = NULL;
-static char *user = NULL;
-static char *pass = NULL;
-static char *cacert = NULL;
+static char *url = NULL;
+static char *user = NULL;
+static char *pass = NULL;
+static char *verify_peer = NULL;
+static char *verify_host = NULL;
+static char *cacert = NULL;
static CURL *curl = NULL;
"URL",
"User",
"Password",
+ "VerifyPeer",
+ "VerifyHost",
"CACert"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
sstrncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+
if (type_instance != NULL)
sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
return (0);
} /* }}} int ascent_submit_gauge */
return (config_set (&user, value));
else if (strcasecmp (key, "Password") == 0)
return (config_set (&pass, value));
+ else if (strcasecmp (key, "VerifyPeer") == 0)
+ return (config_set (&verify_peer, value));
+ else if (strcasecmp (key, "VerifyHost") == 0)
+ return (config_set (&verify_host, value));
else if (strcasecmp (key, "CACert") == 0)
return (config_set (&cacert, value));
else
{
int status;
- status = snprintf (credentials, sizeof (credentials), "%s:%s",
+ status = ssnprintf (credentials, sizeof (credentials), "%s:%s",
user, (pass == NULL) ? "" : pass);
if (status >= sizeof (credentials))
{
"credentials have been truncated.");
return (-1);
}
- credentials[sizeof (credentials) - 1] = '\0';
curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
}
curl_easy_setopt (curl, CURLOPT_URL, url);
+ if ((verify_peer == NULL) || (strcmp (verify_peer, "true") == 0))
+ curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 1);
+ else
+ curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0);
+
+ if ((verify_host == NULL) || (strcmp (verify_host, "true") == 0))
+ curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 2);
+ else
+ curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0);
+
if (cacert != NULL)
curl_easy_setopt (curl, CURLOPT_CAINFO, cacert);
diff --git a/src/battery.c b/src/battery.c
index badd8e752f47717df72b63cb5360e441b0c203f8..416f3397d0e6c01da373ca17dfc8d48fac8ab03a 100644 (file)
--- a/src/battery.c
+++ b/src/battery.c
#elif KERNEL_LINUX
static int battery_pmu_num = 0;
static char *battery_pmu_file = "/proc/pmu/battery_%i";
+static const char *battery_acpi_dir = "/proc/acpi/battery";
#endif /* KERNEL_LINUX */
static int battery_init (void)
for (battery_pmu_num = 0; ; battery_pmu_num++)
{
- len = snprintf (filename, sizeof (filename), battery_pmu_file, battery_pmu_num);
+ len = ssnprintf (filename, sizeof (filename), battery_pmu_file, battery_pmu_num);
if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
break;
@@ -101,8 +102,9 @@ static void battery_submit (const char *plugin_instance, const char *type, doubl
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "battery", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void battery_submit */
#if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
}
#endif /* HAVE_IOKIT_IOKITLIB_H */
+#if KERNEL_LINUX
+static int battery_read_acpi (const char *dir, const char *name,
+ void *user_data)
+{
+ double current = INVALID_VALUE;
+ double voltage = INVALID_VALUE;
+ double charge = INVALID_VALUE;
+ double *valptr = NULL;
+ int charging = 0;
+
+ char filename[256];
+ FILE *fh;
+
+ char buffer[1024];
+ char *fields[8];
+ int numfields;
+ char *endptr;
+ int len;
+
+ len = ssnprintf (filename, sizeof (filename), "%s/%s/state", battery_acpi_dir, name);
+
+ if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
+ return -1;
+
+ if ((fh = fopen (filename, "r")) == NULL) {
+ char errbuf[1024];
+ ERROR ("Cannot open `%s': %s", filename,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return -1;
+ }
+
+ /*
+ * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state
+ * [11:00] <@tokkee> present: yes
+ * [11:00] <@tokkee> capacity state: ok
+ * [11:00] <@tokkee> charging state: charging
+ * [11:00] <@tokkee> present rate: 1724 mA
+ * [11:00] <@tokkee> remaining capacity: 4136 mAh
+ * [11:00] <@tokkee> present voltage: 12428 mV
+ */
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
+ {
+ numfields = strsplit (buffer, fields, 8);
+
+ if (numfields < 3)
+ continue;
+
+ if ((strcmp (fields[0], "charging") == 0)
+ && (strcmp (fields[1], "state:") == 0))
+ {
+ if (strcmp (fields[2], "charging") == 0)
+ charging = 1;
+ else
+ charging = 0;
+ continue;
+ }
+
+ if ((strcmp (fields[0], "present") == 0)
+ && (strcmp (fields[1], "rate:") == 0))
+ valptr = ¤t;
+ else if ((strcmp (fields[0], "remaining") == 0)
+ && (strcmp (fields[1], "capacity:") == 0))
+ valptr = &charge;
+ else if ((strcmp (fields[0], "present") == 0)
+ && (strcmp (fields[1], "voltage:") == 0))
+ valptr = &voltage;
+ else
+ continue;
+
+ endptr = NULL;
+ errno = 0;
+ *valptr = strtod (fields[2], &endptr) / 1000.0;
+
+ if ((fields[2] == endptr) || (errno != 0))
+ *valptr = INVALID_VALUE;
+ } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
+
+ fclose (fh);
+
+ if ((current != INVALID_VALUE) && (charging == 0))
+ current *= -1;
+
+ if (charge != INVALID_VALUE)
+ battery_submit ("0", "charge", charge);
+ if (current != INVALID_VALUE)
+ battery_submit ("0", "current", current);
+ if (voltage != INVALID_VALUE)
+ battery_submit ("0", "voltage", voltage);
+
+ return 0;
+}
+#endif /* KERNEL_LINUX */
+
+
static int battery_read (void)
{
#if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
double charge = INVALID_VALUE;
double *valptr = NULL;
- len = snprintf (filename, sizeof (filename), battery_pmu_file, i);
+ len = ssnprintf (filename, sizeof (filename), battery_pmu_file, i);
if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
continue;
- len = snprintf (batnum_str, sizeof (batnum_str), "%i", i);
+ len = ssnprintf (batnum_str, sizeof (batnum_str), "%i", i);
if ((len < 0) || ((unsigned int)len >= sizeof (batnum_str)))
continue;
battery_submit ("0", "voltage", voltage);
}
- if (access ("/proc/acpi/battery", R_OK | X_OK) == 0)
- {
- double current = INVALID_VALUE;
- double voltage = INVALID_VALUE;
- double charge = INVALID_VALUE;
- double *valptr = NULL;
- int charging = 0;
-
- struct dirent *ent;
- DIR *dh;
+ walk_directory (battery_acpi_dir, battery_read_acpi,
+ /* user_data = */ NULL);
- if ((dh = opendir ("/proc/acpi/battery")) == NULL)
- {
- char errbuf[1024];
- ERROR ("Cannot open `/proc/acpi/battery': %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
-
- while ((ent = readdir (dh)) != NULL)
- {
- if (ent->d_name[0] == '.')
- continue;
-
- len = snprintf (filename, sizeof (filename),
- "/proc/acpi/battery/%s/state",
- ent->d_name);
- if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
- continue;
-
- if ((fh = fopen (filename, "r")) == NULL)
- {
- char errbuf[1024];
- ERROR ("Cannot open `%s': %s", filename,
- sstrerror (errno, errbuf,
- sizeof (errbuf)));
- continue;
- }
-
- /*
- * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state
- * [11:00] <@tokkee> present: yes
- * [11:00] <@tokkee> capacity state: ok
- * [11:00] <@tokkee> charging state: charging
- * [11:00] <@tokkee> present rate: 1724 mA
- * [11:00] <@tokkee> remaining capacity: 4136 mAh
- * [11:00] <@tokkee> present voltage: 12428 mV
- */
- while (fgets (buffer, sizeof (buffer), fh) != NULL)
- {
- numfields = strsplit (buffer, fields, 8);
-
- if (numfields < 3)
- continue;
-
- if ((strcmp (fields[0], "present") == 0)
- && (strcmp (fields[1], "rate:") == 0))
- valptr = ¤t;
- else if ((strcmp (fields[0], "remaining") == 0)
- && (strcmp (fields[1], "capacity:") == 0))
- valptr = &charge;
- else if ((strcmp (fields[0], "present") == 0)
- && (strcmp (fields[1], "voltage:") == 0))
- valptr = &voltage;
- else
- valptr = NULL;
-
- if ((strcmp (fields[0], "charging") == 0)
- && (strcmp (fields[1], "state:") == 0))
- {
- if (strcmp (fields[2], "charging") == 0)
- charging = 1;
- else
- charging = 0;
- }
-
- if (valptr != NULL)
- {
- char *endptr;
-
- endptr = NULL;
- errno = 0;
-
- *valptr = strtod (fields[2], &endptr) / 1000.0;
-
- if ((fields[2] == endptr) || (errno != 0))
- *valptr = INVALID_VALUE;
- }
- } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
-
- fclose (fh);
-
- if ((current != INVALID_VALUE) && (charging == 0))
- current *= -1;
-
- if (charge != INVALID_VALUE)
- battery_submit ("0", "charge", charge);
- if (current != INVALID_VALUE)
- battery_submit ("0", "current", current);
- if (voltage != INVALID_VALUE)
- battery_submit ("0", "voltage", voltage);
- }
-
- closedir (dh);
- }
#endif /* KERNEL_LINUX */
return (0);
diff --git a/src/collectd-exec.pod b/src/collectd-exec.pod
index 59ce399d892873ab04bd589476ec4c2eda89a1a2..d935c70d8a42d87597bb2f29920132800ded5083 100644 (file)
--- a/src/collectd-exec.pod
+++ b/src/collectd-exec.pod
The I<OptionList> is an optional list of I<Options>, where each option if a
key-value-pair. A list of currently understood options can be found below, all
-other options will be ignored.
+other options will be ignored. Values that contain spaces must be quoted with
+double quotes.
I<Valuelist> is a colon-separated list of the time and the values, each either
an integer if the data-source is a counter, or a double if the data-source is
=item B<message=>I<Message> (B<REQUIRED>)
Sets the message of the notification. This is the message that will be made
-accessible to the user, so it should contain some useful information. This
-option must be the last option because the rest of the line will be its value,
-even if there are spaces and equal-signs following it! This option is
-mandatory.
+accessible to the user, so it should contain some useful information. As with
+all options: If the message includes spaces, it must be quoted with double
+quotes. This option is mandatory.
=item B<severity=failure>|B<warning>|B<okay> (B<REQUIRED>)
diff --git a/src/collectd-perl.pod b/src/collectd-perl.pod
index 8cdf08bb3b6807229bb4a985a5b01f74771f8378..c3fcb1088319142f44f88c8b5378c050f2973993 100644 (file)
--- a/src/collectd-perl.pod
+++ b/src/collectd-perl.pod
BaseName "Collectd::Plugin"
EnableDebugger ""
LoadPlugin "FooBar"
+
+ <Plugin FooBar>
+ Foo "Bar"
+ </Plugin>
</Plugin>
=head1 DESCRIPTION
Prepends I<Name>B<::> to all plugin names loaded after this option. This is
provided for convenience to keep plugin names short.
+=item E<lt>B<Plugin> I<Name>E<gt> block
+
+This block may be used to pass on configuration settings to a Perl plugin. The
+configuration is converted into a config-item data type which is passed to the
+registered configuration callback. See below for details about the config-item
+data type and how to register callbacks.
+
+The I<name> identifies the callback. It is used literally and independent of
+the B<BaseName> setting.
+
=item B<EnableDebugger> I<Package>[=I<option>,...]
Run collectd under the control of the Perl source debugger. If I<Package> is
=over 4
+=item configuration functions
+
+This type of functions is called during configuration if an appropriate
+B<Plugin> block has been encountered. It is called once for each B<Plugin>
+block which matches the name of the callback as provided with the
+B<plugin_register> method - see below.
+
=item init functions
This type of functions is called once after loading the module and before any
=over 4
+=item Config-Item
+
+A config-item is one structure which keeps the informations provided in the
+configuration file. The array of children keeps one entry for each
+configuration option. Each such entry is another config-item structure, which
+may nest further if nested blocks are used.
+
+ {
+ key => key,
+ values => [ val1, val2, ... ],
+ children => [ { ... }, { ... }, ... ]
+ }
+
=item Data-Set
A data-set is a list of one or more data-sources. Each data-source defines a
time => time (),
host => $hostname_g,
plugin => 'myplugin',
+ type => 'myplugin',
plugin_instance => '',
type_instance => ''
}
=over 4
+=item TYPE_CONFIG
+
=item TYPE_INIT
=item TYPE_READ
=over 4
+=item TYPE_CONFIG
+
+The only argument passed is I<config-item>. See above for the layout of this
+data type.
+
=item TYPE_INIT
=item TYPE_READ
=item TYPE_FLUSH
-The only argument passed is I<timeout> which indicates that only data older
-than I<timeout> seconds is to be flushed.
+The arguments passed are I<timeout> and I<identifier>. I<timeout> indicates
+that only data older than I<timeout> seconds is to be flushed. I<identifier>
+specifies which values are to be flushed.
=item TYPE_LOG
Removes a callback or data-set from collectd's internal list of
functionsE<nbsp>/ datasets.
-=item B<plugin_dispatch_values> (I<type>, I<value-list>)
+=item B<plugin_dispatch_values> (I<value-list>)
-Submits a I<value-list> of type I<type> to the daemon. If the data-set I<type>
+Submits a I<value-list> to the daemon. If the data-set identified by
+I<value-list>->{I<type>}
is found (and the number of values matches the number of data-sources) then the
type, data-set and value-list is passed to all write-callbacks that are
registered with the daemon.
-=item B<plugin_flush> ([B<timeout> => I<timeout>,] [B<plugins> => I<...>])
+B<Note>: Prior to version 4.4 of collectd, the data-set type used to be passed
+as the first argument to B<plugin_register>. This syntax is still supported
+for backwards compatibility but has been deprecated and will be removed in
+some future version of collectd.
-Flush one or more plugins. I<timeout> is passed on to the registered
-flush-callbacks. If omitted, C<-1> is used. If the I<plugins> argument has
-been specified, only named plugins will be flushed. The argument's value may
-either be a string or a reference to an array of strings.
+=item B<plugin_flush> ([B<timeout> => I<timeout>][, B<plugins> => I<...>][,
+B<identifiers> => I<...>])
+
+Flush one or more plugins. I<timeout> and the specified I<identifiers> are
+passed on to the registered flush-callbacks. If omitted, the timeout defaults
+to C<-1>. The identifier defaults to the undefined value. If the I<plugins>
+argument has been specified, only named plugins will be flushed. The value of
+the B<plugins> and B<identifiers> arguments may either be a string or a
+reference to an array of strings.
=item B<plugin_flush_one> (I<timeout>, I<plugin>)
This is identical to using "plugin_flush (timeout =E<gt> I<timeout>, plugins
=E<gt> I<plugin>".
+B<Note>: Starting with version 4.5 of collectd, B<plugin_flush_one> has been
+deprecated and will be removed in some future version of collectd. Use
+B<plugin_flush> instead.
+
=item B<plugin_flush_all> (I<timeout>)
This is identical to using "plugin_flush (timeout =E<gt> I<timeout>)".
+B<Note>: Starting with version 4.5 of collectd, B<plugin_flush_all> has been
+deprecated and will be removed in some future version of collectd. Use
+B<plugin_flush> instead.
+
=item B<plugin_dispatch_notification> (I<notification>)
Submits a I<notification> to the daemon which will then pass it to all
=over 4
+=item B<TYPE_CONFIG>
+
=item B<TYPE_INIT>
=item B<TYPE_READ>
=item B<TYPE_LOG>
+=item B<TYPE_DATASET>
+
=back
=item B<:ds_types>
down. You should not rely on END blocks anyway - use B<shutdown functions>
instead.
+=item
+
+The perl plugin exports the internal API of collectd which is considered
+unstable and subject to change at any time. We try hard to not break backwards
+compatibility in the Perl API during the life cycle of one major release.
+However, this cannot be guaranteed at all times. Watch out for warnings
+dispatched by the perl plugin after upgrades.
+
=back
=head1 KNOWN BUGS
index 971cb36dc0a138a9c826d5148178714e57078b91..ca00a6defe33e7c45d682c32bae1f90cccdda89a 100644 (file)
The I<OptionList> is an optional list of I<Options>, where each option is a
key-value-pair. A list of currently understood options can be found below, all
-other options will be ignored.
+other options will be ignored. Values that contain spaces must be quoted with
+double quotes.
I<Valuelist> is a colon-separated list of the time and the values, each either
an integer if the data-source is a counter, or a double if the data-source is
=item B<message=>I<Message> (B<REQUIRED>)
Sets the message of the notification. This is the message that will be made
-accessible to the user, so it should contain some useful information. This
-option must be the last option because the rest of the line will be its value,
-even if there are spaces and equal-signs following it! This option is
-mandatory.
+accessible to the user, so it should contain some useful information. As with
+all options: If the message includes spaces, it must be quoted with double
+quotes. This option is mandatory.
=item B<severity=failure>|B<warning>|B<okay> (B<REQUIRED>)
-> | PUTNOTIF type=temperature severity=warning time=1201094702 message=The roof is on fire!
<- | 0 Success
-=item B<FLUSH> [B<timeout=>I<Timeout>] [B<plugin=>I<Plugin> [...]]
+=item B<FLUSH> [B<timeout=>I<Timeout>] [B<plugin=>I<Plugin> [...]] [B<identifier=>I<Ident> [...]]
Flushes all cached data older than I<Timeout> seconds. If no timeout has been
-specified, it defaults to -1 which causes all data to be flushed. B<timeout>
-may be specified multiple times - each occurrence applies to plugins listed
-afterwards.
+specified, it defaults to -1 which causes all data to be flushed.
+
+If the B<plugin> option has been specified, only the I<Plugin> plugin will be
+flushed. You can have multiple B<plugin> options to flush multiple plugins in
+one go. If the B<plugin> option is not given all plugins providing a flush
+callback will be flushed.
-If specified, only specific plugins are flushed. Otherwise all plugins
-providing a flush callback are flushed.
+If the B<identifier> option is given only the specified values will be flushed.
+This is meant to be used by graphing or displaying frontends which want to have
+the lastest values for a specific graph. Again, you can specify the
+B<identifier> option multiple times to flush several values. If this option is
+not specified at all, all values will be flushed.
Example:
- -> | FLUSH
- <- | 0 Done
+ -> | FLUSH plugin=rrdtool identifier=localhost/df/df-root identifier=localhost/df/df-var
+ <- | 0 Done: 2 successful, 0 errors
=back
I<Hostname>/I<Plugin>/I<Type>
Where I<Plugin> and I<Type> are both either of type "I<Name>" or
-"I<Name>-I<Instance>". This sounds more complicated than it is, so here are
+"I<Name>-I<Instance>". If the identifier includes spaces, it must be quoted
+using double quotes. This sounds more complicated than it is, so here are
some examples:
myhost/cpu-0/cpu-user
myhost/load/load
myhost/memory/memory-used
myhost/disk-sda/disk_octets
+ "myups/snmp/temperature-Outlet 1"
=head1 ABSTRACTION LAYER
diff --git a/src/collectd.c b/src/collectd.c
index a3f63b48007336bc48621fa366cbf90a96ccff4c..71eb940fb3251b6ffee1af4829fdc92c915460ce 100644 (file)
--- a/src/collectd.c
+++ b/src/collectd.c
static void *do_flush (void *arg)
{
INFO ("Flushing all data.");
- plugin_flush_all (-1);
+ plugin_flush (NULL, -1, NULL);
INFO ("Finished flushing all data.");
pthread_exit (NULL);
return NULL;
str = global_option_get ("Hostname");
if (str != NULL)
{
- strncpy (hostname_g, str, sizeof (hostname_g));
- hostname_g[sizeof (hostname_g) - 1] = '\0';
+ sstrncpy (hostname_g, str, sizeof (hostname_g));
return (0);
}
if (ai_ptr->ai_canonname == NULL)
continue;
- strncpy (hostname_g, ai_ptr->ai_canonname, sizeof (hostname_g));
- hostname_g[sizeof (hostname_g) - 1] = '\0';
+ sstrncpy (hostname_g, ai_ptr->ai_canonname, sizeof (hostname_g));
break;
}
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 829d3e5983d32958ad14d8829de457cd36da8115..36f0014c30ed6430ad8f154cb904b59256e07b3a 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
@BUILD_PLUGIN_EMAIL_TRUE@LoadPlugin email
@BUILD_PLUGIN_ENTROPY_TRUE@LoadPlugin entropy
@BUILD_PLUGIN_EXEC_TRUE@LoadPlugin exec
+@BUILD_PLUGIN_FILECOUNT_TRUE@LoadPlugin filecount
@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
@BUILD_PLUGIN_NETWORK_TRUE@LoadPlugin network
@BUILD_PLUGIN_NFS_TRUE@LoadPlugin nfs
@BUILD_PLUGIN_NGINX_TRUE@LoadPlugin nginx
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@LoadPlugin notify_desktop
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
+@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
@BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl
@BUILD_PLUGIN_PING_TRUE@LoadPlugin ping
+@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql
@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
@BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
@BUILD_PLUGIN_RRDTOOL_TRUE@LoadPlugin rrdtool
@BUILD_PLUGIN_TAPE_TRUE@LoadPlugin tape
@BUILD_PLUGIN_TCPCONNS_TRUE@LoadPlugin tcpconns
@BUILD_PLUGIN_TEAMSPEAK2_TRUE@LoadPlugin teamspeak2
+@BUILD_PLUGIN_THERMAL_TRUE@LoadPlugin thermal
@BUILD_PLUGIN_UNIXSOCK_TRUE@LoadPlugin unixsock
@BUILD_PLUGIN_USERS_TRUE@LoadPlugin users
@BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid
# NotificationExec "user:group" "/path/to/exec"
#</Plugin>
+#<Plugin filecount>
+# <Directory "/path/to/dir">
+# Instance "foodir"
+# Name "*.conf"
+# MTime "-5m"
+# Size "+10k"
+# </Directory>
+#</Plugin>
+
@BUILD_PLUGIN_HDDTEMP_TRUE@<Plugin hddtemp>
# Host "127.0.0.1"
# Port "7634"
# CACert "/etc/ssl/ca.crt"
#</Plugin>
+#<Plugin notify_desktop>
+# OkayTimeout 1000
+# WarningTimeout 5000
+# FailureTimeout 0
+#</Plugin>
+
+#<Plugin notify_email>
+# SMTPServer "localhost"
+# SMTPPort 25
+# SMTPUser "my-username"
+# SMTPPassword "my-password"
+# From "collectd@main0server.com"
+# # <WARNING/FAILURE/OK> on <hostname>. beware! do not use not more than two %s in this string!!!
+# Subject "Aaaaaa!! %s on %s!!!!!"
+# Recipient "email1@domain1.net"
+# Recipient "email2@domain2.com"
+#</Plugin>
+
#<Plugin ntpd>
# Host "localhost"
# Port 123
# UPS "upsname@hostname:port"
#</Plugin>
+#<Plugin onewire>
+# Device "-s localhost:4304"
+# Sensor "F10FCA000800"
+# IgnoreSelected false
+#</Plugin>
+
#<Plugin perl>
# IncludeDir "/my/include/path"
# BaseName "Collectd::Plugin"
# TTL 255
#</Plugin>
+#<Plugin postgresql>
+# <Query magic>
+# Query "SELECT magic, spells FROM wizard WHERE host = $1;"
+# Param hostname
+# Column gauge magic
+# Column counter spells
+# </Query>
+#
+# <Database foo>
+# Host "hostname"
+# Port 5432
+# User "username"
+# Password "secret"
+#
+# SSLMode "prefer"
+# KRBSrvName "kerberos_service_name"
+#
+# Query magic
+# </Database>
+#
+# <Database bar>
+# Service "service_name"
+# </Database>
+#</Plugin>
+
#<Plugin powerdns>
# <Server "server_name">
# Collect "latency"
# Server "8767"
#</Plugin>
+#<Plugin thermal>
+# ForceUseProcfs false
+# Device "THRM"
+# IgnoreSelected false
+#</Plugin>
+
#<Plugin unixsock>
# SocketFile "@prefix@/var/run/@PACKAGE_NAME@-unixsock"
# SocketGroup "collectd"
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 7f9ae14ecca69d2b1d93c95f70ea7c82774c1064..0df5c3b767f9c585f951e9c2e453358363e849e2 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
ignored. Values are either string, enclosed in double-quotes,
(floating-point-)numbers or a boolean expression, i.E<nbsp>e. either B<true> or
B<false>. String containing of only alphanumeric characters and underscores do
-not need to be quoted.
+not need to be quoted. Lines may be wrapped by using `\' as the last character
+before the newline. This allows long lines to be split into multiple lines.
+Quoted strings may be wrapped as well. However, those are treated special in
+that whitespace at the beginning of the following lines will be ignored, which
+allows for nicely indenting the wrapped lines.
The configuration is read and processed in order, i.E<nbsp>e. from top to
bottom. So the plugins are loaded in the order listed in this config file. It
Optional password needed for authentication.
+=item B<VerifyPeer> B<true|false>
+
+Enable or disable peer SSL certificate verification. See
+L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+
+=item B<VerifyHost> B<true|false>
+
+Enable or disable peer host name verification. If enabled, the plugin checks
+if the C<Common Name> or a C<Subject Alternate Name> field of the SSL
+certificate matches the host name provided by the B<URL> option. If this
+identity check fails, the connection is aborted. Obviously, only works when
+connecting to a SSL enabled server. Enabled by default.
+
=item B<CACert> I<File>
File that holds one or more SSL certificates. If you want to use HTTPS you will
=back
+=head2 Plugin C<filecount>
+
+The C<filecount> plugin counts the number of files in a certain directory (and
+its subdirectories) and their combined size. The configuration is very straight
+forward:
+
+ <Plugin "filecount">
+ <Directory "/var/qmail/queue/mess">
+ Instance "qmail-message"
+ </Directory>
+ <Directory "/var/qmail/queue/todo">
+ Instance "qmail-todo"
+ </Directory>
+ <Directory "/var/lib/php5">
+ Instance "php5-sessions"
+ Name "sess_*"
+ </Directory>
+ </Plugin>
+
+The example above counts the number of files in QMail's queue directories and
+the number of PHP5 sessions. Jfiy: The "todo" queue holds the messages that
+QMail has not yet looked at, the "message" queue holds the messages that were
+classified into "local" and "remote".
+
+As you can see, the configuration consists of one or more C<Directory> blocks,
+each of which specifies a directory in which to count the files. Within those
+blocks, the following options are recognized:
+
+=over 4
+
+=item B<Instance> I<Instance>
+
+Sets the plugin instance to I<Instance>. That instance name must be unique, but
+it's your responsibility, the plugin doesn't check for that. If not given, the
+instance is set to the directory name with all slashes replaced by underscores
+and all leading underscores removed.
+
+=item B<Name> I<Pattern>
+
+Only count files that match I<Pattern>, where I<Pattern> is a shell-like
+wildcard as understood by L<fnmatch(3)>. Only the B<filename> is checked
+against the pattern, not the entire path. In case this makes it easier for you:
+This option has been named after the B<-name> parameter to L<find(1)>.
+
+=item B<MTime> I<Age>
+
+Count only files of a specific age: If I<Age> is greater than zero, only files
+that haven't been touched in the last I<Age> seconds are counted. If I<Age> is
+a negative number, this is inversed. For example, if B<-60> is specified, only
+files that have been modified in the last minute will be counted.
+
+The number can also be followed by a "multiplier" to easily specify a larger
+timespan. When given in this notation, the argument must in quoted, i.E<nbsp>e.
+must be passed as string. So the B<-60> could also be written as B<"-1m"> (one
+minute). Valid multipliers are C<s> (second), C<m> (minute), C<h> (hour), C<d>
+(day), C<w> (week), and C<y> (year). There is no "month" multiplier. You can
+also specify fractional numbers, e.E<nbsp>g. B<"0.5d"> is identical to
+B<"12h">.
+
+=item B<Size> I<Size>
+
+Count only files of a specific size. When I<Size> is a positive number, only
+files that are at least this big are counted. If I<Size> is a negative number,
+this is inversed, i.E<nbsp>e. only files smaller than the absolute value of
+I<Size> are counted.
+
+As with the B<MTime> option, a "multiplier" may be added. For a detailed
+description see above. Valid multipliers here are C<b> (byte), C<k> (kilobyte),
+C<m> (megabyte), C<g> (gigabyte), C<t> (terabyte), and C<p> (petabyte). Please
+note that there are 1000 bytes in a kilobyte, not 1024.
+
+=back
+
=head2 Plugin C<hddtemp>
To get values from B<hddtemp> collectd connects to B<localhost> (127.0.0.1),
interfaces you're interested in. Sometimes, however, it's easier/preferred
to collect all interfaces I<except> a few ones. This option enables you to
do that: By setting B<IgnoreSelected> to I<true> the effect of
-B<Interface> is inversed: All selected interfaces are ignored and all
+B<Interface> is inverted: All selected interfaces are ignored and all
other interfaces are collected.
=back
the effect of B<Sensor> is inverted: All selected sensors are ignored and
all other sensors are collected.
+=item B<NotifySensorAdd> I<true>|I<false>
+
+If a sensor appears after initialization time of a minute a notification
+is sent.
+
+=item B<NotifySensorRemove> I<true>|I<false>
+
+If a sensor disappears a notification is sent.
+
+=item B<NotifySensorNotPresent> I<true>|I<false>
+
+If you have for example dual power supply and one of them is (un)plugged then
+a notification is sent.
+
=back
=head2 Plugin C<iptables>
can use the B<Irq>-option to pick the interrupt you're interested in.
Sometimes, however, it's easier/preferred to collect all interrupts I<except> a
few ones. This option enables you to do that: By setting B<IgnoreSelected> to
-I<true> the effect of B<Irq> is inversed: All selected interrupts are ignored
+I<true> the effect of B<Irq> is inverted: All selected interrupts are ignored
and all other interrupts are collected.
=back
The behaviour is the same as with all other similar plugins: If nothing is
selected at all, everything is collected. If some things are selected using the
options described above, only these statistics are collected. If you set
-B<IgnoreSelected> to B<true>, this behavior is inversed, i.E<nbsp>e. the
+B<IgnoreSelected> to B<true>, this behavior is inverted, i.E<nbsp>e. the
specified statistics will not be collected.
=back
=back
+=head2 Plugin C<notify_desktop>
+
+This plugin sends a desktop notification to a notification daemon, as defined
+in the Desktop Notification Specification. To actually display the
+notifications, B<notification-daemon> is required and B<collectd> has to be
+able to access the X server.
+
+The Desktop Notification Specification can be found at
+L<http://www.galago-project.org/specs/notification/>.
+
+=over 4
+
+=item B<OkayTimeout> I<timeout>
+
+=item B<WarningTimeout> I<timeout>
+
+=item B<FailureTimeout> I<timeout>
+
+Set the I<timeout>, in milliseconds, after which to expire the notification
+for C<OKAY>, C<WARNING> and C<FAILURE> severities respectively. If zero has
+been specified, the displayed notification will not be closed at all - the
+user has to do so herself. These options default to 5000. If a negative number
+has been specified, the default is used as well.
+
+=back
+
=head2 Plugin C<ntpd>
=over 4
=back
+=head2 Plugin C<onewire>
+
+B<EXPERIMENTAL!> See notes below.
+
+The C<onewire> plugin uses the B<owcapi> library from the B<owfs> project
+L<http://owfs.org/> to read sensors connected via the onewire bus.
+
+Currently only temperature sensors (sensors with the family code C<10>,
+e.E<nbsp>g. DS1820, DS18S20, DS1920) can be read. If you have other sensors you
+would like to have included, please send a sort request to the mailing list.
+
+Hubs (the DS2409 chips) are working, but read the note, why this plugin is
+experimental, below.
+
+=over 4
+
+=item B<Device> I<Device>
+
+Sets the device to read the values from. This can either be a "real" hardware
+device, such as a serial port or an USB port, or the address of the
+L<owserver(1)> socket, usually B<localhost:4304>.
+
+Though the documentation claims to automatically recognize the given address
+format, with versionE<nbsp>2.7p4 we had to specify the type explicitly. So
+with that version, the following configuration worked for us:
+
+ <Plugin onewire>
+ Device "-s localhost:4304"
+ </Plugin>
+
+This directive is B<required> and does not have a default value.
+
+=item B<Sensor> I<Sensor>
+
+Selects sensors to collect or to ignore, depending on B<IgnoreSelected>, see
+below. Sensors are specified without the family byte at the beginning, to you'd
+use C<F10FCA000800>, and B<not> include the leading C<10.> family byte and
+point.
+
+=item B<IgnoreSelected> I<true>|I<false>
+
+If no configuration if given, the B<onewire> plugin will collect data from all
+sensors found. This may not be practical, especially if sensors are added and
+removed regularly. Sometimes, however, it's easier/preferred to collect only
+specific sensors or all sensors I<except> a few specified ones. This option
+enables you to do that: By setting B<IgnoreSelected> to I<true> the effect of
+B<Sensor> is inverted: All selected interfaces are ignored and all other
+interfaces are collected.
+
+=back
+
+B<EXPERIMENTAL!> The C<onewire> plugin is experimental, because it doesn't yet
+work with big setups. It works with one sensor being attached to one
+controller, but as soon as you throw in a couple more senors and maybe a hub
+or two, reading all values will take more than ten seconds (the default
+interval). We will probably add some separate thread for reading the sensors
+and some cache or something like that, but it's not done yet. We will try to
+maintain backwards compatibility in the future, but we can't probmise. So in
+short: If it works for you: Great! But kaap in mind that the config I<might>
+change, though this is unlikely. Oh, and if you want to help improving this
+plugin, just send a short notice to the mailing list. ThanksE<nbsp>:)
+
=head2 Plugin C<perl>
This plugin embeds a Perl-interpreter into collectd and provides an interface
=back
+=head2 Plugin C<postgresql>
+
+The C<postgresql> plugin queries statistics from PostgreSQL databases. It
+keeps a persistent connection to all configured databases and tries to
+reconnect if the connection has been interrupted. A database is configured by
+specifying a B<Database> block as described below. The default statistics are
+collected from PostgreSQL's B<statistics collector> which thus has to be
+enabled for this plugin to work correctly. This should usually be the case by
+default. See the section "The Statistics Collector" of the B<PostgreSQL
+Documentation> for details.
+
+By specifying custom database queries using a B<Query> block as described
+below, you may collect any data that is available from some PostgreSQL
+database. This way, you are able to access statistics of external daemons
+which are available in a PostgreSQL database or use future or special
+statistics provided by PostgreSQL without the need to upgrade your collectd
+installation.
+
+The B<PostgreSQL Documentation> manual can be found at
+L<http://www.postgresql.org/docs/manuals/>.
+
+ <Plugin postgresql>
+ <Query magic>
+ Query "SELECT magic, spells FROM wizard WHERE host = $1;"
+ Param hostname
+ Column gauge magic
+ Column counter spells
+ </Query>
+
+ <Database foo>
+ Host "hostname"
+ Port "5432"
+ User "username"
+ Password "secret"
+ SSLMode "prefer"
+ KRBSrvName "kerberos_service_name"
+ Query magic
+ </Database>
+ <Database bar>
+ Service "service_name"
+ </Database>
+ </Plugin>
+
+The B<Query> block defines one database query which may later be used by a
+database definition. It accepts a single mandatory argument which specifies
+the name of the query. The names of all queries have to be unique. The
+following configuration options are available to define the query:
+
+=over 4
+
+=item B<Query> I<sql query>
+
+Specify the I<sql query> which the plugin should execute. The string may
+contain the tokens B<$1>, B<$2>, etc. which are used to reference the first,
+second, etc. parameter. The value of the parameters is specified by the
+B<Param> configuration option - see below for details. To include a literal
+B<$> character followed by a number, surround it with single quotes (B<'>).
+
+Any SQL command which may return data (such as C<SELECT> or C<SHOW>) is
+allowed. Note, however, that only a single command may be used. Semicolons are
+allowed as long as a single non-empty command has been specified only.
+
+=item B<Param> I<hostname>|I<database>|I<username>
+
+Specify the parameters which should be passed to the SQL query. The parameters
+are referred to in the SQL query as B<$1>, B<$2>, etc. in the same order as
+they appear in the configuration file. The value of the parameter is
+determined depending on the value of the B<Param> option as follows:
+
+=over 4
+
+=item I<hostname>
+
+The configured hostname of the database connection. If a UNIX domain socket is
+used, the parameter expands to "localhost".
+
+=item I<database>
+
+The name of the database of the current connection.
+
+=item I<username>
+
+The username used to connect to the database.
+
+=back
+
+Please note that parameters are only supported by PostgreSQL's protocol
+version 3 and above which was introduced in version 7.4 of PostgreSQL.
+
+=item B<Column> I<type> [I<type instance>]
+
+Specify the I<type> and optional I<type instance> used to dispatch the value
+of each result column. Detailed information about types and their
+configuration can be found in L<types.db(5)>. The number and order of the
+B<Column> options has to match the columns of the query result.
+
+=item B<MinPGVersion> I<version>
+
+=item B<MaxPGVersion> I<version>
+
+Specify the minimum or maximum version of PostgreSQL that this query should be
+used with. Some statistics might only be available with certain versions of
+PostgreSQL. This allows you to specify multiple queries with the same name but
+which apply to different versions, thus allowing you to use the same
+configuration in a heterogeneous environment.
+
+The I<version> has to be specified as the concatenation of the major, minor
+and patch-level versions, each represented as two-decimal-digit numbers. For
+example, version 8.2.3 will become 80203.
+
+=back
+
+The following predefined queries are available (the definitions can be found
+in the F<postgresql_default.conf> file which, by default, is available at
+C<I<prefix>/share/collectd/>):
+
+=over 4
+
+=item B<backends>
+
+This query collects the number of backends, i.E<nbsp>e. the number of
+connected clients.
+
+=item B<transactions>
+
+This query collects the numbers of committed and rolled-back transactions of
+the user tables.
+
+=item B<queries>
+
+This query collects the numbers of various table modifications (i.E<nbsp>e.
+insertions, updates, deletions) of the user tables.
+
+=item B<query_plans>
+
+This query collects the numbers of various table scans and returned tuples of
+the user tables.
+
+=item B<table_states>
+
+This query collects the numbers of live and dead rows in the user tables.
+
+=item B<disk_io>
+
+This query collects disk block access counts for user tables.
+
+=item B<disk_usage>
+
+This query collects the on-disk size of the database in bytes.
+
+=back
+
+The B<Database> block defines one PostgreSQL database for which to collect
+statistics. It accepts a single mandatory argument which specifies the
+database name. None of the other options are required. PostgreSQL will use
+default values as documented in the section "CONNECTING TO A DATABASE" in the
+L<psql(1)> manpage. However, be aware that those defaults may be influenced by
+the user collectd is run as and special environment variables. See the manpage
+for details.
+
+=over 4
+
+=item B<Host> I<hostname>
+
+Specify the hostname or IP of the PostgreSQL server to connect to. If the
+value begins with a slash, it is interpreted as the directory name in which to
+look for the UNIX domain socket.
+
+This option is also used to determine the hostname that is associated with a
+collected data set. If it has been omitted or either begins with with a slash
+or equals B<localhost> it will be replaced with the global hostname definition
+of collectd. Any other value will be passed literally to collectd when
+dispatching values. Also see the global B<Hostname> and B<FQDNLookup> options.
+
+=item B<Port> I<port>
+
+Specify the TCP port or the local UNIX domain socket file extension of the
+server.
+
+=item B<User> I<username>
+
+Specify the username to be used when connecting to the server.
+
+=item B<Password> I<password>
+
+Specify the password to be used when connecting to the server.
+
+=item B<SSLMode> I<disable>|I<allow>|I<prefer>|I<require>
+
+Specify whether to use an SSL connection when contacting the server. The
+following modes are supported:
+
+=over 4
+
+=item I<disable>
+
+Do not use SSL at all.
+
+=item I<allow>
+
+First, try to connect without using SSL. If that fails, try using SSL.
+
+=item I<prefer> (default)
+
+First, try to connect using SSL. If that fails, try without using SSL.
+
+=item I<require>
+
+Use SSL only.
+
+=back
+
+=item B<KRBSrvName> I<kerberos_service_name>
+
+Specify the Kerberos service name to use when authenticating with Kerberos 5
+or GSSAPI. See the sections "Kerberos authentication" and "GSSAPI" of the
+B<PostgreSQL Documentation> for details.
+
+=item B<Service> I<service_name>
+
+Specify the PostgreSQL service name to use for additional parameters. That
+service has to be defined in F<pg_service.conf> and holds additional
+connection parameters. See the section "The Connection Service File" in the
+B<PostgreSQL Documentation> for details.
+
+=item B<Query> I<query>
+
+Specify a I<query> which should be executed for the database connection. This
+may be any of the predefined or user-defined queries. If no such option is
+given, it defaults to "backends", "transactions", "queries", "query_plans",
+"table_states", "disk_io" and "disk_usage". Else, the specified queries are
+used only.
+
+=back
+
=head2 Plugin C<powerdns>
The C<powerdns> plugin queries statistics from an authoritative PowerDNS
@@ -1131,7 +1558,7 @@ Set the "XFiles Factor". The default is 0.1. If unsure, don't set this option.
=item B<CacheFlush> I<Seconds>
-When the C<rrdtool plugin> uses a cache (by setting B<CacheTimeout>, see below)
+When the C<rrdtool> plugin uses a cache (by setting B<CacheTimeout>, see below)
it writes all values for a certain RRD-file if the oldest value is older than
(or equal to) the number of seconds specified. If some RRD-file is not updated
anymore for some reason (the computer was shut down, the network is broken,
@@ -1150,6 +1577,30 @@ reduces IO-operations and thus lessens the load produced by updating the files.
The trade off is that the graphs kind of "drag behind" and that more memory is
used.
+=item B<WritesPerSecond> B<Updates>
+
+When collecting many statistics with collectd and the C<rrdtool> plugin, you
+will run serious performance problems. The B<CacheFlush> setting and the
+internal update queue assert that collectd continues to work just fine even
+under heavy load, but the system may become very unresponsive and slow. This is
+a problem especially if you create graphs from the RRD files on the same
+machine, for example using the C<graph.cgi> script included in the
+C<contrib/collection3/> directory.
+
+This setting is designed for very large setups. Setting this option to a value
+between 25 and 80 updates per second, depending on your hardware, will leave
+the server responsive enough to draw graphs even while all the cached values
+are written to disk. Flushed values, i.E<nbsp>e. values that are forced to disk
+by the B<FLUSH> command, are B<not> effected by this limit. They are still
+written as fast as possible, so that web frontends have up to date data when
+generating graphs.
+
+For example: If you have 100,000 RRD files and set B<WritesPerSecond> to 30
+updates per second, writing all values to disk will take approximately
+56E<nbsp>minutes. Together with the flushing ability that's integrated into
+"collection3" you'll end up with a responsive and fast system, up to date
+graphs and basically a "backup" of your values every hour.
+
=back
=head2 Plugin C<sensors>
Thus, you can use the B<Sensor>-option to pick the sensors you're interested
in. Sometimes, however, it's easier/preferred to collect all sensors I<except> a
few ones. This option enables you to do that: By setting B<IgnoreSelected> to
-I<true> the effect of B<Sensor> is inversed: All selected sensors are ignored
+I<true> the effect of B<Sensor> is inverted: All selected sensors are ignored
and all other sensors are collected.
=back
=back
+=head2 Plugin C<thermal>
+
+=over 4
+
+=item B<ForceUseProcfs> I<true>|I<false>
+
+By default, the C<thermal> plugin tries to read the statistics from the Linux
+C<sysfs> interface. If that is not available, the plugin falls back to the
+C<procfs> interface. By setting this option to I<true>, you can force the
+plugin to use the latter. This option defaults to I<false>.
+
+=item B<Device> I<Device>
+
+Selects the name of the thermal device that you want to collect or ignore,
+depending on the value of the B<IgnoreSelected> option. This option may be
+used multiple times to specify a list of devices.
+
+=item B<IgnoreSelected> I<true>|I<false>
+
+Invert the selection: If set to true, all devices B<except> the ones that
+match the device names specified by the B<Device> option are collected. By
+default only selected devices are collected if a selection is made. If no
+selection is configured at all, B<all> devices are selected.
+
+=back
+
=head2 Plugin C<unixsock>
=over 4
L<hddtemp(8)>,
L<kstat(3KSTAT)>,
L<mbmon(1)>,
+L<psql(1)>,
L<rrdtool(1)>,
L<sensors(1)>
diff --git a/src/collectd.h b/src/collectd.h
index eece4203894b1a51786446b6787fba77f152d944..196530fbc3dfdedec57048ff6da2e602b0554d1f 100644 (file)
--- a/src/collectd.h
+++ b/src/collectd.h
#if HAVE_STDINT_H
# include <stdint.h>
#endif
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
#endif
+#ifndef PKGDATADIR
+#define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
+#endif
+
#ifndef COLLECTD_GRP_NAME
# define COLLECTD_GRP_NAME "collectd"
#endif
diff --git a/src/common.c b/src/common.c
index 82b4aaae87745b0e6afb5ca4e1004d9c2de8647a..61a759b10b2c3dad4d85716ffe5ef1dd55979625 100644 (file)
--- a/src/common.c
+++ b/src/common.c
return (dest);
} /* char *sstrncpy */
+int ssnprintf (char *dest, size_t n, const char *format, ...)
+{
+ int ret = 0;
+ va_list ap;
+
+ va_start (ap, format);
+ ret = vsnprintf (dest, n, format, ap);
+ dest[n - 1] = '\0';
+ va_end (ap);
+
+ return (ret);
+} /* int ssnprintf */
+
char *sstrdup (const char *s)
{
char *r;
pthread_mutex_lock (&strerror_r_lock);
temp = strerror (errnum);
- strncpy (buf, temp, buflen);
+ sstrncpy (buf, temp, buflen);
pthread_mutex_unlock (&strerror_r_lock);
}
if (buf[0] == '\0')
{
if ((temp != NULL) && (temp != buf) && (temp[0] != '\0'))
- strncpy (buf, temp, buflen);
+ sstrncpy (buf, temp, buflen);
else
- strncpy (buf, "strerror_r did not return "
+ sstrncpy (buf, "strerror_r did not return "
"an error message", buflen);
}
}
#else
if (strerror_r (errnum, buf, buflen) != 0)
{
- snprintf (buf, buflen, "Error #%i; "
+ ssnprintf (buf, buflen, "Error #%i; "
"Additionally, strerror_r failed.",
errnum);
}
#endif /* STRERROR_R_CHAR_P */
- buf[buflen - 1] = '\0';
return (buf);
} /* char *sstrerror */
if ((len = strlen (file_orig)) < 1)
return (-1);
- else if (len >= 512)
+ else if (len >= sizeof (file_copy))
return (-1);
/*
/*
* Create a copy for `strtok_r' to destroy
*/
- strncpy (file_copy, file_orig, 512);
- file_copy[511] = '\0';
+ sstrncpy (file_copy, file_orig, sizeof (file_copy));
/*
* Break into components. This will eat up several slashes in a row and
if (kc == NULL)
return (-1);
- snprintf (ident, 128, "%s,%i,%s", module, instance, name);
- ident[127] = '\0';
+ ssnprintf (ident, sizeof (ident), "%s,%i,%s", module, instance, name);
if (*ksp_ptr == NULL)
{
if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0))
{
if ((type_instance == NULL) || (strlen (type_instance) == 0))
- status = snprintf (ret, ret_len, "%s/%s/%s",
+ status = ssnprintf (ret, ret_len, "%s/%s/%s",
hostname, plugin, type);
else
- status = snprintf (ret, ret_len, "%s/%s/%s-%s",
+ status = ssnprintf (ret, ret_len, "%s/%s/%s-%s",
hostname, plugin, type,
type_instance);
}
else
{
if ((type_instance == NULL) || (strlen (type_instance) == 0))
- status = snprintf (ret, ret_len, "%s/%s-%s/%s",
+ status = ssnprintf (ret, ret_len, "%s/%s-%s/%s",
hostname, plugin, plugin_instance,
type);
else
- status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s",
+ status = ssnprintf (ret, ret_len, "%s/%s-%s/%s-%s",
hostname, plugin, plugin_instance,
type, type_instance);
}
n->severity = severity;
if (message != NULL)
- strncpy (n->message, message, sizeof (n->message));
+ sstrncpy (n->message, message, sizeof (n->message));
if (host != NULL)
- strncpy (n->host, host, sizeof (n->host));
+ sstrncpy (n->host, host, sizeof (n->host));
if (plugin != NULL)
- strncpy (n->plugin, plugin, sizeof (n->plugin));
+ sstrncpy (n->plugin, plugin, sizeof (n->plugin));
if (plugin_instance != NULL)
- strncpy (n->plugin_instance, plugin_instance,
+ sstrncpy (n->plugin_instance, plugin_instance,
sizeof (n->plugin_instance));
if (type != NULL)
- strncpy (n->type, type, sizeof (n->type));
+ sstrncpy (n->type, type, sizeof (n->type));
if (type_instance != NULL)
- strncpy (n->type_instance, type_instance,
+ sstrncpy (n->type_instance, type_instance,
sizeof (n->type_instance));
- n->message[sizeof (n->message) - 1] = '\0';
- n->host[sizeof (n->host) - 1] = '\0';
- n->plugin[sizeof (n->plugin) - 1] = '\0';
- n->plugin_instance[sizeof (n->plugin_instance) - 1] = '\0';
- n->type[sizeof (n->type) - 1] = '\0';
- n->type_instance[sizeof (n->type_instance) - 1] = '\0';
-
return (0);
} /* int notification_init */
+
+int walk_directory (const char *dir, dirwalk_callback_f callback,
+ void *user_data)
+{
+ struct dirent *ent;
+ DIR *dh;
+ int success;
+ int failure;
+
+ success = 0;
+ failure = 0;
+
+ if ((dh = opendir (dir)) == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("walk_directory: Cannot open '%s': %s", dir,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return -1;
+ }
+
+ while ((ent = readdir (dh)) != NULL)
+ {
+ int status;
+
+ if (ent->d_name[0] == '.')
+ continue;
+
+ status = (*callback) (dir, ent->d_name, user_data);
+ if (status != 0)
+ failure++;
+ else
+ success++;
+ }
+
+ closedir (dh);
+
+ if ((success == 0) && (failure > 0))
+ return (-1);
+ return (0);
+}
+
+int read_file_contents (const char *filename, char *buf, int bufsize)
+{
+ FILE *fh;
+ int n;
+
+ if ((fh = fopen (filename, "r")) == NULL)
+ return -1;
+
+ n = fread(buf, 1, bufsize, fh);
+ fclose(fh);
+
+ return n;
+}
+
+
diff --git a/src/common.h b/src/common.h
index 9e7e4aa39d9319af5c7b3303ac252e8572f8dcbc..f463b77e0c3b6f95707a4092d8f5310979ce3b5e 100644 (file)
--- a/src/common.h
+++ b/src/common.h
#define STATIC_ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
char *sstrncpy (char *dest, const char *src, size_t n);
+int ssnprintf (char *dest, size_t n, const char *format, ...);
char *sstrdup(const char *s);
void *smalloc(size_t size);
char *sstrerror (int errnum, char *buf, size_t buflen);
notification_init (n, NOTIF_FAILURE, NULL, \
(vl)->host, (vl)->plugin, (vl)->plugin_instance, \
(ds)->type, (vl)->type_instance)
+
+typedef int (*dirwalk_callback_f)(const char *dirname, const char *filename,
+ void *user_data);
+int walk_directory (const char *dir, dirwalk_callback_f callback,
+ void *user_data);
+int read_file_contents (const char *filename, char *buf, int bufsize);
+
#endif /* COMMON_H */
diff --git a/src/configfile.c b/src/configfile.c
index 8b526f2e958902a5dcbb22a674b0c0caa267f44f..9609086feca391d0e6c097c03eeef3e7207a5b74 100644 (file)
--- a/src/configfile.c
+++ b/src/configfile.c
else if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
{
char tmp[128];
- snprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number);
- tmp[127] = '\0';
+ ssnprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number);
return (global_option_set (ci->key, tmp));
}
else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
int status = -1;
if (ci->values[i].type == OCONFIG_TYPE_STRING)
- status = snprintf (buffer_ptr, buffer_free, " %s",
+ status = ssnprintf (buffer_ptr, buffer_free, " %s",
ci->values[i].value.string);
else if (ci->values[i].type == OCONFIG_TYPE_NUMBER)
- status = snprintf (buffer_ptr, buffer_free, " %lf",
+ status = ssnprintf (buffer_ptr, buffer_free, " %lf",
ci->values[i].value.number);
else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
- status = snprintf (buffer_ptr, buffer_free, " %s",
+ status = ssnprintf (buffer_ptr, buffer_free, " %s",
ci->values[i].value.boolean
? "true" : "false");
if ((de->d_name[0] == '.') || (de->d_name[0] == '\0'))
continue;
- status = snprintf (name, sizeof (name), "%s/%s",
+ status = ssnprintf (name, sizeof (name), "%s/%s",
dir, de->d_name);
if (status >= sizeof (name))
{
diff --git a/src/cpu.c b/src/cpu.c
index 0fadc06458d2fbb5ace382a731bb6bcf19283bb3..e9ab78320d4523848274f726eb42e2bb87eb030f 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "cpu", sizeof (vl.plugin));
- snprintf (vl.plugin_instance, sizeof (vl.type_instance),
+ ssnprintf (vl.plugin_instance, sizeof (vl.type_instance),
"%i", cpu_num);
- vl.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+ sstrncpy (vl.type, "cpu", sizeof (vl.type));
sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values ("cpu", &vl);
+ plugin_dispatch_values (&vl);
}
static int cpu_read (void)
diff --git a/src/cpufreq.c b/src/cpufreq.c
index 74e542b49745c151020ac4d849ff86815bc49339..3738b54c2f450eb8f3f4e52994f9180b369d3850 100644 (file)
--- a/src/cpufreq.c
+++ b/src/cpufreq.c
while (1)
{
- status = snprintf (filename, sizeof (filename),
+ status = ssnprintf (filename, sizeof (filename),
"/sys/devices/system/cpu/cpu%d/cpufreq/"
"scaling_cur_freq", num_cpu);
if ((status < 1) || ((unsigned int)status >= sizeof (filename)))
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "cpufreq", sizeof (vl.plugin));
- snprintf (vl.type_instance, sizeof (vl.type_instance),
+ sstrncpy (vl.type, "cpufreq", sizeof (vl.type));
+ ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%i", cpu_num);
- plugin_dispatch_values ("cpufreq", &vl);
+ plugin_dispatch_values (&vl);
}
static int cpufreq_read (void)
for (i = 0; i < num_cpu; i++)
{
- status = snprintf (filename, sizeof (filename),
+ status = ssnprintf (filename, sizeof (filename),
"/sys/devices/system/cpu/cpu%d/cpufreq/"
"scaling_cur_freq", i);
if ((status < 1) || ((unsigned int)status >= sizeof (filename)))
diff --git a/src/csv.c b/src/csv.c
index ff59f91c006e81511b6aeec738000398ed945bdc..a94b7001025419602961980efa993506e9755b33 100644 (file)
--- a/src/csv.c
+++ b/src/csv.c
int i;
gauge_t *rates = NULL;
+ assert (0 == strcmp (ds->type, vl->type));
+
memset (buffer, '\0', buffer_len);
- status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
+ status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
if ((status < 1) || (status >= buffer_len))
return (-1);
offset = status;
{
if (store_rates == 0)
{
- status = snprintf (buffer + offset,
+ status = ssnprintf (buffer + offset,
buffer_len - offset,
",%llu",
vl->values[i].counter);
"uc_get_rate failed.");
return (-1);
}
- status = snprintf (buffer + offset,
+ status = ssnprintf (buffer + offset,
buffer_len - offset,
",%lf", rates[i]);
}
}
else /* if (ds->ds[i].type == DS_TYPE_GAUGE) */
{
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
",%lf", vl->values[i].gauge);
}
int offset = 0;
int status;
+ assert (0 == strcmp (ds->type, vl->type));
+
if (datadir != NULL)
{
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
"%s/", datadir);
if ((status < 1) || (status >= buffer_len - offset))
return (-1);
offset += status;
}
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
"%s/", vl->host);
if ((status < 1) || (status >= buffer_len - offset))
return (-1);
offset += status;
if (strlen (vl->plugin_instance) > 0)
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
"%s-%s/", vl->plugin, vl->plugin_instance);
else
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
"%s/", vl->plugin);
if ((status < 1) || (status >= buffer_len - offset))
return (-1);
offset += status;
if (strlen (vl->type_instance) > 0)
- status = snprintf (buffer + offset, buffer_len - offset,
- "%s-%s", ds->type, vl->type_instance);
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s-%s", vl->type, vl->type_instance);
else
- status = snprintf (buffer + offset, buffer_len - offset,
- "%s", ds->type);
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s", vl->type);
if ((status < 1) || (status >= buffer_len - offset))
return (-1);
offset += status;
struct flock fl;
int status;
+ if (0 != strcmp (ds->type, vl->type)) {
+ ERROR ("csv plugin: DS type does not match value list type");
+ return -1;
+ }
+
if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
return (-1);
diff --git a/src/df.c b/src/df.c
index 6bd92500834c1659c2066c11d124bea27dbab5d1..26d23826fccf32c81420f417192956737f64bdc8 100644 (file)
--- a/src/df.c
+++ b/src/df.c
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "df", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
- strncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
+ sstrncpy (vl.type, "df", sizeof (vl.host));
+ sstrncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
- plugin_dispatch_values ("df", &vl);
+ plugin_dispatch_values (&vl);
} /* void df_submit */
static int df_read (void)
if (strcmp (mnt_ptr->dir, "/") == 0)
{
- strncpy (mnt_name, "root", sizeof (mnt_name));
+ sstrncpy (mnt_name, "root", sizeof (mnt_name));
}
else
{
int i, len;
- strncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
+ sstrncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
len = strlen (mnt_name);
for (i = 0; i < len; i++)
diff --git a/src/disk.c b/src/disk.c
index 20afd30b602fca4b10e9ccfe1b8a9ecfbf22a15c..29aa979018b42bc9621d5b011a73daf0ae12722c 100644 (file)
--- a/src/disk.c
+++ b/src/disk.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, plugin_instance,
+ sstrncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void disk_submit */
#if HAVE_IOKIT_IOKITLIB_H
write_tme = dict_get_value (stats_dict,
kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
- if (snprintf (disk_name, 64, "%i-%i", disk_major, disk_minor) >= 64)
+ if (ssnprintf (disk_name, sizeof (disk_name),
+ "%i-%i", disk_major, disk_minor) >= sizeof (disk_name))
{
DEBUG ("snprintf (major, minor) failed.");
CFRelease (child_dict);
diff --git a/src/dns.c b/src/dns.c
index 69cb1922c3fd26ca8306f6c91fa1882ed4ccf364..c04169fec8a4809cb9e7b5516b5011e8d49a6e3a 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "dns", sizeof (vl.plugin));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void submit_counter */
static void submit_octets (counter_t queries, counter_t responses)
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "dns", sizeof (vl.plugin));
+ sstrncpy (vl.type, "dns_octets", sizeof (vl.type));
- plugin_dispatch_values ("dns_octets", &vl);
+ plugin_dispatch_values (&vl);
} /* void submit_counter */
static int dns_read (void)
diff --git a/src/email.c b/src/email.c
index 0882ad46299b5d118494c0407c7f4a9a0f17a9cb..e208f13049f168cbc08775366d5e01f7523c1982 100644 (file)
--- a/src/email.c
+++ b/src/email.c
}
addr.sun_family = AF_UNIX;
-
- strncpy (addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
- addr.sun_path[UNIX_PATH_MAX - 1] = '\0';
+ sstrncpy (addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
errno = 0;
if (-1 == bind (connector_socket, (struct sockaddr *)&addr,
@@ -655,9 +653,10 @@ static void email_submit (const char *type, const char *type_instance, gauge_t v
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "email", sizeof (vl.plugin));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void email_submit */
/* Copy list l1 to list l2. l2 may partly exist already, but it is assumed
diff --git a/src/entropy.c b/src/entropy.c
index 69ce3142bc7f4e412ded5f0483be4c793f3cb7d6..2e20a67c08661dbdebd4e66e276184e17d97983b 100644 (file)
--- a/src/entropy.c
+++ b/src/entropy.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "entropy", sizeof (vl.plugin));
- sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
- sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+ sstrncpy (vl.type, "entropy", sizeof (vl.type));
- plugin_dispatch_values ("entropy", &vl);
+ plugin_dispatch_values (&vl);
}
static int entropy_read (void)
diff --git a/src/exec.c b/src/exec.c
index 07c35c9bcf36d0e307ebbc48a93fb1e7fafa57e1..711ec996861897bfa87ecb9e5adf1e6bb1078aca 100644 (file)
--- a/src/exec.c
+++ b/src/exec.c
{
char *tmp = strrchr (ci->values[1].value.string, '/');
if (tmp == NULL)
- strncpy (buffer, ci->values[1].value.string, sizeof (buffer));
+ sstrncpy (buffer, ci->values[1].value.string, sizeof (buffer));
else
- strncpy (buffer, tmp + 1, sizeof (buffer));
- buffer[sizeof (buffer) - 1] = '\0';
+ sstrncpy (buffer, tmp + 1, sizeof (buffer));
}
pl->argv[0] = strdup (buffer);
if (pl->argv[0] == NULL)
{
if (ci->values[i + 1].type == OCONFIG_TYPE_NUMBER)
{
- snprintf (buffer, sizeof (buffer), "%lf",
+ ssnprintf (buffer, sizeof (buffer), "%lf",
ci->values[i + 1].value.number);
}
else
{
if (ci->values[i + 1].value.boolean)
- strncpy (buffer, "true", sizeof (buffer));
+ sstrncpy (buffer, "true", sizeof (buffer));
else
- strncpy (buffer, "false", sizeof (buffer));
+ sstrncpy (buffer, "false", sizeof (buffer));
}
- buffer[sizeof (buffer) - 1] = '\0';
pl->argv[i] = strdup (buffer);
}
@@ -492,19 +490,19 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
static int parse_line (char *buffer) /* {{{ */
{
- char *fields[256];
- int fields_num;
-
- fields[0] = "PUTVAL";
- fields_num = strsplit (buffer, fields + 1, STATIC_ARRAY_SIZE(fields) - 1);
-
- if (strcasecmp (fields[1], "putval") == 0)
- return (handle_putval (stdout, fields + 1, fields_num));
- else if (strcasecmp (fields[1], "putnotif") == 0)
- return (handle_putnotif (stdout, fields + 1, fields_num));
-
- /* compatibility code */
- return (handle_putval (stdout, fields, fields_num + 1));
+ if (strncasecmp ("PUTVAL", buffer, strlen ("PUTVAL")) == 0)
+ return (handle_putval (stdout, buffer));
+ else if (strncasecmp ("PUTNOTIF", buffer, strlen ("PUTNOTIF")) == 0)
+ return (handle_putnotif (stdout, buffer));
+ else
+ {
+ /* For backwards compatibility */
+ char tmp[1220];
+ /* Let's annoy the user a bit.. */
+ INFO ("exec plugin: Prepending `PUTVAL' to this line: %s", buffer);
+ ssnprintf (tmp, sizeof (tmp), "PUTVAL %s", buffer);
+ return (handle_putval (stdout, tmp));
+ }
} /* int parse_line }}} */
static void *exec_read_one (void *arg) /* {{{ */
static void *exec_notification_one (void *arg) /* {{{ */
{
program_list_t *pl = ((program_list_and_notification_t *) arg)->pl;
- const notification_t *n = &((program_list_and_notification_t *) arg)->n;
+ notification_t *n = &((program_list_and_notification_t *) arg)->n;
+ notification_meta_t *meta;
int fd;
FILE *fh;
int pid;
if (strlen (n->type_instance) > 0)
fprintf (fh, "TypeInstance: %s\n", n->type_instance);
+ for (meta = n->meta; meta != NULL; meta = meta->next)
+ {
+ if (meta->type == NM_TYPE_STRING)
+ fprintf (fh, "%s: %s\n", meta->name, meta->value_string);
+ else if (meta->type == NM_TYPE_SIGNED_INT)
+ fprintf (fh, "%s: %"PRIi64"\n", meta->name, meta->value_signed_int);
+ else if (meta->type == NM_TYPE_UNSIGNED_INT)
+ fprintf (fh, "%s: %"PRIu64"\n", meta->name, meta->value_unsigned_int);
+ else if (meta->type == NM_TYPE_DOUBLE)
+ fprintf (fh, "%s: %e\n", meta->name, meta->value_double);
+ else if (meta->type == NM_TYPE_BOOLEAN)
+ fprintf (fh, "%s: %s\n", meta->name,
+ meta->value_boolean ? "true" : "false");
+ }
+
fprintf (fh, "\n%s\n", n->message);
fflush (fh);
DEBUG ("exec plugin: Child %i exited with status %i.",
pid, status);
+ plugin_notification_meta_free (n);
sfree (arg);
pthread_exit ((void *) 0);
return (NULL);
pln->pl = pl;
memcpy (&pln->n, n, sizeof (notification_t));
+ /* Set the `meta' member to NULL, otherwise `plugin_notification_meta_copy'
+ * will run into an endless loop. */
+ pln->n.meta = NULL;
+ plugin_notification_meta_copy (&pln->n, n);
+
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&t, &attr, exec_notification_one, (void *) pln);
diff --git a/src/filecount.c b/src/filecount.c
--- /dev/null
+++ b/src/filecount.c
@@ -0,0 +1,546 @@
+/**
+ * collectd - src/filecount.c
+ * Copyright (C) 2008 Alessandro Iurlano
+ * Copyright (C) 2008 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Alessandro Iurlano <alessandro.iurlano at gmail.com>
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <fnmatch.h>
+
+struct fc_directory_conf_s
+{
+ char *path;
+ char *instance;
+
+ /* Data counters */
+ uint64_t files_num;
+ uint64_t files_size;
+
+ /* Selectors */
+ char *name;
+ int64_t mtime;
+ int64_t size;
+
+ /* Helper for the recursive functions */
+ time_t now;
+};
+typedef struct fc_directory_conf_s fc_directory_conf_t;
+
+static fc_directory_conf_t **directories = NULL;
+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.time = time (NULL);
+ 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));
+ sstrncpy (vl.type, "files", sizeof (vl.type));
+
+ plugin_dispatch_values (&vl);
+
+ values[0].gauge = (gauge_t) dir->files_size;
+ sstrncpy (vl.type, "bytes", sizeof (vl.type));
+
+ plugin_dispatch_values (&vl);
+} /* void fc_submit_dir */
+
+/*
+ * Config:
+ * <Plugin filecount>
+ * <Directory /path/to/dir>
+ * Instance "foobar"
+ * Name "*.conf"
+ * MTime -3600
+ * Size "+10M"
+ * </Directory>
+ * </Plugin>
+ *
+ * Collect:
+ * - Number of files
+ * - Total size
+ */
+
+static int fc_config_set_instance (fc_directory_conf_t *dir, const char *str)
+{
+ char buffer[1024];
+ char *ptr;
+ char *copy;
+
+ sstrncpy (buffer, str, sizeof (buffer));
+ for (ptr = buffer; *ptr != 0; ptr++)
+ if (*ptr == '/')
+ *ptr = '_';
+
+ for (ptr = buffer; *ptr == '_'; ptr++)
+ /* do nothing */;
+
+ if (*ptr == 0)
+ return (-1);
+
+ copy = strdup (ptr);
+ if (copy == NULL)
+ return (-1);
+
+ sfree (dir->instance);
+ dir->instance = copy;
+
+ return (0);
+} /* int fc_config_set_instance */
+
+static int fc_config_add_dir_instance (fc_directory_conf_t *dir,
+ oconfig_item_t *ci)
+{
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("filecount plugin: The `Instance' config option needs exactly "
+ "one string argument.");
+ return (-1);
+ }
+
+ return (fc_config_set_instance (dir, ci->values[0].value.string));
+} /* int fc_config_add_dir_instance */
+
+static int fc_config_add_dir_name (fc_directory_conf_t *dir,
+ oconfig_item_t *ci)
+{
+ char *temp;
+
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("filecount plugin: The `Name' config option needs exactly one "
+ "string argument.");
+ return (-1);
+ }
+
+ temp = strdup (ci->values[0].value.string);
+ if (temp == NULL)
+ {
+ ERROR ("filecount plugin: strdup failed.");
+ return (-1);
+ }
+
+ sfree (dir->name);
+ dir->name = temp;
+
+ return (0);
+} /* int fc_config_add_dir_name */
+
+static int fc_config_add_dir_mtime (fc_directory_conf_t *dir,
+ oconfig_item_t *ci)
+{
+ char *endptr;
+ double temp;
+
+ if ((ci->values_num != 1)
+ || ((ci->values[0].type != OCONFIG_TYPE_STRING)
+ && (ci->values[0].type != OCONFIG_TYPE_NUMBER)))
+ {
+ WARNING ("filecount plugin: The `MTime' config option needs exactly one "
+ "string or numeric argument.");
+ return (-1);
+ }
+
+ if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
+ {
+ dir->mtime = (int64_t) ci->values[0].value.number;
+ return (0);
+ }
+
+ errno = 0;
+ endptr = NULL;
+ temp = strtod (ci->values[0].value.string, &endptr);
+ if ((errno != 0) || (endptr == NULL)
+ || (endptr == ci->values[0].value.string))
+ {
+ WARNING ("filecount plugin: Converting `%s' to a number failed.",
+ ci->values[0].value.string);
+ return (-1);
+ }
+
+ switch (*endptr)
+ {
+ case 0:
+ case 's':
+ case 'S':
+ break;
+
+ case 'm':
+ case 'M':
+ temp *= 60;
+ break;
+
+ case 'h':
+ case 'H':
+ temp *= 3600;
+ break;
+
+ case 'd':
+ case 'D':
+ temp *= 86400;
+ break;
+
+ case 'w':
+ case 'W':
+ temp *= 7 * 86400;
+ break;
+
+ case 'y':
+ case 'Y':
+ temp *= 31557600; /* == 365.25 * 86400 */
+ break;
+
+ default:
+ WARNING ("filecount plugin: Invalid suffix for `MTime': `%c'", *endptr);
+ return (-1);
+ } /* switch (*endptr) */
+
+ dir->mtime = (int64_t) temp;
+
+ return (0);
+} /* int fc_config_add_dir_mtime */
+
+static int fc_config_add_dir_size (fc_directory_conf_t *dir,
+ oconfig_item_t *ci)
+{
+ char *endptr;
+ double temp;
+
+ if ((ci->values_num != 1)
+ || ((ci->values[0].type != OCONFIG_TYPE_STRING)
+ && (ci->values[0].type != OCONFIG_TYPE_NUMBER)))
+ {
+ WARNING ("filecount plugin: The `Size' config option needs exactly one "
+ "string or numeric argument.");
+ return (-1);
+ }
+
+ if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
+ {
+ dir->size = (int64_t) ci->values[0].value.number;
+ return (0);
+ }
+
+ errno = 0;
+ endptr = NULL;
+ temp = strtod (ci->values[0].value.string, &endptr);
+ if ((errno != 0) || (endptr == NULL)
+ || (endptr == ci->values[0].value.string))
+ {
+ WARNING ("filecount plugin: Converting `%s' to a number failed.",
+ ci->values[0].value.string);
+ return (-1);
+ }
+
+ switch (*endptr)
+ {
+ case 0:
+ case 'b':
+ case 'B':
+ break;
+
+ case 'k':
+ case 'K':
+ temp *= 1000.0;
+ break;
+
+ case 'm':
+ case 'M':
+ temp *= 1000.0 * 1000.0;
+ break;
+
+ case 'g':
+ case 'G':
+ temp *= 1000.0 * 1000.0 * 1000.0;
+ break;
+
+ case 't':
+ case 'T':
+ temp *= 1000.0 * 1000.0 * 1000.0 * 1000.0;
+ break;
+
+ case 'p':
+ case 'P':
+ temp *= 1000.0 * 1000.0 * 1000.0 * 1000.0 * 1000.0;
+ break;
+
+ default:
+ WARNING ("filecount plugin: Invalid suffix for `Size': `%c'", *endptr);
+ return (-1);
+ } /* switch (*endptr) */
+
+ dir->size = (int64_t) temp;
+
+ return (0);
+} /* int fc_config_add_dir_size */
+
+static int fc_config_add_dir (oconfig_item_t *ci)
+{
+ fc_directory_conf_t *dir;
+ int status;
+ int i;
+
+ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("filecount plugin: `Directory' needs exactly one string "
+ "argument.");
+ return (-1);
+ }
+
+ /* Initialize `dir' */
+ dir = (fc_directory_conf_t *) malloc (sizeof (*dir));
+ if (dir == NULL)
+ {
+ ERROR ("filecount plugin: malloc failed.");
+ return (-1);
+ }
+ memset (dir, 0, sizeof (*dir));
+
+ dir->path = strdup (ci->values[0].value.string);
+ if (dir->path == NULL)
+ {
+ ERROR ("filecount plugin: strdup failed.");
+ return (-1);
+ }
+
+ fc_config_set_instance (dir, dir->path);
+
+ dir->name = NULL;
+ dir->mtime = 0;
+ dir->size = 0;
+
+ status = 0;
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *option = ci->children + i;
+
+ if (strcasecmp ("Instance", option->key) == 0)
+ status = fc_config_add_dir_instance (dir, option);
+ else if (strcasecmp ("Name", option->key) == 0)
+ status = fc_config_add_dir_name (dir, option);
+ else if (strcasecmp ("MTime", option->key) == 0)
+ status = fc_config_add_dir_mtime (dir, option);
+ else if (strcasecmp ("Size", option->key) == 0)
+ status = fc_config_add_dir_size (dir, option);
+ else
+ {
+ WARNING ("filecount plugin: fc_config_add_dir: "
+ "Option `%s' not allowed here.", option->key);
+ status = -1;
+ }
+
+ if (status != 0)
+ break;
+ } /* for (ci->children) */
+
+ if (status == 0)
+ {
+ fc_directory_conf_t **temp;
+
+ temp = (fc_directory_conf_t **) realloc (directories,
+ sizeof (*directories) * directories_num);
+ if (temp == NULL)
+ {
+ ERROR ("filecount plugin: realloc failed.");
+ status = -1;
+ }
+ else
+ {
+ directories = temp;
+ directories[directories_num] = dir;
+ directories_num++;
+ }
+ }
+
+ if (status != 0)
+ {
+ sfree (dir->name);
+ sfree (dir->instance);
+ sfree (dir->path);
+ sfree (dir);
+ return (-1);
+ }
+
+ return (0);
+} /* int fc_config_add_dir */
+
+static int fc_config (oconfig_item_t *ci)
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("Directory", child->key) == 0)
+ fc_config_add_dir (child);
+ else
+ {
+ WARNING ("filecount plugin: Ignoring unknown config option `%s'.",
+ child->key);
+ }
+ } /* for (ci->children) */
+
+ return (0);
+} /* int fc_config */
+
+static int fc_init (void)
+{
+ if (directories_num < 1)
+ {
+ WARNING ("filecount plugin: No directories have been configured.");
+ return (-1);
+ }
+
+ return (0);
+} /* int fc_init */
+
+static int fc_read_dir_callback (const char *dirname, const char *filename,
+ void *user_data)
+{
+ fc_directory_conf_t *dir = user_data;
+ char abs_path[PATH_MAX];
+ struct stat statbuf;
+ int status;
+
+ if (dir == NULL)
+ return (-1);
+
+ ssnprintf (abs_path, sizeof (abs_path), "%s/%s", dirname, filename);
+
+ status = lstat (abs_path, &statbuf);
+ if (status != 0)
+ {
+ ERROR ("filecount plugin: stat (%s) failed.", abs_path);
+ return (-1);
+ }
+
+ if (S_ISDIR (statbuf.st_mode))
+ {
+ status = walk_directory (abs_path, fc_read_dir_callback, dir);
+ return (status);
+ }
+ else if (!S_ISREG (statbuf.st_mode))
+ {
+ return (0);
+ }
+
+ if (dir->name != NULL)
+ {
+ status = fnmatch (dir->name, filename, /* flags = */ 0);
+ if (status != 0)
+ return (0);
+ }
+
+ if (dir->mtime != 0)
+ {
+ time_t mtime = dir->now;
+
+ if (dir->mtime < 0)
+ mtime += dir->mtime;
+ else
+ mtime -= dir->mtime;
+
+ DEBUG ("filecount plugin: Only collecting files that were touched %s %u.",
+ (dir->mtime < 0) ? "after" : "before",
+ (unsigned int) mtime);
+
+ if (((dir->mtime < 0) && (statbuf.st_mtime < mtime))
+ || ((dir->mtime > 0) && (statbuf.st_mtime > mtime)))
+ return (0);
+ }
+
+ if (dir->size != 0)
+ {
+ off_t size;
+
+ if (dir->size < 0)
+ size = (off_t) ((-1) * dir->size);
+ else
+ size = (off_t) dir->size;
+
+ if (((dir->size < 0) && (statbuf.st_size > size))
+ || ((dir->size > 0) && (statbuf.st_size < size)))
+ return (0);
+ }
+
+ dir->files_num++;
+ dir->files_size += (uint64_t) statbuf.st_size;
+
+ return (0);
+} /* int fc_read_dir_callback */
+
+static int fc_read_dir (fc_directory_conf_t *dir)
+{
+ int status;
+
+ dir->files_num = 0;
+ dir->files_size = 0;
+
+ if (dir->mtime != 0)
+ dir->now = time (NULL);
+
+ status = walk_directory (dir->path, fc_read_dir_callback, dir);
+ if (status != 0)
+ {
+ WARNING ("filecount plugin: walk_directory (%s) failed.", dir->path);
+ return (-1);
+ }
+
+ fc_submit_dir (dir);
+
+ return (0);
+} /* int fc_read_dir */
+
+static int fc_read (void)
+{
+ size_t i;
+
+ for (i = 0; i < directories_num; i++)
+ fc_read_dir (directories[i]);
+
+ return (0);
+} /* int fc_read */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("filecount", fc_config);
+ plugin_register_init ("filecount", fc_init);
+ plugin_register_read ("filecount", fc_read);
+} /* void module_register */
+
+/*
+ * vim: set sw=2 sts=2 et :
+ */
diff --git a/src/hddtemp.c b/src/hddtemp.c
index cb49577057f9e277c1777e9710dc351775483be9..9f4a7254feede2d27d057bdf5750bb1ee3f73ba2 100644 (file)
--- a/src/hddtemp.c
+++ b/src/hddtemp.c
{
int port = (int) (atof (value));
if ((port > 0) && (port <= 65535))
- snprintf (hddtemp_port, sizeof (hddtemp_port),
+ ssnprintf (hddtemp_port, sizeof (hddtemp_port),
"%i", port);
else
- strncpy (hddtemp_port, value, sizeof (hddtemp_port));
- hddtemp_port[sizeof (hddtemp_port) - 1] = '\0';
+ sstrncpy (hddtemp_port, value, sizeof (hddtemp_port));
}
else if (strcasecmp (key, "TranslateDevicename") == 0)
{
if ((ret = (char *) malloc (128 * sizeof (char))) == NULL)
return (NULL);
- if (snprintf (ret, 128, "%i-%i", list->major, list->minor) >= 128)
+ if (ssnprintf (ret, 128, "%i-%i", list->major, list->minor) >= 128)
{
free (ret);
return (NULL);
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "hddtemp", sizeof (vl.plugin));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type, "temperature", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values ("temperature", &vl);
+ plugin_dispatch_values (&vl);
}
static int hddtemp_read (void)
diff --git a/src/interface.c b/src/interface.c
index 2add89d750004b163c85da9536ede49443dbb400..806a336dfde09c814c9ab9f204e5770758251893 100644 (file)
--- a/src/interface.c
+++ b/src/interface.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "interface", sizeof (vl.plugin));
- strncpy (vl.type_instance, dev, sizeof (vl.type_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, dev, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void if_submit */
static int interface_read (void)
diff --git a/src/ipmi.c b/src/ipmi.c
index 956aaf44c25cc3bf659e02e7768bca6268449f24..e219e89ca197508144584c9bb5a8d477ad8d73fc 100644 (file)
--- a/src/ipmi.c
+++ b/src/ipmi.c
/**
* collectd - src/ipmi.c
* Copyright (C) 2008 Florian octo Forster
+ * Copyright (C) 2008 Peter Holik
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
*
* Authors:
* Florian octo Forster <octo at verplant.org>
+ * Peter Holik <peter at holik.at>
**/
#include "collectd.h"
struct c_ipmi_sensor_list_s
{
ipmi_sensor_id_t sensor_id;
+ char sensor_name[DATA_MAX_NAME_LEN];
+ char sensor_type[DATA_MAX_NAME_LEN];
+ int sensor_not_present;
c_ipmi_sensor_list_t *next;
};
static pthread_mutex_t sensor_list_lock = PTHREAD_MUTEX_INITIALIZER;
static c_ipmi_sensor_list_t *sensor_list = NULL;
+static int c_ipmi_init_in_progress = 0;
static int c_ipmi_active = 0;
static pthread_t thread_id = (pthread_t) 0;
static const char *config_keys[] =
{
"Sensor",
- "IgnoreSelected"
+ "IgnoreSelected",
+ "NotifySensorAdd",
+ "NotifySensorRemove",
+ "NotifySensorNotPresent"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static ignorelist_t *ignorelist = NULL;
+static int c_ipmi_nofiy_add = 0;
+static int c_ipmi_nofiy_remove = 0;
+static int c_ipmi_nofiy_notpresent = 0;
+
/*
* Misc private functions
*/
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- char sensor_name[IPMI_SENSOR_NAME_LEN];
- char *sensor_name_ptr;
- int sensor_type;
- const char *type;
-
- memset (sensor_name, 0, sizeof (sensor_name));
- ipmi_sensor_get_name (sensor, sensor_name, sizeof (sensor_name));
- sensor_name[sizeof (sensor_name) - 1] = 0;
-
- sensor_name_ptr = strstr (sensor_name, ").");
- if (sensor_name_ptr == NULL)
- sensor_name_ptr = sensor_name;
- else
- sensor_name_ptr += 2;
+ c_ipmi_sensor_list_t *list_item = (c_ipmi_sensor_list_t *)user_data;
if (err != 0)
{
- INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
- "because it failed with status %#x.",
- sensor_name_ptr, err);
- sensor_list_remove (sensor);
+ if ((err & 0xff) == IPMI_NOT_PRESENT_CC)
+ {
+ if (list_item->sensor_not_present == 0)
+ {
+ list_item->sensor_not_present = 1;
+
+ INFO ("ipmi plugin: sensor_read_handler: sensor %s "
+ "not present.", list_item->sensor_name);
+
+ if (c_ipmi_nofiy_notpresent)
+ {
+ notification_t n = { NOTIF_WARNING, time(NULL), "", "", "ipmi",
+ "", "", "", NULL };
+
+ sstrncpy (n.host, hostname_g, sizeof (n.host));
+ sstrncpy (n.type_instance, list_item->sensor_name,
+ sizeof (n.type_instance));
+ sstrncpy (n.type, list_item->sensor_type, sizeof (n.type));
+ ssnprintf (n.message, sizeof (n.message),
+ "sensor %s not present", list_item->sensor_name);
+
+ plugin_dispatch_notification (&n);
+ }
+ }
+ }
+ else
+ {
+ INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
+ "because it failed with status %#x.",
+ list_item->sensor_name, err);
+ sensor_list_remove (sensor);
+ }
return;
}
+ else if (list_item->sensor_not_present == 1)
+ {
+ list_item->sensor_not_present = 0;
+
+ INFO ("ipmi plugin: sensor_read_handler: sensor %s present.",
+ list_item->sensor_name);
+
+ if (c_ipmi_nofiy_notpresent)
+ {
+ notification_t n = { NOTIF_OKAY, time(NULL), "", "", "ipmi",
+ "", "", "", NULL };
+
+ sstrncpy (n.host, hostname_g, sizeof (n.host));
+ sstrncpy (n.type_instance, list_item->sensor_name,
+ sizeof (n.type_instance));
+ sstrncpy (n.type, list_item->sensor_type, sizeof (n.type));
+ ssnprintf (n.message, sizeof (n.message),
+ "sensor %s present", list_item->sensor_name);
+
+ plugin_dispatch_notification (&n);
+ }
+ }
if (value_present != IPMI_BOTH_VALUES_PRESENT)
{
INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
"because it provides %s. If you need this sensor, "
"please file a bug report.",
- sensor_name_ptr,
+ list_item->sensor_name,
(value_present == IPMI_RAW_VALUE_PRESENT)
? "only the raw value"
: "no value");
return;
}
- /* Both `ignorelist' and `plugin_instance' may be NULL. */
- if (ignorelist_match (ignorelist, sensor_name_ptr) != 0)
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "ipmi", sizeof (vl.plugin));
+ sstrncpy (vl.type, list_item->sensor_type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, list_item->sensor_name, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+} /* void sensor_read_handler */
+
+static int sensor_list_add (ipmi_sensor_t *sensor)
+{
+ ipmi_sensor_id_t sensor_id;
+ c_ipmi_sensor_list_t *list_item;
+ c_ipmi_sensor_list_t *list_prev;
+
+ char sensor_name[DATA_MAX_NAME_LEN];
+ char *sensor_name_ptr;
+ int sensor_type, len;
+ const char *type;
+ ipmi_entity_t *ent = ipmi_sensor_get_entity(sensor);
+
+ sensor_id = ipmi_sensor_convert_to_id (sensor);
+
+ memset (sensor_name, 0, sizeof (sensor_name));
+ ipmi_sensor_get_name (sensor, sensor_name, sizeof (sensor_name));
+ sensor_name[sizeof (sensor_name) - 1] = 0;
+
+ len = DATA_MAX_NAME_LEN - strlen(sensor_name);
+ strncat(sensor_name, " ", len--);
+ strncat(sensor_name, ipmi_entity_get_entity_id_string(ent), len);
+
+ sensor_name_ptr = strstr (sensor_name, ").");
+ if (sensor_name_ptr == NULL)
+ sensor_name_ptr = sensor_name;
+ else
{
- sensor_list_remove (sensor);
- return;
+ char *sensor_name_ptr_id = strstr (sensor_name, "(");
+
+ sensor_name_ptr += 2;
+ len = DATA_MAX_NAME_LEN - strlen(sensor_name);
+ strncat(sensor_name, " ", len--);
+ strncat(sensor_name, sensor_name_ptr_id,
+ MIN(sensor_name_ptr - sensor_name_ptr_id - 1, len));
}
+ /* Both `ignorelist' and `plugin_instance' may be NULL. */
+ if (ignorelist_match (ignorelist, sensor_name_ptr) != 0)
+ return (0);
+
/* FIXME: Use rate unit or base unit to scale the value */
sensor_type = ipmi_sensor_get_sensor_type (sensor);
default:
{
const char *sensor_type_str;
-
+
sensor_type_str = ipmi_sensor_get_sensor_type_string (sensor);
- INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
+ INFO ("ipmi plugin: sensor_list_add: Ignore sensor %s, "
"because I don't know how to handle its type (%#x, %s). "
"If you need this sensor, please file a bug report.",
sensor_name_ptr, sensor_type, sensor_type_str);
- sensor_list_remove (sensor);
- return;
+ return (-1);
}
} /* switch (sensor_type) */
- values[0].gauge = value;
-
- vl.values = values;
- vl.values_len = 1;
- vl.time = time (NULL);
-
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
- sstrncpy (vl.plugin, "ipmi", sizeof (vl.plugin));
- sstrncpy (vl.type_instance, sensor_name_ptr, sizeof (vl.type_instance));
-
- plugin_dispatch_values (type, &vl);
-} /* void sensor_read_handler */
-
-static int sensor_list_add (ipmi_sensor_t *sensor)
-{
- ipmi_sensor_id_t sensor_id;
- c_ipmi_sensor_list_t *list_item;
- c_ipmi_sensor_list_t *list_prev;
-
- sensor_id = ipmi_sensor_convert_to_id (sensor);
-
pthread_mutex_lock (&sensor_list_lock);
list_prev = NULL;
else
sensor_list = list_item;
+ sstrncpy (list_item->sensor_name, sensor_name_ptr,
+ sizeof (list_item->sensor_name));
+ sstrncpy (list_item->sensor_type, type, sizeof (list_item->sensor_type));
+
pthread_mutex_unlock (&sensor_list_lock);
+ if (c_ipmi_nofiy_add && (c_ipmi_init_in_progress == 0))
+ {
+ notification_t n = { NOTIF_OKAY, time(NULL), "", "", "ipmi",
+ "", "", "", NULL };
+
+ sstrncpy (n.host, hostname_g, sizeof (n.host));
+ sstrncpy (n.type_instance, list_item->sensor_name,
+ sizeof (n.type_instance));
+ sstrncpy (n.type, list_item->sensor_type, sizeof (n.type));
+ ssnprintf (n.message, sizeof (n.message),
+ "sensor %s added", list_item->sensor_name);
+
+ plugin_dispatch_notification (&n);
+ }
+
return (0);
} /* int sensor_list_add */
pthread_mutex_unlock (&sensor_list_lock);
+ if (c_ipmi_nofiy_remove && c_ipmi_active)
+ {
+ notification_t n = { NOTIF_WARNING, time(NULL), "", "",
+ "ipmi", "", "", "", NULL };
+
+ sstrncpy (n.host, hostname_g, sizeof (n.host));
+ sstrncpy (n.type_instance, list_item->sensor_name,
+ sizeof (n.type_instance));
+ sstrncpy (n.type, list_item->sensor_type, sizeof (n.type));
+ ssnprintf (n.message, sizeof (n.message),
+ "sensor %s removed", list_item->sensor_name);
+
+ plugin_dispatch_notification (&n);
+ }
+
free (list_item);
return (0);
} /* int sensor_list_remove */
list_item = list_item->next)
{
ipmi_sensor_id_get_reading (list_item->sensor_id,
- sensor_read_handler, /* user data = */ NULL);
+ sensor_read_handler, /* user data = */ list_item);
} /* for (list_item) */
pthread_mutex_unlock (&sensor_list_lock);
{
int invert = 1;
if ((strcasecmp ("True", value) == 0)
- || (strcasecmp ("Yes", value) == 0)
- || (strcasecmp ("On", value) == 0))
+ || (strcasecmp ("Yes", value) == 0)
+ || (strcasecmp ("On", value) == 0))
invert = 0;
ignorelist_set_invert (ignorelist, invert);
}
+ else if (strcasecmp ("NotifySensorAdd", key) == 0)
+ {
+ if ((strcasecmp ("True", value) == 0)
+ || (strcasecmp ("Yes", value) == 0)
+ || (strcasecmp ("On", value) == 0))
+ c_ipmi_nofiy_add = 1;
+ }
+ else if (strcasecmp ("NotifySensorRemove", key) == 0)
+ {
+ if ((strcasecmp ("True", value) == 0)
+ || (strcasecmp ("Yes", value) == 0)
+ || (strcasecmp ("On", value) == 0))
+ c_ipmi_nofiy_remove = 1;
+ }
+ else if (strcasecmp ("NotifySensorNotPresent", key) == 0)
+ {
+ if ((strcasecmp ("True", value) == 0)
+ || (strcasecmp ("Yes", value) == 0)
+ || (strcasecmp ("On", value) == 0))
+ c_ipmi_nofiy_notpresent = 1;
+ }
else
{
return (-1);
{
int status;
+ /* Don't send `ADD' notifications during startup (~ 1 minute) */
+ c_ipmi_init_in_progress = 1 + (60 / interval_g);
+
c_ipmi_active = 1;
status = pthread_create (&thread_id, /* attr = */ NULL, thread_main,
}
sensor_list_read_all ();
-
+
+ if (c_ipmi_init_in_progress > 0)
+ c_ipmi_init_in_progress--;
+ else
+ c_ipmi_init_in_progress = 0;
+
return (0);
} /* int c_ipmi_read */
diff --git a/src/iptables.c b/src/iptables.c
index ea8c65e9008916c6004d4ce0b9e41f24f78cba64..e1694af3475407ae75ba98de73e8b48598e63a56 100644 (file)
--- a/src/iptables.c
+++ b/src/iptables.c
table = fields[0];
chain = fields[1];
- table_len = strlen (table);
- if ((unsigned int)table_len >= sizeof(temp.table))
+ table_len = strlen (table) + 1;
+ if ((unsigned int)table_len > sizeof(temp.table))
{
ERROR ("Table `%s' too long.", table);
free (value_copy);
return (1);
}
- strncpy (temp.table, table, table_len);
- temp.table[table_len] = '\0';
+ sstrncpy (temp.table, table, table_len);
- chain_len = strlen (chain);
- if ((unsigned int)chain_len >= sizeof(temp.chain))
+ chain_len = strlen (chain) + 1;
+ if ((unsigned int)chain_len > sizeof(temp.chain))
{
ERROR ("Chain `%s' too long.", chain);
free (value_copy);
return (1);
}
- strncpy (temp.chain, chain, chain_len);
- temp.chain[chain_len] = '\0';
+ sstrncpy (temp.chain, chain, chain_len);
if (fields_num >= 3)
{
}
if (fields_num >= 4)
- strncpy (temp.name, fields[3], sizeof (temp.name) - 1);
+ sstrncpy (temp.name, fields[3], sizeof (temp.name));
free (value_copy);
value_copy = NULL;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin));
- status = snprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ status = ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
"%s-%s", chain->table, chain->chain);
if ((status < 1) || ((unsigned int)status >= sizeof (vl.plugin_instance)))
return (0);
if (chain->name[0] != '\0')
{
- strncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
+ sstrncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
}
else
{
if (chain->rule_type == RTYPE_NUM)
- snprintf (vl.type_instance, sizeof (vl.type_instance),
+ ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%i", chain->rule.num);
else
- strncpy (vl.type_instance, (char *) match->data,
+ sstrncpy (vl.type_instance, (char *) match->data,
sizeof (vl.type_instance));
}
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+ sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
values[0].counter = (counter_t) entry->counters.bcnt;
- plugin_dispatch_values ("ipt_bytes", &vl);
+ plugin_dispatch_values (&vl);
+ sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
values[0].counter = (counter_t) entry->counters.pcnt;
- plugin_dispatch_values ("ipt_packets", &vl);
+ plugin_dispatch_values (&vl);
return (0);
} /* void submit_match */
diff --git a/src/ipvs.c b/src/ipvs.c
index 2de28dd83918c782f31aada5e0d20859987b0729..85e65d27e57823f2fa3776237d125cf5db82e4d3 100644 (file)
--- a/src/ipvs.c
+++ b/src/ipvs.c
/* inet_ntoa() returns a pointer to a statically allocated buffer
* I hope non-glibc systems behave the same */
- len = snprintf (pi, size, "%s_%s%u", inet_ntoa (addr),
+ len = ssnprintf (pi, size, "%s_%s%u", inet_ntoa (addr),
(se->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
ntohs (se->port));
/* inet_ntoa() returns a pointer to a statically allocated buffer
* I hope non-glibc systems behave the same */
- len = snprintf (ti, size, "%s_%u", inet_ntoa (addr),
+ len = ssnprintf (ti, size, "%s_%u", inet_ntoa (addr),
ntohs (de->port));
if ((0 > len) || (size <= len)) {
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, pi, sizeof (vl.plugin_instance));
- sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total", sizeof (vl.type_instance));
+ sstrncpy (vl.type, "connections", sizeof (vl.type));
+ sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total",
+ sizeof (vl.type_instance));
- plugin_dispatch_values ("connections", &vl);
+ plugin_dispatch_values (&vl);
return;
} /* cipvs_submit_connections */
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, pi, sizeof (vl.plugin_instance));
- sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total", sizeof (vl.type_instance));
+ sstrncpy (vl.type, t, sizeof (vl.type));
+ sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total",
+ sizeof (vl.type_instance));
- plugin_dispatch_values (t, &vl);
+ plugin_dispatch_values (&vl);
return;
} /* cipvs_submit_if */
diff --git a/src/irq.c b/src/irq.c
index 93c6076ba0429396131650a90766f2f075938142..9b7e61877d8c62bafc009e91e1f792c43024e63e 100644 (file)
--- a/src/irq.c
+++ b/src/irq.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "irq", sizeof (vl.plugin));
+ sstrncpy (vl.type, "irq", sizeof (vl.type));
- status = snprintf (vl.type_instance, sizeof (vl.type_instance),
+ status = ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%u", irq);
if ((status < 1) || ((unsigned int)status >= sizeof (vl.type_instance)))
return;
- plugin_dispatch_values ("irq", &vl);
+ plugin_dispatch_values (&vl);
} /* void irq_submit */
static int irq_read (void)
index 4d9fc3de811bce2f7b79da20b566e65171d9baa0..b559e863179ebfebaf1acc4219baa24522897e5d 100644 (file)
--- a/src/liboconfig/scanner.l
+++ b/src/liboconfig/scanner.l
/**
* oconfig - src/scanner.l
* Copyright (C) 2007 Florian octo Forster <octo at verplant.org>
+ * Copyright (C) 2008 Sebastian tokkee Harl <sh at tokkee.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#include "oconfig.h"
#include "aux_types.h"
#include "parser.h"
+
+/* multiline string buffer */
+static char *ml_buffer = NULL;
+static int ml_pos = 0;
+static int ml_len = 0;
+
+#define ml_free (ml_len - ml_pos)
+
+static void ml_append (char *);
+
+#ifdef yyterminate
+# undef yyterminate
+#endif
+#define yyterminate() \
+ do { free (ml_buffer); ml_buffer = NULL; ml_pos = 0; ml_len = 0; \
+ return YY_NULL; } while (0)
%}
%option yylineno
%option noyywrap
+%x ML
WHITE_SPACE [\ \t\b]
-QUOTED_STRING \"([^\\"]+|\\.)*\"
+NON_WHITE_SPACE [^\ \t\b]
+EOL (\r\n|\n)
+QUOTED_STRING ([^\\"]+|\\.)*
UNQUOTED_STRING [0-9A-Za-z_]+
HEX_NUMBER 0[xX][0-9a-fA-F]+
OCT_NUMBER 0[0-7]+
{WHITE_SPACE} |
{COMMENT} {/* ignore */}
-\n {return (EOL);}
+\\{EOL} {/* continue line */}
+
+{EOL} {return (EOL);}
"/" {return (SLASH);}
"<" {return (OPENBRAC);}
">" {return (CLOSEBRAC);}
{NUMBER} {yylval.number = strtod (yytext, NULL); return (NUMBER);}
-{QUOTED_STRING} {yylval.string = yytext; return (QUOTED_STRING);}
+\"{QUOTED_STRING}\" {yylval.string = yytext; return (QUOTED_STRING);}
{UNQUOTED_STRING} {yylval.string = yytext; return (UNQUOTED_STRING);}
+
+\"{QUOTED_STRING}\\{EOL} {
+ int len = strlen (yytext);
+
+ ml_pos = 0;
+
+ /* remove "\\<EOL>" */
+ if ('\r' == yytext[len - 2])
+ len -= 3;
+ else
+ len -= 2;
+ yytext[len] = '\0';
+
+ ml_append (yytext);
+ BEGIN (ML);
+}
+<ML>^{WHITE_SPACE}+ {/* remove leading white-space */}
+<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\\{EOL} {
+ int len = strlen (yytext);
+
+ /* remove "\\<EOL>" */
+ if ('\r' == yytext[len - 2])
+ len -= 3;
+ else
+ len -= 2;
+ yytext[len] = '\0';
+
+ ml_append(yytext);
+}
+<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\" {
+ ml_append(yytext);
+ yylval.string = ml_buffer;
+
+ BEGIN (INITIAL);
+ return (QUOTED_STRING);
+}
%%
+static void ml_append (char *string)
+{
+ int len = strlen (string);
+ int s;
+
+ if (ml_free <= len) {
+ ml_len += len - ml_free + 1;
+ ml_buffer = (char *)realloc (ml_buffer, ml_len);
+ if (NULL == ml_buffer)
+ YY_FATAL_ERROR ("out of dynamic memory in ml_append");
+ }
+
+ s = snprintf (ml_buffer + ml_pos, ml_free, "%s", string);
+ if ((0 > s) || (ml_free <= s))
+ YY_FATAL_ERROR ("failed to write to multiline buffer");
+
+ ml_pos += s;
+ return;
+} /* ml_append */
+
diff --git a/src/libvirt.c b/src/libvirt.c
index 81d7f1cd3012cdeb478961918ce9397db7a6cd58..5acff29a578cd609dff2ba7de65bab1e13c4fc3b 100644 (file)
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -634,7 +634,7 @@ ignore_device_match (ignorelist_t *il, const char *domname, const char *devpath)
ERROR ("libvirt plugin: malloc failed.");
return 0;
}
- snprintf (name, n, "%s:%s", domname, devpath);
+ ssnprintf (name, n, "%s:%s", domname, devpath);
r = ignorelist_match (il, name);
free (name);
return r;
vl->time = t;
vl->interval = interval_g;
- strncpy (vl->plugin, "libvirt", sizeof (vl->plugin));
- vl->plugin[sizeof (vl->plugin) - 1] = '\0';
+ sstrncpy (vl->plugin, "libvirt", sizeof (vl->plugin));
vl->host[0] = '\0';
host_ptr = vl->host;
vl.values = values;
vl.values_len = 1;
- plugin_dispatch_values (type, &vl);
+ sstrncpy (vl.type, type, sizeof (vl.type));
+
+ plugin_dispatch_values (&vl);
}
static void
vl.values = values;
vl.values_len = 1;
- snprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr);
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr);
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
}
static void
vl.values = values;
vl.values_len = 2;
- strncpy (vl.type_instance, devname, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, devname, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void submit_counter2 */
static int
diff --git a/src/load.c b/src/load.c
index e0e0c0ed87942a04afdeb03fa0338bc08446e64e..72c7756a34b27d325b82fcc084e3afdb77f02dc8 100644 (file)
--- a/src/load.c
+++ b/src/load.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "load", sizeof (vl.plugin));
+ sstrncpy (vl.type, "load", sizeof (vl.type));
- plugin_dispatch_values ("load", &vl);
+ plugin_dispatch_values (&vl);
}
static int load_read (void)
diff --git a/src/logfile.c b/src/logfile.c
index 36ac58d711ee8a1764fd19ec72fefc9afffeafc5..382386b75552fa0915d9ade6ded18bc5b9954f3d 100644 (file)
--- a/src/logfile.c
+++ b/src/logfile.c
int buf_len = sizeof (buf);
int status;
- status = snprintf (buf_ptr, buf_len, "Notification: severity = %s",
+ status = ssnprintf (buf_ptr, buf_len, "Notification: severity = %s",
(n->severity == NOTIF_FAILURE) ? "FAILURE"
: ((n->severity == NOTIF_WARNING) ? "WARNING"
: ((n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN")));
#define APPEND(bufptr, buflen, key, value) \
if ((buflen > 0) && (strlen (value) > 0)) { \
- int status = snprintf (bufptr, buflen, ", %s = %s", key, value); \
+ int status = ssnprintf (bufptr, buflen, ", %s = %s", key, value); \
if (status > 0) { \
bufptr += status; \
buflen -= status; \
diff --git a/src/mbmon.c b/src/mbmon.c
index 22a26da5e613ef884d3b5c92331b574d85e1d5ff..344caddffd91f286b94b96721d065b4c2751f652 100644 (file)
--- a/src/mbmon.c
+++ b/src/mbmon.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "mbmon", sizeof (vl.plugin));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void mbmon_submit */
/* Trim trailing whitespace from a string. */
diff --git a/src/memcached.c b/src/memcached.c
index c3fa06b72b78401e38efb63b4f8c44440b9558f6..7bdad0a01a475f42d7d5c9c37b07c1abf62a0144 100644 (file)
--- a/src/memcached.c
+++ b/src/memcached.c
} else if (strcasecmp (key, "Port") == 0) {
int port = (int) (atof (value));
if ((port > 0) && (port <= 65535)) {
- snprintf (memcached_port, sizeof (memcached_port), "%i", port);
+ ssnprintf (memcached_port, sizeof (memcached_port), "%i", port);
} else {
- strncpy (memcached_port, value, sizeof (memcached_port));
+ sstrncpy (memcached_port, value, sizeof (memcached_port));
}
- memcached_port[sizeof (memcached_port) - 1] = '\0';
} else {
return -1;
}
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_inst != NULL)
- {
- strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- }
+ sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void memcached_submit_cmd */
/* }}} */
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_inst != NULL)
- {
- strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- }
+ sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void memcached_submit_cmd */
/* }}} */
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_inst != NULL)
- {
- strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- }
+ sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
}
/* }}} */
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_inst != NULL)
- {
- strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- }
+ sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
}
/* }}} */
diff --git a/src/memory.c b/src/memory.c
index a4a9af3a2128fdce1343d90e7b6e85a24eb8b7dd..c31b30efe29b109cf3ae7c73055a48502c5b21fb 100644 (file)
--- a/src/memory.c
+++ b/src/memory.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "memory", sizeof (vl.plugin));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+ sstrncpy (vl.type, "memory", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values ("memory", &vl);
+ plugin_dispatch_values (&vl);
}
static int memory_read (void)
diff --git a/src/multimeter.c b/src/multimeter.c
index c6b070a035691a2cbabd3c816231444448892ea5..994747f94f4167c352febc69c8ca4eb884c28650 100644 (file)
--- a/src/multimeter.c
+++ b/src/multimeter.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "multimeter", sizeof (vl.plugin));
+ sstrncpy (vl.type, "multimeter", sizeof (vl.type));
- plugin_dispatch_values ("multimeter", &vl);
+ plugin_dispatch_values (&vl);
}
static int multimeter_read (void)
diff --git a/src/mysql.c b/src/mysql.c
index aa585d6554eb88ddedffb8f38f5286b386deeba6..312a819e4980190a13bbabd957b30ca6efcea599 100644 (file)
--- a/src/mysql.c
+++ b/src/mysql.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void counter_submit */
static void qcache_submit (counter_t hits, counter_t inserts,
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
+ sstrncpy (vl.type, "mysql_qcache", sizeof (vl.type));
- plugin_dispatch_values ("mysql_qcache", &vl);
+ plugin_dispatch_values (&vl);
} /* void qcache_submit */
static void threads_submit (gauge_t running, gauge_t connected, gauge_t cached,
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
+ sstrncpy (vl.type, "mysql_threads", sizeof (vl.type));
- plugin_dispatch_values ("mysql_threads", &vl);
+ plugin_dispatch_values (&vl);
} /* void threads_submit */
static void traffic_submit (counter_t rx, counter_t tx)
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
+ sstrncpy (vl.type, "mysql_octets", sizeof (vl.type));
- plugin_dispatch_values ("mysql_octets", &vl);
+ plugin_dispatch_values (&vl);
} /* void traffic_submit */
static int mysql_read (void)
diff --git a/src/netlink.c b/src/netlink.c
index d6288e986903f0833e67dde81a439d3c7717b588..d14e5101dd885824b904b754845aa039dca05630 100644 (file)
--- a/src/netlink.c
+++ b/src/netlink.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+ sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_instance != NULL)
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void submit_one */
static void submit_two (const char *dev, const char *type,
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+ sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_instance != NULL)
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void submit_two */
static int link_filter (const struct sockaddr_nl *sa,
- const struct nlmsghdr *nmh, void *args)
+ struct nlmsghdr *nmh, void *args)
{
struct ifinfomsg *msg;
int msg_len;
} /* int link_filter */
static int qos_filter (const struct sockaddr_nl *sa,
- const struct nlmsghdr *nmh, void *args)
+ struct nlmsghdr *nmh, void *args)
{
struct tcmsg *msg;
int msg_len;
if (strcmp (tc_type, "filter") == 0)
numberic_id = msg->tcm_parent;
- snprintf (tc_inst, sizeof (tc_inst), "%s-%x:%x",
+ ssnprintf (tc_inst, sizeof (tc_inst), "%s-%x:%x",
(const char *) RTA_DATA (attrs[TCA_KIND]),
numberic_id >> 16,
numberic_id & 0x0000FFFF);
- tc_inst[sizeof (tc_inst) - 1] = '\0';
}
DEBUG ("netlink plugin: qos_filter: got %s for %s (%i).",
struct gnet_stats_basic bs;
char type_instance[DATA_MAX_NAME_LEN];
- snprintf (type_instance, sizeof (type_instance), "%s-%s",
+ ssnprintf (type_instance, sizeof (type_instance), "%s-%s",
tc_type, tc_inst);
- type_instance[sizeof (type_instance) - 1] = '\0';
memset (&bs, '\0', sizeof (bs));
memcpy (&bs, RTA_DATA (attrs_stats[TCA_STATS_BASIC]),
struct tc_stats ts;
char type_instance[DATA_MAX_NAME_LEN];
- snprintf (type_instance, sizeof (type_instance), "%s-%s",
+ ssnprintf (type_instance, sizeof (type_instance), "%s-%s",
tc_type, tc_inst);
- type_instance[sizeof (type_instance) - 1] = '\0';
memset(&ts, '\0', sizeof (ts));
memcpy(&ts, RTA_DATA (attrs[TCA_STATS]),
diff --git a/src/network.c b/src/network.c
index 0ea51b3bba7e6e7b381f3ca9c9724ddd2cba2232..fbbcd122d5bce1328229ca941b12a628d50feace 100644 (file)
--- a/src/network.c
+++ b/src/network.c
return (0);
} /* int cache_flush */
-static int cache_check (const char *type, const value_list_t *vl)
+static int cache_check (const value_list_t *vl)
{
char key[1024];
time_t *value = NULL;
return (-1);
if (format_name (key, sizeof (key), vl->host, vl->plugin,
- vl->plugin_instance, type, vl->type_instance))
+ vl->plugin_instance, vl->type, vl->type_instance))
return (-1);
pthread_mutex_lock (&cache_lock);
int status;
value_list_t vl = VALUE_LIST_INIT;
- char type[DATA_MAX_NAME_LEN];
notification_t n;
DEBUG ("network plugin: parse_packet: buffer = %p; buffer_len = %i;",
buffer, buffer_len);
memset (&vl, '\0', sizeof (vl));
- memset (&type, '\0', sizeof (type));
memset (&n, '\0', sizeof (n));
status = 0;
if ((vl.time > 0)
&& (strlen (vl.host) > 0)
&& (strlen (vl.plugin) > 0)
- && (strlen (type) > 0)
- && (cache_check (type, &vl) == 0))
+ && (strlen (vl.type) > 0)
+ && (cache_check (&vl) == 0))
{
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
}
else
{
else if (pkg_type == TYPE_TYPE)
{
status = parse_part_string (&buffer, &buffer_len,
- type, sizeof (type));
+ vl.type, sizeof (vl.type));
if (status == 0)
- sstrncpy (n.type, type, sizeof (n.type));
+ sstrncpy (n.type, vl.type, sizeof (n.type));
}
else if (pkg_type == TYPE_TYPE_INSTANCE)
{
sstrncpy (vl_def->plugin_instance, vl->plugin_instance, sizeof (vl_def->plugin_instance));
}
- if (strcmp (type_def, ds->type) != 0)
+ if (strcmp (type_def, vl->type) != 0)
{
if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
- ds->type, strlen (ds->type)) != 0)
+ vl->type, strlen (vl->type)) != 0)
return (-1);
- sstrncpy (type_def, ds->type, sizeof (type_def));
+ sstrncpy (type_def, vl->type, sizeof (type_def));
}
if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
/* If the value is already in the cache, we have received it via the
* network. We write it again if forwarding is activated. It's then in
* the cache and should we receive it again we will ignore it. */
- status = cache_check (ds->type, vl);
+ status = cache_check (vl);
if ((network_config_forward == 0)
&& (status != 0))
return (0);
return (0);
} /* int network_init */
-static int network_flush (int timeout)
+/*
+ * The flush option of the network plugin cannot flush individual identifiers.
+ * All the values are added to a buffer and sent when the buffer is full, the
+ * requested value may or may not be in there, it's not worth finding out. We
+ * just send the buffer if `flush' is called - if the requested value was in
+ * there, good. If not, well, then there is nothing to flush.. -octo
+ */
+static int network_flush (int timeout, const char *identifier)
{
pthread_mutex_lock (&send_buffer_lock);
diff --git a/src/nfs.c b/src/nfs.c
index 91e6788631acba20630a3da4434444cde9e5f4f1..f2db895a00d484bf647e1c2a9a7688dd106ca31e 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "nfs", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, plugin_instance,
+ sstrncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type));
for (i = 0; i < len; i++)
{
values[0].counter = val[i];
- strncpy (vl.type_instance, names[i],
+ sstrncpy (vl.type_instance, names[i],
sizeof (vl.type_instance));
DEBUG ("%s-%s/nfs_procedure-%s = %llu",
vl.plugin, vl.plugin_instance,
vl.type_instance, val[i]);
- plugin_dispatch_values ("nfs_procedure", &vl);
+ plugin_dispatch_values (&vl);
}
} /* void nfs_procedures_submit */
continue;
}
- snprintf (plugin_instance, sizeof (plugin_instance),
+ ssnprintf (plugin_instance, sizeof (plugin_instance),
"v2%s", inst);
- plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
values = (unsigned long long *) malloc (nfs2_procedures_names_num * sizeof (unsigned long long));
if (values == NULL)
continue;
}
- snprintf (plugin_instance, sizeof (plugin_instance),
+ ssnprintf (plugin_instance, sizeof (plugin_instance),
"v3%s", inst);
- plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
values = (unsigned long long *) malloc (nfs3_procedures_names_num * sizeof (unsigned long long));
if (values == NULL)
diff --git a/src/nginx.c b/src/nginx.c
index 283e8f6f3fa85ae2568aab63c45a170ed8ba35ca..91bcf75404927bfcd708e16faf71b5b7606fe304 100644 (file)
--- a/src/nginx.c
+++ b/src/nginx.c
if (user != NULL)
{
- if (snprintf (credentials, 1024, "%s:%s", user, pass == NULL ? "" : pass) >= 1024)
+ if (ssnprintf (credentials, sizeof (credentials),
+ "%s:%s", user, pass == NULL ? "" : pass) >= sizeof (credentials))
{
ERROR ("nginx plugin: Credentials would have been truncated.");
return (-1);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "nginx", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (inst != NULL)
- {
- strncpy (vl.type_instance, inst, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- }
+ sstrncpy (vl.type_instance, inst, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void submit */
static int nginx_read (void)
diff --git a/src/notify_desktop.c b/src/notify_desktop.c
--- /dev/null
+++ b/src/notify_desktop.c
@@ -0,0 +1,161 @@
+/**
+ * collectd - src/notify_desktop.c
+ * Copyright (C) 2008 Sebastian Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Sebastian Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This plugin sends desktop notifications to a notification daemon.
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <glib.h>
+#include <libnotify/notify.h>
+
+#define log_info(...) INFO ("notify_desktop: " __VA_ARGS__)
+#define log_warn(...) WARNING ("notify_desktop: " __VA_ARGS__)
+#define log_err(...) ERROR ("notify_desktop: " __VA_ARGS__)
+
+#define DEFAULT_TIMEOUT 5000
+
+static int okay_timeout = DEFAULT_TIMEOUT;
+static int warn_timeout = DEFAULT_TIMEOUT;
+static int fail_timeout = DEFAULT_TIMEOUT;
+
+static int set_timeout (oconfig_item_t *ci, int *timeout)
+{
+ if ((0 != ci->children_num) || (1 != ci->values_num)
+ || (OCONFIG_TYPE_NUMBER != ci->values[0].type)) {
+ log_err ("%s expects a single number argument.", ci->key);
+ return 1;
+ }
+
+ *timeout = (int)ci->values[0].value.number;
+ if (0 > *timeout)
+ *timeout = DEFAULT_TIMEOUT;
+ return 0;
+} /* set_timeout */
+
+static int c_notify_config (oconfig_item_t *ci)
+{
+ int i = 0;
+
+ for (i = 0; i < ci->children_num; ++i) {
+ oconfig_item_t *c = ci->children + i;
+
+ if (0 == strcasecmp (c->key, "OkayTimeout"))
+ set_timeout (c, &okay_timeout);
+ else if (0 == strcasecmp (c->key, "WarningTimeout"))
+ set_timeout (c, &warn_timeout);
+ else if (0 == strcasecmp (c->key, "FailureTimeout"))
+ set_timeout (c, &fail_timeout);
+ }
+ return 0;
+} /* c_notify_config */
+
+static int c_notify (const notification_t *n)
+{
+ NotifyNotification *notification = NULL;
+ NotifyUrgency urgency = NOTIFY_URGENCY_LOW;
+ int timeout = okay_timeout;
+
+ char summary[1024];
+
+ if (NOTIF_WARNING == n->severity) {
+ urgency = NOTIFY_URGENCY_NORMAL;
+ timeout = warn_timeout;
+ }
+ else if (NOTIF_FAILURE == n->severity) {
+ urgency = NOTIFY_URGENCY_CRITICAL;
+ timeout = fail_timeout;
+ }
+
+ ssnprintf (summary, sizeof (summary), "collectd %s notification",
+ (NOTIF_FAILURE == n->severity) ? "FAILURE"
+ : (NOTIF_WARNING == n->severity) ? "WARNING"
+ : (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
+
+ notification = notify_notification_new (summary, n->message, NULL, NULL);
+ if (NULL == notification) {
+ log_err ("Failed to create a new notification.");
+ return -1;
+ }
+
+ notify_notification_set_urgency (notification, urgency);
+ notify_notification_set_timeout (notification, timeout);
+
+ if (! notify_notification_show (notification, NULL))
+ log_err ("Failed to display notification.");
+
+ g_object_unref (G_OBJECT (notification));
+ return 0;
+} /* c_notify */
+
+static int c_notify_shutdown (void)
+{
+ plugin_unregister_init ("notify_desktop");
+ plugin_unregister_notification ("notify_desktop");
+ plugin_unregister_shutdown ("notify_desktop");
+
+ if (notify_is_initted ())
+ notify_uninit ();
+ return 0;
+} /* c_notify_shutdown */
+
+static int c_notify_init (void)
+{
+ char *name = NULL;
+ char *vendor = NULL;
+ char *version = NULL;
+ char *spec_version = NULL;
+
+ if (! notify_init (PACKAGE_STRING)) {
+ log_err ("Failed to initialize libnotify.");
+ return -1;
+ }
+
+ if (! notify_get_server_info (&name, &vendor, &version, &spec_version))
+ log_warn ("Failed to get the notification server info. "
+ "Check if you have a notification daemon running.");
+ else {
+ log_info ("Found notification daemon: %s (%s) %s (spec version %s)",
+ name, vendor, version, spec_version);
+ free (name);
+ free (vendor);
+ free (version);
+ free (spec_version);
+ }
+
+ plugin_register_notification ("notify_desktop", c_notify);
+ plugin_register_shutdown ("notify_desktop", c_notify_shutdown);
+ return 0;
+} /* c_notify_init */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("notify_desktop", c_notify_config);
+ plugin_register_init ("notify_desktop", c_notify_init);
+ return;
+} /* module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/notify_email.c b/src/notify_email.c
--- /dev/null
+++ b/src/notify_email.c
@@ -0,0 +1,287 @@
+/**
+ * collectd - src/notify_email.c
+ * Copyright (C) 2008 Oleg King
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Oleg King <king2 at kaluga.ru>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <auth-client.h>
+#include <libesmtp.h>
+
+#define MAXSTRING 256
+
+static const char *config_keys[] =
+{
+ "SMTPServer",
+ "SMTPPort",
+ "SMTPUser",
+ "SMTPPassword",
+ "From",
+ "Recipient",
+ "Subject"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char **recipients;
+static int recipients_len = 0;
+
+static smtp_session_t session;
+static smtp_message_t message;
+static auth_context_t authctx = NULL;
+
+static int smtp_port = 25;
+static char *smtp_host = NULL;
+static char *smtp_user = NULL;
+static char *smtp_password = NULL;
+static char *email_from = NULL;
+static char *email_subject = NULL;
+
+#define DEFAULT_SMTP_HOST "localhost"
+#define DEFAULT_SMTP_FROM "root@localhost"
+#define DEFAULT_SMTP_SUBJECT "Collectd notify: %s@%s"
+
+/* Callback to get username and password */
+static int authinteract (auth_client_request_t request, char **result,
+ int fields, void *arg)
+{
+ int i;
+ for (i = 0; i < fields; i++)
+ {
+ if (request[i].flags & AUTH_USER)
+ result[i] = smtp_user;
+ else if (request[i].flags & AUTH_PASS)
+ result[i] = smtp_password;
+ else
+ return 0;
+ }
+ return 1;
+} /* int authinteract */
+
+/* Callback to print the recipient status */
+static void print_recipient_status (smtp_recipient_t recipient,
+ const char *mailbox, void *arg)
+{
+ const smtp_status_t *status;
+
+ status = smtp_recipient_status (recipient);
+ if (status->text[strlen(status->text) - 2] == '\r')
+ status->text[strlen(status->text) - 2] = 0;
+ INFO ("notify_email: notify sent to %s: %d %s", mailbox, status->code,
+ status->text);
+} /* void print_recipient_status */
+
+/* Callback to monitor SMTP activity */
+static void monitor_cb (const char *buf, int buflen, int writing, void *arg)
+{
+ char log_str[MAXSTRING];
+
+ sstrncpy (log_str, buf, sizeof (log_str));
+ if (buflen > 2)
+ log_str[buflen - 2] = 0; /* replace \n with \0 */
+
+ if (writing == SMTP_CB_HEADERS) {
+ DEBUG ("notify_email plugin: SMTP --- H: %s", log_str);
+ return;
+ }
+ DEBUG (writing
+ ? "notify_email plugin: SMTP >>> C: %s"
+ : "notify_email plugin: SMTP <<< S: %s",
+ log_str);
+} /* void monitor_cb */
+
+static int notify_email_init (void)
+{
+ char server[MAXSTRING];
+
+ auth_client_init();
+ if (!(session = smtp_create_session ())) {
+ ERROR ("notify_email plugin: cannot create SMTP session");
+ return (-1);
+ }
+
+ smtp_set_monitorcb (session, monitor_cb, NULL, 1);
+ smtp_set_hostname (session, hostname_g);
+ ssnprintf(server, sizeof (server), "%s:%i",
+ (smtp_host == NULL) ? DEFAULT_SMTP_HOST : smtp_host,
+ smtp_port);
+ smtp_set_server (session, server);
+
+ if (smtp_user && smtp_password) {
+ authctx = auth_create_context ();
+ auth_set_mechanism_flags (authctx, AUTH_PLUGIN_PLAIN, 0);
+ auth_set_interact_cb (authctx, authinteract, NULL);
+ }
+
+ if ( !smtp_auth_set_context (session, authctx)) {
+ ERROR ("notify_email plugin: cannot set SMTP auth context");
+ return (-1);
+ }
+
+ return (0);
+} /* int notify_email_init */
+
+static int notify_email_shutdown (void)
+{
+ smtp_destroy_session (session);
+ auth_destroy_context (authctx);
+ auth_client_exit();
+ return (0);
+} /* int notify_email_shutdown */
+
+static int notify_email_config (const char *key, const char *value)
+{
+ if (strcasecmp (key, "Recipient") == 0)
+ {
+ char **tmp;
+
+ tmp = (char **) realloc ((void *) recipients, (recipients_len + 1) * sizeof (char *));
+ if (tmp == NULL) {
+ ERROR ("notify_email: realloc failed.");
+ return (-1);
+ }
+
+ recipients = tmp;
+ recipients[recipients_len] = strdup (value);
+ if (recipients[recipients_len] == NULL) {
+ ERROR ("notify_email: strdup failed.");
+ return (-1);
+ }
+ recipients_len++;
+ }
+ else if (0 == strcasecmp (key, "SMTPServer")) {
+ sfree (smtp_host);
+ smtp_host = strdup (value);
+ }
+ else if (0 == strcasecmp (key, "SMTPPort")) {
+ int port_tmp = atoi (value);
+ if (port_tmp < 1 || port_tmp > 65535)
+ {
+ WARNING ("notify_email plugin: Invalid SMTP port: %i", port_tmp);
+ return (1);
+ }
+ smtp_port = port_tmp;
+ }
+ else if (0 == strcasecmp (key, "SMTPUser")) {
+ sfree (smtp_user);
+ smtp_user = strdup (value);
+ }
+ else if (0 == strcasecmp (key, "SMTPPassword")) {
+ sfree (smtp_password);
+ smtp_password = strdup (value);
+ }
+ else if (0 == strcasecmp (key, "From")) {
+ sfree (email_from);
+ email_from = strdup (value);
+ }
+ else if (0 == strcasecmp (key, "Subject")) {
+ sfree (email_subject);
+ email_subject = strdup (value);
+ }
+ else {
+ return -1;
+ }
+ return 0;
+} /* int notify_email_config (const char *, const char *) */
+
+static int notify_email_notification (const notification_t *n)
+{
+ smtp_recipient_t recipient;
+
+ struct tm timestamp_tm;
+ char timestamp_str[64];
+
+ char severity[32];
+ char subject[MAXSTRING];
+
+ char buf[4096] = "";
+ int buf_len = sizeof (buf);
+ int i;
+
+ ssnprintf (severity, sizeof (severity), "%s",
+ (n->severity == NOTIF_FAILURE) ? "FAILURE"
+ : ((n->severity == NOTIF_WARNING) ? "WARNING"
+ : ((n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN")));
+
+ ssnprintf (subject, sizeof (subject),
+ (email_subject == NULL) ? DEFAULT_SMTP_SUBJECT : email_subject,
+ severity, n->host);
+
+ localtime_r (&n->time, ×tamp_tm);
+ strftime (timestamp_str, sizeof (timestamp_str), "%Y-%m-%d %H:%M:%S",
+ ×tamp_tm);
+ timestamp_str[sizeof (timestamp_str) - 1] = '\0';
+
+ /* Let's make RFC822 message text with \r\n EOLs */
+ ssnprintf (buf, buf_len,
+ "MIME-Version: 1.0\r\n"
+ "Content-Type: text/plain;\r\n"
+ "Content-Transfer-Encoding: 8bit\r\n"
+ "Subject: %s\r\n"
+ "\r\n"
+ "%s - %s@%s\r\n"
+ "\r\n"
+ "Message: %s",
+ subject,
+ timestamp_str,
+ severity,
+ n->host,
+ n->message);
+
+ if (!(message = smtp_add_message (session))) {
+ ERROR ("notify_email plugin: cannot set SMTP message");
+ return (-1);
+ }
+ smtp_set_reverse_path (message, email_from);
+ smtp_set_header (message, "To", NULL, NULL);
+ smtp_set_message_str (message, buf);
+
+ for (i = 0; i < recipients_len; i++)
+ recipient = smtp_add_recipient (message, recipients[i]);
+
+ /* Initiate a connection to the SMTP server and transfer the message. */
+ if (!smtp_start_session (session)) {
+ char buf[MAXSTRING];
+ ERROR ("notify_email plugin: SMTP server problem: %s",
+ smtp_strerror (smtp_errno (), buf, sizeof buf));
+ return (-1);
+ } else {
+ const smtp_status_t *status;
+ /* Report on the success or otherwise of the mail transfer. */
+ status = smtp_message_transfer_status (message);
+ DEBUG ("notify_email plugin: SMTP server report: %d %s",
+ status->code, (status->text != NULL) ? status->text : "\n");
+ smtp_enumerate_recipients (message, print_recipient_status, NULL);
+ }
+
+ return (0);
+} /* int notify_email_notification */
+
+void module_register (void)
+{
+ plugin_register_init ("notify_email", notify_email_init);
+ plugin_register_shutdown ("notify_email", notify_email_shutdown);
+ plugin_register_config ("notify_email", notify_email_config,
+ config_keys, config_keys_num);
+ plugin_register_notification ("notify_email", notify_email_notification);
+} /* void module_register (void) */
+
+/* vim: set sw=2 sts=2 ts=8 et : */
diff --git a/src/ntpd.c b/src/ntpd.c
index a7ef0fa3fd13fd0efbbce605688efa72eb93b7d8..44964bb5a8dbd936d23ef2e828e4d05b2561c543 100644 (file)
--- a/src/ntpd.c
+++ b/src/ntpd.c
{
int port = (int) (atof (value));
if ((port > 0) && (port <= 65535))
- snprintf (ntpd_port, sizeof (ntpd_port),
+ ssnprintf (ntpd_port, sizeof (ntpd_port),
"%i", port);
else
- strncpy (ntpd_port, value, sizeof (ntpd_port));
- ntpd_port[sizeof (ntpd_port) - 1] = '\0';
+ sstrncpy (ntpd_port, value, sizeof (ntpd_port));
}
else if (strcasecmp (key, "ReverseLookups") == 0)
{
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "ntpd", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
- strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
}
/* returns `tv0 - tv1' in milliseconds or 0 if `tv1 > tv0' */
if (refclock_id < refclock_names_num)
{
- strncpy (peername, refclock_names[refclock_id],
+ sstrncpy (peername, refclock_names[refclock_id],
sizeof (peername));
}
else
addr_obj.s_addr = ptr->srcadr;
addr_str = inet_ntoa (addr_obj);
- strncpy (peername, addr_str, sizeof (peername));
+ sstrncpy (peername, addr_str, sizeof (peername));
}
}
else /* Normal network host. */
diff --git a/src/nut.c b/src/nut.c
index 695d93b5aa574a7f1c3469f8272e14983d29789c..8796d5873377cb6fbb61c51a65f011616f235c76 100644 (file)
--- a/src/nut.c
+++ b/src/nut.c
vl.values = values;
vl.values_len = STATIC_ARRAY_SIZE (values);
vl.time = time (NULL);
- strncpy (vl.host,
+ sstrncpy (vl.host,
(strcasecmp (ups->hostname, "localhost") == 0)
? hostname_g
: ups->hostname,
sizeof (vl.host));
sstrncpy (vl.plugin, "nut", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, ups->upsname, sizeof (vl.plugin_instance));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.plugin_instance, ups->upsname, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- vl.host[sizeof (vl.host) - 1] = '\0';
- vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
-
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void nut_submit */
static int nut_read_one (nut_ups_t *ups)
diff --git a/src/onewire.c b/src/onewire.c
--- /dev/null
+++ b/src/onewire.c
@@ -0,0 +1,312 @@
+/**
+ * collectd - src/owfs.c
+ * Copyright (C) 2008 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at noris.net>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#include <owcapi.h>
+
+#define OW_FAMILY_LENGTH 8
+#define OW_FAMILY_MAX_FEATURES 2
+struct ow_family_features_s
+{
+ char family[OW_FAMILY_LENGTH];
+ struct
+ {
+ char filename[DATA_MAX_NAME_LEN];
+ char type[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN];
+ } features[OW_FAMILY_MAX_FEATURES];
+ size_t features_num;
+};
+typedef struct ow_family_features_s ow_family_features_t;
+
+/* see http://owfs.sourceforge.net/ow_table.html for a list of families */
+static ow_family_features_t ow_family_features[] =
+{
+ {
+ /* family = */ "10.",
+ {
+ {
+ /* filename = */ "temperature",
+ /* type = */ "temperature",
+ /* type_instance = */ ""
+ }
+ },
+ /* features_num = */ 1
+ }
+};
+static int ow_family_features_num = STATIC_ARRAY_SIZE (ow_family_features);
+
+static char *device_g = NULL;
+
+static const char *config_keys[] =
+{
+ "Device",
+ "IgnoreSelected",
+ "Sensor",
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *sensor_list;
+
+static int cow_load_config (const char *key, const char *value)
+{
+ if (sensor_list == NULL)
+ sensor_list = ignorelist_create (1);
+
+ if (strcasecmp (key, "Sensor") == 0)
+ {
+ if (ignorelist_add (sensor_list, value))
+ {
+ ERROR ("sensors plugin: "
+ "Cannot add value to ignorelist.");
+ return (1);
+ }
+ }
+ else if (strcasecmp (key, "IgnoreSelected") == 0)
+ {
+ ignorelist_set_invert (sensor_list, 1);
+ if ((strcasecmp (value, "True") == 0)
+ || (strcasecmp (value, "Yes") == 0)
+ || (strcasecmp (value, "On") == 0))
+ ignorelist_set_invert (sensor_list, 0);
+ }
+ else if (strcasecmp (key, "Device") == 0)
+ {
+ char *temp;
+ temp = strdup (value);
+ if (temp == NULL)
+ {
+ ERROR ("onewire plugin: strdup failed.");
+ return (1);
+ }
+ sfree (device_g);
+ device_g = temp;
+ }
+ else
+ {
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int cow_init (void)
+{
+ int status;
+
+ if (device_g == NULL)
+ {
+ ERROR ("onewire plugin: cow_init: No device configured.");
+ return (-1);
+ }
+
+ status = (int) OW_init (device_g);
+ if (status != 0)
+ {
+ ERROR ("onewire plugin: OW_init(%s) failed: %i.", device_g, status);
+ return (1);
+ }
+
+ return (0);
+} /* int cow_init */
+
+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;
+ size_t i;
+
+ if (sensor_list != NULL)
+ {
+ DEBUG ("onewire plugin: Checking ignorelist for `%s'", name);
+ if (ignorelist_match (sensor_list, name) != 0)
+ return 0;
+ }
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "onewire", sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, name, sizeof (vl.plugin_instance));
+
+ for (i = 0; i < family_info->features_num; i++)
+ {
+ char *buffer;
+ size_t buffer_size;
+ int status;
+
+ char file[4096];
+ char *endptr;
+
+ snprintf (file, sizeof (file), "%s/%s",
+ path, family_info->features[i].filename);
+ file[sizeof (file) - 1] = 0;
+
+ buffer = NULL;
+ buffer_size = 0;
+ 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);
+ return (-1);
+ }
+
+ endptr = NULL;
+ values[0].gauge = strtod (buffer, &endptr);
+ if (endptr == NULL)
+ {
+ ERROR ("onewire plugin: Buffer is not a number: %s", buffer);
+ status = -1;
+ continue;
+ }
+
+ sstrncpy (vl.type, family_info->features[i].type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, family_info->features[i].type_instance,
+ sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+ success++;
+
+ free (buffer);
+ } /* for (i = 0; i < features_num; i++) */
+
+ return ((success > 0) ? 0 : -1);
+} /* int cow_read_values */
+
+/* Forward declaration so the recursion below works */
+static int cow_read_bus (const char *path);
+
+/*
+ * cow_read_ds2409
+ *
+ * Handles:
+ * - DS2409 - MicroLAN Coupler
+ */
+static int cow_read_ds2409 (const char *path)
+{
+ char subpath[4096];
+ int status;
+
+ status = ssnprintf (subpath, sizeof (subpath), "%s/main", path);
+ if ((status > 0) && (status < sizeof (subpath)))
+ cow_read_bus (subpath);
+
+ status = ssnprintf (subpath, sizeof (subpath), "%s/aux", path);
+ if ((status > 0) && (status < sizeof (subpath)))
+ cow_read_bus (subpath);
+
+ return (0);
+} /* int cow_read_ds2409 */
+
+static int cow_read_bus (const char *path)
+{
+ char *buffer;
+ size_t buffer_size;
+ int status;
+
+ char *buffer_ptr;
+ char *dummy;
+ char *saveptr;
+ char subpath[4096];
+
+ status = OW_get (path, &buffer, &buffer_size);
+ if (status < 0)
+ {
+ ERROR ("onewire plugin: OW_get (%s) failed. status = %#x;",
+ path, status);
+ return (-1);
+ }
+ DEBUG ("onewire plugin: OW_get (%s) returned: %s",
+ path, buffer);
+
+ dummy = buffer;
+ saveptr = NULL;
+ while ((buffer_ptr = strtok_r (dummy, ",/", &saveptr)) != NULL)
+ {
+ int i;
+
+ dummy = NULL;
+
+ if (strcmp ("/", path) == 0)
+ status = ssnprintf (subpath, sizeof (subpath), "/%s", buffer_ptr);
+ else
+ status = ssnprintf (subpath, sizeof (subpath), "%s/%s",
+ path, buffer_ptr);
+ if ((status <= 0) || (status >= sizeof (subpath)))
+ continue;
+
+ for (i = 0; i < ow_family_features_num; i++)
+ {
+ if (strncmp (ow_family_features[i].family, buffer_ptr,
+ strlen (ow_family_features[i].family)) != 0)
+ continue;
+
+ cow_read_values (subpath,
+ buffer_ptr + strlen (ow_family_features[i].family),
+ ow_family_features + i);
+ break;
+ }
+ if (i < ow_family_features_num)
+ continue;
+
+ /* DS2409 */
+ if (strncmp ("1F.", buffer_ptr, strlen ("1F.")) == 0)
+ {
+ cow_read_ds2409 (subpath);
+ continue;
+ }
+ } /* while (strtok_r) */
+
+ free (buffer);
+ return (0);
+} /* int cow_read_bus */
+
+static int cow_read (void)
+{
+ return (cow_read_bus ("/"));
+} /* int cow_read */
+
+static int cow_shutdown (void)
+{
+ OW_finish ();
+ ignorelist_free (sensor_list);
+ return (0);
+} /* int cow_shutdown */
+
+void module_register (void)
+{
+ plugin_register_init ("onewire", cow_init);
+ plugin_register_read ("onewire", cow_read);
+ plugin_register_shutdown ("onewire", cow_shutdown);
+ plugin_register_config ("onewire", cow_load_config,
+ config_keys, config_keys_num);
+}
+
+/* vim: set sw=2 sts=2 ts=8 et fdm=marker cindent : */
diff --git a/src/perl.c b/src/perl.c
index 2a8180d2231d71e64fedbe55f5c197b87327195d..bb62267e89608166c70392ce52518fbd0ce74a51 100644 (file)
--- a/src/perl.c
+++ b/src/perl.c
#define PLUGIN_TYPES 7
+#define PLUGIN_CONFIG 254
#define PLUGIN_DATASET 255
#define log_debug(...) DEBUG ("perl: " __VA_ARGS__)
static XS (Collectd_plugin_register_ds);
static XS (Collectd_plugin_unregister_ds);
static XS (Collectd_plugin_dispatch_values);
-static XS (Collectd_plugin_flush_one);
-static XS (Collectd_plugin_flush_all);
+static XS (Collectd__plugin_flush);
static XS (Collectd_plugin_dispatch_notification);
static XS (Collectd_plugin_log);
static XS (Collectd_call_by_name);
{ "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 },
- { "Collectd::plugin_flush_one", Collectd_plugin_flush_one },
- { "Collectd::plugin_flush_all", Collectd_plugin_flush_all },
+ { "Collectd::_plugin_flush", Collectd__plugin_flush },
{ "Collectd::plugin_dispatch_notification",
Collectd_plugin_dispatch_notification },
{ "Collectd::plugin_log", Collectd_plugin_log },
{ "Collectd::TYPE_LOG", PLUGIN_LOG },
{ "Collectd::TYPE_NOTIF", PLUGIN_NOTIF },
{ "Collectd::TYPE_FLUSH", PLUGIN_FLUSH },
+ { "Collectd::TYPE_CONFIG", PLUGIN_CONFIG },
{ "Collectd::TYPE_DATASET", PLUGIN_DATASET },
{ "Collectd::DS_TYPE_COUNTER", DS_TYPE_COUNTER },
{ "Collectd::DS_TYPE_GAUGE", DS_TYPE_GAUGE },
return -1;
if (NULL != (tmp = hv_fetch (hash, "name", 4, 0))) {
- strncpy (ds->name, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
- ds->name[DATA_MAX_NAME_LEN - 1] = '\0';
+ sstrncpy (ds->name, SvPV_nolen (*tmp), sizeof (ds->name));
}
else {
log_err ("hv2data_source: No DS name given.");
newSVpv (vl->plugin_instance, 0), 0))
return -1;
+ if ('\0' != vl->type[0])
+ if (NULL == hv_store (hash, "type", 4, newSVpv (vl->type, 0), 0))
+ return -1;
+
if ('\0' != vl->type_instance[0])
if (NULL == hv_store (hash, "type_instance", 13,
newSVpv (vl->type_instance, 0), 0))
return 0;
} /* static int notification2hv (notification_t *, HV *) */
+static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash)
+{
+ int i;
+
+ AV *values;
+ AV *children;
+
+ if (NULL == hv_store (hash, "key", 3, newSVpv (ci->key, 0), 0))
+ return -1;
+
+ values = newAV ();
+ if (0 < ci->values_num)
+ av_extend (values, ci->values_num);
+
+ if (NULL == hv_store (hash, "values", 6, newRV_noinc ((SV *)values), 0)) {
+ av_clear (values);
+ av_undef (values);
+ return -1;
+ }
+
+ for (i = 0; i < ci->values_num; ++i) {
+ SV *value;
+
+ switch (ci->values[i].type) {
+ case OCONFIG_TYPE_STRING:
+ value = newSVpv (ci->values[i].value.string, 0);
+ break;
+ case OCONFIG_TYPE_NUMBER:
+ value = newSVnv ((NV)ci->values[i].value.number);
+ break;
+ case OCONFIG_TYPE_BOOLEAN:
+ value = ci->values[i].value.boolean ? &PL_sv_yes : &PL_sv_no;
+ break;
+ default:
+ log_err ("oconfig_item2hv: Invalid value type %i.",
+ ci->values[i].type);
+ value = &PL_sv_undef;
+ }
+
+ if (NULL == av_store (values, i, value)) {
+ sv_free (value);
+ return -1;
+ }
+ }
+
+ /* ignoring 'parent' member which is uninteresting in this case */
+
+ children = newAV ();
+ if (0 < ci->children_num)
+ av_extend (children, ci->children_num);
+
+ if (NULL == hv_store (hash, "children", 8, newRV_noinc ((SV *)children), 0)) {
+ av_clear (children);
+ av_undef (children);
+ return -1;
+ }
+
+ for (i = 0; i < ci->children_num; ++i) {
+ HV *child = newHV ();
+
+ if (0 != oconfig_item2hv (aTHX_ ci->children + i, child)) {
+ hv_clear (child);
+ hv_undef (child);
+ return -1;
+ }
+
+ if (NULL == av_store (children, i, newRV_noinc ((SV *)child))) {
+ hv_clear (child);
+ hv_undef (child);
+ return -1;
+ }
+ }
+ return 0;
+} /* static int oconfig_item2hv (pTHX_ oconfig_item_t *, HV *) */
+
/*
* Internal functions.
*/
static char *get_module_name (char *buf, size_t buf_len, const char *module) {
int status = 0;
if (base_name[0] == '\0')
- status = snprintf (buf, buf_len, "%s", module);
+ status = ssnprintf (buf, buf_len, "%s", module);
else
- status = snprintf (buf, buf_len, "%s::%s", base_name, module);
+ status = ssnprintf (buf, buf_len, "%s::%s", base_name, module);
if ((status < 0) || ((unsigned int)status >= buf_len))
return (NULL);
- buf[buf_len - 1] = '\0';
return (buf);
} /* char *get_module_name */
ds[i].name, ds[i].type, ds[i].min, ds[i].max);
}
- strncpy (set->type, name, DATA_MAX_NAME_LEN);
- set->type[DATA_MAX_NAME_LEN - 1] = '\0';
+ sstrncpy (set->type, name, sizeof (set->type));
set->ds_num = len + 1;
set->ds = ds;
* type_instance => $tinstance,
* }
*/
-static int pplugin_dispatch_values (pTHX_ char *name, HV *values)
+static int pplugin_dispatch_values (pTHX_ HV *values)
{
value_list_t list = VALUE_LIST_INIT;
value_t *val = NULL;
int ret = 0;
- if ((NULL == name) || (NULL == values))
+ if (NULL == values)
return -1;
+ if (NULL == (tmp = hv_fetch (values, "type", 4, 0))) {
+ log_err ("pplugin_dispatch_values: No type given.");
+ return -1;
+ }
+
+ sstrncpy (list.type, SvPV_nolen (*tmp), sizeof (list.type));
+
if ((NULL == (tmp = hv_fetch (values, "values", 6, 0)))
|| (! (SvROK (*tmp) && (SVt_PVAV == SvTYPE (SvRV (*tmp)))))) {
log_err ("pplugin_dispatch_values: No valid values given.");
val = (value_t *)smalloc (len * sizeof (value_t));
- list.values_len = av2value (aTHX_ name, (AV *)SvRV (*tmp), val, len);
+ list.values_len = av2value (aTHX_ list.type, (AV *)SvRV (*tmp),
+ val, len);
list.values = val;
if (-1 == list.values_len) {
}
if (NULL != (tmp = hv_fetch (values, "host", 4, 0))) {
- strncpy (list.host, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
- list.host[DATA_MAX_NAME_LEN - 1] = '\0';
+ sstrncpy (list.host, SvPV_nolen (*tmp), sizeof (list.host));
}
else {
sstrncpy (list.host, hostname_g, sizeof (list.host));
}
- if (NULL != (tmp = hv_fetch (values, "plugin", 6, 0))) {
- strncpy (list.plugin, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
- list.plugin[DATA_MAX_NAME_LEN - 1] = '\0';
- }
+ if (NULL != (tmp = hv_fetch (values, "plugin", 6, 0)))
+ sstrncpy (list.plugin, SvPV_nolen (*tmp), sizeof (list.plugin));
- if (NULL != (tmp = hv_fetch (values, "plugin_instance", 15, 0))) {
- strncpy (list.plugin_instance, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
- list.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
- }
+ if (NULL != (tmp = hv_fetch (values, "plugin_instance", 15, 0)))
+ sstrncpy (list.plugin_instance, SvPV_nolen (*tmp),
+ sizeof (list.plugin_instance));
- if (NULL != (tmp = hv_fetch (values, "type_instance", 13, 0))) {
- strncpy (list.type_instance, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
- list.type_instance[DATA_MAX_NAME_LEN - 1] = '\0';
- }
+ if (NULL != (tmp = hv_fetch (values, "type_instance", 13, 0)))
+ sstrncpy (list.type_instance, SvPV_nolen (*tmp),
+ sizeof (list.type_instance));
- ret = plugin_dispatch_values (name, &list);
+ ret = plugin_dispatch_values (&list);
sfree (val);
return ret;
n.time = time (NULL);
if (NULL != (tmp = hv_fetch (notif, "message", 7, 0)))
- strncpy (n.message, SvPV_nolen (*tmp), sizeof (n.message));
- n.message[sizeof (n.message) - 1] = '\0';
+ sstrncpy (n.message, SvPV_nolen (*tmp), sizeof (n.message));
if (NULL != (tmp = hv_fetch (notif, "host", 4, 0)))
- strncpy (n.host, SvPV_nolen (*tmp), sizeof (n.host));
+ sstrncpy (n.host, SvPV_nolen (*tmp), sizeof (n.host));
else
- strncpy (n.host, hostname_g, sizeof (n.host));
- n.host[sizeof (n.host) - 1] = '\0';
+ sstrncpy (n.host, hostname_g, sizeof (n.host));
if (NULL != (tmp = hv_fetch (notif, "plugin", 6, 0)))
- strncpy (n.plugin, SvPV_nolen (*tmp), sizeof (n.plugin));
- n.plugin[sizeof (n.plugin) - 1] = '\0';
+ sstrncpy (n.plugin, SvPV_nolen (*tmp), sizeof (n.plugin));
if (NULL != (tmp = hv_fetch (notif, "plugin_instance", 15, 0)))
- strncpy (n.plugin_instance, SvPV_nolen (*tmp),
+ sstrncpy (n.plugin_instance, SvPV_nolen (*tmp),
sizeof (n.plugin_instance));
- n.plugin_instance[sizeof (n.plugin_instance) - 1] = '\0';
if (NULL != (tmp = hv_fetch (notif, "type", 4, 0)))
- strncpy (n.type, SvPV_nolen (*tmp), sizeof (n.type));
- n.type[sizeof (n.type) - 1] = '\0';
+ sstrncpy (n.type, SvPV_nolen (*tmp), sizeof (n.type));
if (NULL != (tmp = hv_fetch (notif, "type_instance", 13, 0)))
- strncpy (n.type_instance, SvPV_nolen (*tmp), sizeof (n.type_instance));
- n.type_instance[sizeof (n.type_instance) - 1] = '\0';
+ sstrncpy (n.type_instance, SvPV_nolen (*tmp), sizeof (n.type_instance));
return plugin_dispatch_notification (&n);
} /* static int pplugin_dispatch_notification (HV *) */
* time => $time,
* host => $hostname,
* plugin => $plugin,
+ * type => $type,
* plugin_instance => $instance,
* type_instance => $type_instance
* };
else if (PLUGIN_FLUSH == type) {
/*
* $_[0] = $timeout;
+ * $_[1] = $identifier;
*/
XPUSHs (sv_2mortal (newSViv (va_arg (ap, int))));
+ XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
}
PUTBACK;
*/
static XS (Collectd_plugin_dispatch_values)
{
- SV *values = NULL;
+ SV *values = NULL;
+ int values_idx = 0;
int ret = 0;
dXSARGS;
- if (2 != items) {
- log_err ("Usage: Collectd::plugin_dispatch_values(name, values)");
+ if (2 == items) {
+ log_warn ("Collectd::plugin_dispatch_values with two arguments "
+ "is deprecated - pass the type through values->{type}.");
+ values_idx = 1;
+ }
+ else if (1 != items) {
+ log_err ("Usage: Collectd::plugin_dispatch_values(values)");
XSRETURN_EMPTY;
}
- log_debug ("Collectd::plugin_dispatch_values: "
- "name = \"%s\", values=\"%s\"",
- SvPV_nolen (ST (0)), SvPV_nolen (ST (1)));
+ log_debug ("Collectd::plugin_dispatch_values: values=\"%s\"",
+ SvPV_nolen (ST (values_idx)));
- values = ST (1);
+ values = ST (values_idx);
if (! (SvROK (values) && (SVt_PVHV == SvTYPE (SvRV (values))))) {
log_err ("Collectd::plugin_dispatch_values: Invalid values.");
XSRETURN_EMPTY;
}
- if ((NULL == ST (0)) || (NULL == values))
+ if (((2 == items) && (NULL == ST (0))) || (NULL == values))
+ XSRETURN_EMPTY;
+
+ if ((2 == items) && (NULL == hv_store ((HV *)SvRV (values), "type", 4,
+ newSVsv (ST (0)), 0))) {
+ log_err ("Collectd::plugin_dispatch_values: Could not store type.");
XSRETURN_EMPTY;
+ }
- ret = pplugin_dispatch_values (aTHX_ SvPV_nolen (ST (0)),
- (HV *)SvRV (values));
+ ret = pplugin_dispatch_values (aTHX_ (HV *)SvRV (values));
if (0 == ret)
XSRETURN_YES;
} /* static XS (Collectd_plugin_dispatch_values) */
/*
- * Collectd::plugin_flush_one (timeout, name).
+ * Collectd::_plugin_flush (plugin, timeout, identifier).
+ *
+ * plugin:
+ * name of the plugin to flush
*
* timeout:
* timeout to use when flushing the data
*
- * name:
- * name of the plugin to flush
+ * identifier:
+ * data-set identifier to flush
*/
-static XS (Collectd_plugin_flush_one)
+static XS (Collectd__plugin_flush)
{
+ char *plugin = NULL;
+ int timeout = -1;
+ char *id = NULL;
+
dXSARGS;
- if (2 != items) {
- log_err ("Usage: Collectd::plugin_flush_one(timeout, name)");
+ if (3 != items) {
+ log_err ("Usage: Collectd::_plugin_flush(plugin, timeout, id)");
XSRETURN_EMPTY;
}
- log_debug ("Collectd::plugin_flush_one: timeout = %i, name = \"%s\"",
- (int)SvIV (ST (0)), SvPV_nolen (ST (1)));
+ if (SvOK (ST (0)))
+ plugin = SvPV_nolen (ST (0));
- if (0 == plugin_flush_one ((int)SvIV (ST (0)), SvPV_nolen (ST (1))))
- XSRETURN_YES;
- else
- XSRETURN_EMPTY;
-} /* static XS (Collectd_plugin_flush_one) */
+ if (SvOK (ST (1)))
+ timeout = (int)SvIV (ST (1));
-/*
- * Collectd::plugin_flush_all (timeout).
- *
- * timeout:
- * timeout to use when flushing the data
- */
-static XS (Collectd_plugin_flush_all)
-{
- dXSARGS;
-
- if (1 != items) {
- log_err ("Usage: Collectd::plugin_flush_all(timeout)");
- XSRETURN_EMPTY;
- }
+ if (SvOK (ST (2)))
+ id = SvPV_nolen (ST (2));
- log_debug ("Collectd::plugin_flush_all: timeout = %i", (int)SvIV (ST (0)));
+ log_debug ("Collectd::_plugin_flush: plugin = \"%s\", timeout = %i, "
+ "id = \"%s\"", plugin, timeout, id);
- plugin_flush_all ((int)SvIV (ST (0)));
- XSRETURN_YES;
-} /* static XS (Collectd_plugin_flush_all) */
+ if (0 == plugin_flush (plugin, timeout, id))
+ XSRETURN_YES;
+ else
+ XSRETURN_EMPTY;
+} /* static XS (Collectd__plugin_flush) */
/*
* Collectd::plugin_dispatch_notification (notif).
return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif);
} /* static int perl_notify (const notification_t *) */
-static int perl_flush (const int timeout)
+static int perl_flush (int timeout, const char *identifier)
{
dTHX;
aTHX = t->interp;
}
- return pplugin_call_all (aTHX_ PLUGIN_FLUSH, timeout);
+ return pplugin_call_all (aTHX_ PLUGIN_FLUSH, timeout, identifier);
} /* static int perl_flush (const int) */
static int perl_shutdown (void)
static int g_pv_set (pTHX_ SV *var, MAGIC *mg)
{
char *pv = mg->mg_ptr;
- strncpy (pv, SvPV_nolen (var), DATA_MAX_NAME_LEN);
- pv[DATA_MAX_NAME_LEN - 1] = '\0';
+ sstrncpy (pv, SvPV_nolen (var), DATA_MAX_NAME_LEN);
return 0;
} /* static int g_pv_set (pTHX_ SV *, MAGIC *) */
value = ci->values[0].value.string;
log_debug ("perl_config: Setting plugin basename to \"%s\"", value);
- strncpy (base_name, value, sizeof (base_name));
- base_name[sizeof (base_name) - 1] = '\0';
+ sstrncpy (base_name, value, sizeof (base_name));
return 0;
} /* static int perl_config_basename (oconfig_item_it *) */
return 0;
} /* static int perl_config_includedir (oconfig_item_it *) */
+/*
+ * <Plugin> block
+ */
+static int perl_config_plugin (pTHX_ oconfig_item_t *ci)
+{
+ int retvals = 0;
+ int ret = 0;
+
+ char *plugin;
+ HV *config;
+
+ dSP;
+
+ if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+ log_err ("LoadPlugin expects a single string argument.");
+ return 1;
+ }
+
+ plugin = ci->values[0].value.string;
+ config = newHV ();
+
+ if (0 != oconfig_item2hv (aTHX_ ci, config)) {
+ hv_clear (config);
+ hv_undef (config);
+
+ log_err ("Unable to convert configuration to a Perl hash value.");
+ config = Nullhv;
+ }
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK (SP);
+
+ XPUSHs (sv_2mortal (newSVpv (plugin, 0)));
+ XPUSHs (sv_2mortal (newRV_noinc ((SV *)config)));
+
+ PUTBACK;
+
+ retvals = call_pv ("Collectd::_plugin_dispatch_config", G_SCALAR);
+
+ SPAGAIN;
+ if (0 < retvals) {
+ SV *tmp = POPs;
+ if (! SvTRUE (tmp))
+ ret = 1;
+ }
+ else
+ ret = 1;
+
+ PUTBACK;
+ FREETMPS;
+ LEAVE;
+ return ret;
+} /* static int perl_config_plugin (oconfig_item_it *) */
+
static int perl_config (oconfig_item_t *ci)
{
+ int status = 0;
int i = 0;
dTHXa (NULL);
for (i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
+ int current_status;
if (NULL != perl_threads)
aTHX = PERL_GET_CONTEXT;
if (0 == strcasecmp (c->key, "LoadPlugin"))
- perl_config_loadplugin (aTHX_ c);
+ current_status = perl_config_loadplugin (aTHX_ c);
else if (0 == strcasecmp (c->key, "BaseName"))
- perl_config_basename (aTHX_ c);
+ current_status = perl_config_basename (aTHX_ c);
else if (0 == strcasecmp (c->key, "EnableDebugger"))
- perl_config_enabledebugger (aTHX_ c);
+ current_status = perl_config_enabledebugger (aTHX_ c);
else if (0 == strcasecmp (c->key, "IncludeDir"))
- perl_config_includedir (aTHX_ c);
+ current_status = perl_config_includedir (aTHX_ c);
+ else if (0 == strcasecmp (c->key, "Plugin"))
+ current_status = perl_config_plugin (aTHX_ c);
else
log_warn ("Ignoring unknown config key \"%s\".", c->key);
+
+ /* fatal error - it's up to perl_config_* to clean up */
+ if (0 > current_status) {
+ log_err ("Configuration failed with a fatal error - "
+ "plugin disabled!");
+ return current_status;
+ }
+
+ status += current_status;
}
- return 0;
+ return status;
} /* static int perl_config (oconfig_item_t *) */
void module_register (void)
diff --git a/src/ping.c b/src/ping.c
index 09de77ce97f8db083127a386f6ec41ea99c1d134..ac5b0f85907040ab0b7fbc242f6dad85d81ce79c 100644 (file)
--- a/src/ping.c
+++ b/src/ping.c
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "ping", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
- strncpy (vl.type_instance, host, sizeof (vl.type_instance));
+ sstrncpy (vl.type_instance, host, sizeof (vl.type_instance));
+ sstrncpy (vl.type, "ping", sizeof (vl.type));
- plugin_dispatch_values ("ping", &vl);
+ plugin_dispatch_values (&vl);
}
static int ping_read (void)
diff --git a/src/plugin.c b/src/plugin.c
index e72561bd8e333063ff88310686fe43227b573f5a..1ec254417069a14cd3f9b8248476807edc91610a 100644 (file)
--- a/src/plugin.c
+++ b/src/plugin.c
**/
#include "collectd.h"
+#include "utils_complain.h"
#include <ltdl.h>
/* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
* type when matching the filename */
- if (snprintf (typename, BUFSIZE, "%s.so", type) >= BUFSIZE)
+ if (ssnprintf (typename, sizeof (typename),
+ "%s.so", type) >= sizeof (typename))
{
WARNING ("snprintf: truncated: `%s.so'", type);
return (-1);
if (strncasecmp (de->d_name, typename, typename_len))
continue;
- if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE)
+ if (ssnprintf (filename, sizeof (filename),
+ "%s/%s", dir, de->d_name) >= sizeof (filename))
{
WARNING ("snprintf: truncated: `%s/%s'", dir, de->d_name);
continue;
return (register_callback (&list_write, name, (void *) callback));
} /* int plugin_register_write */
-int plugin_register_flush (const char *name, int (*callback) (const int))
+int plugin_register_flush (const char *name,
+ int (*callback) (const int timeout, const char *identifier))
{
return (register_callback (&list_flush, name, (void *) callback));
} /* int plugin_register_flush */
pthread_mutex_unlock (&read_lock);
} /* void plugin_read_all */
-int plugin_flush_one (int timeout, const char *name)
+int plugin_flush (const char *plugin, int timeout, const char *identifier)
{
- int (*callback) (int);
- llentry_t *le;
- int status;
-
- if (list_flush == NULL)
- return (-1);
-
- le = llist_search (list_flush, name);
- if (le == NULL)
- return (-1);
- callback = (int (*) (int)) le->value;
-
- status = (*callback) (timeout);
-
- return (status);
-} /* int plugin_flush_ont */
-
-void plugin_flush_all (int timeout)
-{
- int (*callback) (int);
- llentry_t *le;
-
- if (list_flush == NULL)
- return;
-
- le = llist_head (list_flush);
- while (le != NULL)
- {
- callback = (int (*) (int)) le->value;
- le = le->next;
-
- (*callback) (timeout);
- }
-} /* void plugin_flush_all */
+ int (*callback) (int timeout, const char *identifier);
+ llentry_t *le;
+
+ if (list_flush == NULL)
+ return (0);
+
+ le = llist_head (list_flush);
+ while (le != NULL)
+ {
+ if ((plugin != NULL)
+ && (strcmp (plugin, le->key) != 0))
+ {
+ le = le->next;
+ continue;
+ }
+
+ callback = (int (*) (int, const char *)) le->value;
+ (*callback) (timeout, identifier);
+
+ le = le->next;
+ }
+ return (0);
+} /* int plugin_flush */
void plugin_shutdown_all (void)
{
}
} /* void plugin_shutdown_all */
-int plugin_dispatch_values (const char *name, value_list_t *vl)
+int plugin_dispatch_values (value_list_t *vl)
{
+ static c_complain_t no_write_complaint = C_COMPLAIN_INIT;
+
int (*callback) (const data_set_t *, const value_list_t *);
data_set_t *ds;
llentry_t *le;
- if (list_write == NULL)
- {
- ERROR ("plugin_dispatch_values: No write callback has been "
- "registered. Please load at least one plugin "
- "that provides a write function.");
+ if ((vl == NULL) || (*vl->type == '\0')) {
+ ERROR ("plugin_dispatch_values: Invalid value list.");
return (-1);
}
+ if (list_write == NULL)
+ c_complain_once (LOG_WARNING, &no_write_complaint,
+ "plugin_dispatch_values: No write callback has been "
+ "registered. Please load at least one output plugin, "
+ "if you want the collected data to be stored.");
+
if (data_sets == NULL)
{
ERROR ("plugin_dispatch_values: No data sets registered. "
return (-1);
}
- if (c_avl_get (data_sets, name, (void *) &ds) != 0)
+ if (c_avl_get (data_sets, vl->type, (void *) &ds) != 0)
{
- INFO ("plugin_dispatch_values: Dataset not found: %s", name);
+ INFO ("plugin_dispatch_values: Dataset not found: %s", vl->type);
return (-1);
}
(unsigned int) vl->time, vl->interval,
vl->host,
vl->plugin, vl->plugin_instance,
- ds->type, vl->type_instance);
+ vl->type, vl->type_instance);
+
+#if COLLECT_DEBUG
+ assert (0 == strcmp (ds->type, vl->type));
+#else
+ if (0 != strcmp (ds->type, vl->type))
+ WARNING ("plugin_dispatch_values: (ds->type = %s) != (vl->type = %s)",
+ ds->type, vl->type);
+#endif
#if COLLECT_DEBUG
assert (ds->ds_num == vl->values_len);
escape_slashes (vl->host, sizeof (vl->host));
escape_slashes (vl->plugin, sizeof (vl->plugin));
escape_slashes (vl->plugin_instance, sizeof (vl->plugin_instance));
+ escape_slashes (vl->type, sizeof (vl->type));
escape_slashes (vl->type_instance, sizeof (vl->type_instance));
/* Update the value cache */
return (ds);
} /* data_set_t *plugin_get_ds */
+
+static int plugin_notification_meta_add (notification_t *n,
+ const char *name,
+ enum notification_meta_type_e type,
+ const void *value)
+{
+ notification_meta_t *meta;
+ notification_meta_t *tail;
+
+ if ((n == NULL) || (name == NULL) || (value == NULL))
+ {
+ ERROR ("plugin_notification_meta_add: A pointer is NULL!");
+ return (-1);
+ }
+
+ meta = (notification_meta_t *) malloc (sizeof (notification_meta_t));
+ if (meta == NULL)
+ {
+ ERROR ("plugin_notification_meta_add: malloc failed.");
+ return (-1);
+ }
+ memset (meta, 0, sizeof (notification_meta_t));
+
+ sstrncpy (meta->name, name, sizeof (meta->name));
+ meta->type = type;
+
+ switch (type)
+ {
+ case NM_TYPE_STRING:
+ {
+ meta->value_string = strdup ((const char *) value);
+ if (meta->value_string == NULL)
+ {
+ ERROR ("plugin_notification_meta_add: strdup failed.");
+ sfree (meta);
+ return (-1);
+ }
+ break;
+ }
+ case NM_TYPE_SIGNED_INT:
+ {
+ meta->value_signed_int = *((int64_t *) value);
+ break;
+ }
+ case NM_TYPE_UNSIGNED_INT:
+ {
+ meta->value_unsigned_int = *((uint64_t *) value);
+ break;
+ }
+ case NM_TYPE_DOUBLE:
+ {
+ meta->value_double = *((double *) value);
+ break;
+ }
+ case NM_TYPE_BOOLEAN:
+ {
+ meta->value_boolean = *((bool *) value);
+ break;
+ }
+ default:
+ {
+ ERROR ("plugin_notification_meta_add: Unknown type: %i", type);
+ sfree (meta);
+ return (-1);
+ }
+ } /* switch (type) */
+
+ meta->next = NULL;
+ tail = n->meta;
+ while ((tail != NULL) && (tail->next != NULL))
+ tail = tail->next;
+
+ if (tail == NULL)
+ n->meta = meta;
+ else
+ tail->next = meta;
+
+ return (0);
+} /* int plugin_notification_meta_add */
+
+int plugin_notification_meta_add_string (notification_t *n,
+ const char *name,
+ const char *value)
+{
+ return (plugin_notification_meta_add (n, name, NM_TYPE_STRING, value));
+}
+
+int plugin_notification_meta_add_signed_int (notification_t *n,
+ const char *name,
+ int64_t value)
+{
+ return (plugin_notification_meta_add (n, name, NM_TYPE_SIGNED_INT, &value));
+}
+
+int plugin_notification_meta_add_unsigned_int (notification_t *n,
+ const char *name,
+ uint64_t value)
+{
+ return (plugin_notification_meta_add (n, name, NM_TYPE_UNSIGNED_INT, &value));
+}
+
+int plugin_notification_meta_add_double (notification_t *n,
+ const char *name,
+ double value)
+{
+ return (plugin_notification_meta_add (n, name, NM_TYPE_DOUBLE, &value));
+}
+
+int plugin_notification_meta_add_boolean (notification_t *n,
+ const char *name,
+ bool value)
+{
+ return (plugin_notification_meta_add (n, name, NM_TYPE_BOOLEAN, &value));
+}
+
+int plugin_notification_meta_copy (notification_t *dst,
+ const notification_t *src)
+{
+ notification_meta_t *meta;
+
+ assert (dst != NULL);
+ assert (src != NULL);
+ assert (dst != src);
+ assert ((src->meta == NULL) || (src->meta != dst->meta));
+
+ for (meta = src->meta; meta != NULL; meta = meta->next)
+ {
+ if (meta->type == NM_TYPE_STRING)
+ plugin_notification_meta_add_string (dst, meta->name,
+ meta->value_string);
+ else if (meta->type == NM_TYPE_SIGNED_INT)
+ plugin_notification_meta_add_signed_int (dst, meta->name,
+ meta->value_signed_int);
+ else if (meta->type == NM_TYPE_UNSIGNED_INT)
+ plugin_notification_meta_add_unsigned_int (dst, meta->name,
+ meta->value_unsigned_int);
+ else if (meta->type == NM_TYPE_DOUBLE)
+ plugin_notification_meta_add_double (dst, meta->name,
+ meta->value_double);
+ else if (meta->type == NM_TYPE_BOOLEAN)
+ plugin_notification_meta_add_boolean (dst, meta->name,
+ meta->value_boolean);
+ }
+
+ return (0);
+} /* int plugin_notification_meta_copy */
+
+int plugin_notification_meta_free (notification_t *n)
+{
+ notification_meta_t *this;
+ notification_meta_t *next;
+
+ if (n == NULL)
+ {
+ ERROR ("plugin_notification_meta_free: n == NULL!");
+ return (-1);
+ }
+
+ this = n->meta;
+ n->meta = NULL;
+ while (this != NULL)
+ {
+ next = this->next;
+
+ if (this->type == NM_TYPE_STRING)
+ {
+ free ((char *)this->value_string);
+ this->value_string = NULL;
+ }
+ sfree (this);
+
+ this = next;
+ }
+
+ return (0);
+} /* int plugin_notification_meta_free */
diff --git a/src/plugin.h b/src/plugin.h
index 318b54734a0cbe1777855b624c9dd87adacab492..3ffde461b07da1baf684a2189bf0f6eba90e6214 100644 (file)
--- a/src/plugin.h
+++ b/src/plugin.h
char host[DATA_MAX_NAME_LEN];
char plugin[DATA_MAX_NAME_LEN];
char plugin_instance[DATA_MAX_NAME_LEN];
+ char type[DATA_MAX_NAME_LEN];
char type_instance[DATA_MAX_NAME_LEN];
};
typedef struct value_list_s value_list_t;
-#define VALUE_LIST_INIT { NULL, 0, 0, interval_g, "localhost", "", "", "" }
-#define VALUE_LIST_STATIC { NULL, 0, 0, 0, "localhost", "", "", "" }
+#define VALUE_LIST_INIT { NULL, 0, 0, interval_g, "localhost", "", "", "", "" }
+#define VALUE_LIST_STATIC { NULL, 0, 0, 0, "localhost", "", "", "", "" }
struct data_source_s
{
};
typedef struct data_set_s data_set_t;
+enum notification_meta_type_e
+{
+ NM_TYPE_STRING,
+ NM_TYPE_SIGNED_INT,
+ NM_TYPE_UNSIGNED_INT,
+ NM_TYPE_DOUBLE,
+ NM_TYPE_BOOLEAN
+};
+
+typedef struct notification_meta_s
+{
+ char name[DATA_MAX_NAME_LEN];
+ enum notification_meta_type_e type;
+ union
+ {
+ const char *value_string;
+ int64_t value_signed_int;
+ uint64_t value_unsigned_int;
+ double value_double;
+ bool value_boolean;
+ };
+ struct notification_meta_s *next;
+} notification_meta_t;
+
typedef struct notification_s
{
int severity;
char plugin_instance[DATA_MAX_NAME_LEN];
char type[DATA_MAX_NAME_LEN];
char type_instance[DATA_MAX_NAME_LEN];
+ notification_meta_t *meta;
} notification_t;
/*
void plugin_init_all (void);
void plugin_read_all (void);
-void plugin_flush_all (int timeout);
void plugin_shutdown_all (void);
-int plugin_flush_one (int timeout, const char *name);
+int plugin_flush (const char *plugin, int timeout, const char *identifier);
/*
* The `plugin_register_*' functions are used to make `config', `init',
int plugin_register_write (const char *name,
int (*callback) (const data_set_t *ds, const value_list_t *vl));
int plugin_register_flush (const char *name,
- int (*callback) (const int));
+ int (*callback) (const int timeout, const char *identifier));
int plugin_register_shutdown (char *name,
int (*callback) (void));
int plugin_register_data_set (const data_set_t *ds);
* write-functions.
*
* ARGUMENTS
- * `name' Name/type of the data-set that describe the values in `vl'.
* `vl' Value list of the values that have been read by a `read'
* function.
*/
-int plugin_dispatch_values (const char *name, value_list_t *vl);
+int plugin_dispatch_values (value_list_t *vl);
int plugin_dispatch_notification (const notification_t *notif);
const data_set_t *plugin_get_ds (const char *name);
+int plugin_notification_meta_add_string (notification_t *n,
+ const char *name,
+ const char *value);
+int plugin_notification_meta_add_signed_int (notification_t *n,
+ const char *name,
+ int64_t value);
+int plugin_notification_meta_add_unsigned_int (notification_t *n,
+ const char *name,
+ uint64_t value);
+int plugin_notification_meta_add_double (notification_t *n,
+ const char *name,
+ double value);
+int plugin_notification_meta_add_boolean (notification_t *n,
+ const char *name,
+ bool value);
+
+int plugin_notification_meta_copy (notification_t *dst,
+ const notification_t *src);
+
+int plugin_notification_meta_free (notification_t *n);
+
#endif /* PLUGIN_H */
diff --git a/src/postgresql.c b/src/postgresql.c
--- /dev/null
+++ b/src/postgresql.c
@@ -0,0 +1,895 @@
+/**
+ * collectd - src/postgresql.c
+ * Copyright (C) 2008 Sebastian Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Sebastian Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This module collects PostgreSQL database statistics.
+ */
+
+#include "collectd.h"
+#include "common.h"
+
+#include "configfile.h"
+#include "plugin.h"
+
+#include "utils_complain.h"
+
+#include <pg_config_manual.h>
+#include <libpq-fe.h>
+
+#define log_err(...) ERROR ("postgresql: " __VA_ARGS__)
+#define log_warn(...) WARNING ("postgresql: " __VA_ARGS__)
+#define log_info(...) INFO ("postgresql: " __VA_ARGS__)
+
+#ifndef C_PSQL_DEFAULT_CONF
+# define C_PSQL_DEFAULT_CONF PKGDATADIR "/postgresql_default.conf"
+#endif
+
+/* Appends the (parameter, value) pair to the string
+ * pointed to by 'buf' suitable to be used as argument
+ * for PQconnectdb(). If value equals NULL, the pair
+ * is ignored. */
+#define C_PSQL_PAR_APPEND(buf, buf_len, parameter, value) \
+ if ((0 < (buf_len)) && (NULL != (value)) && ('\0' != *(value))) { \
+ int s = ssnprintf (buf, buf_len, " %s = '%s'", parameter, value); \
+ if (0 < s) { \
+ buf += s; \
+ buf_len -= s; \
+ } \
+ }
+
+/* Returns the tuple (major, minor, patchlevel)
+ * for the given version number. */
+#define C_PSQL_SERVER_VERSION3(server_version) \
+ (server_version) / 10000, \
+ (server_version) / 100 - (int)((server_version) / 10000) * 100, \
+ (server_version) - (int)((server_version) / 100) * 100
+
+/* Returns true if the given host specifies a
+ * UNIX domain socket. */
+#define C_PSQL_IS_UNIX_DOMAIN_SOCKET(host) \
+ ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
+
+/* Returns the tuple (host, delimiter, port) for a
+ * given (host, port) pair. Depending on the value of
+ * 'host' a UNIX domain socket or a TCP socket is
+ * assumed. */
+#define C_PSQL_SOCKET3(host, port) \
+ ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, \
+ C_PSQL_IS_UNIX_DOMAIN_SOCKET (host) ? "/.s.PGSQL." : ":", \
+ port
+
+typedef enum {
+ C_PSQL_PARAM_HOST = 1,
+ C_PSQL_PARAM_DB,
+ C_PSQL_PARAM_USER,
+} c_psql_param_t;
+
+typedef struct {
+ char *type;
+ char *type_instance;
+ int ds_type;
+} c_psql_col_t;
+
+typedef struct {
+ char *name;
+ char *query;
+
+ c_psql_param_t *params;
+ int params_num;
+
+ c_psql_col_t *cols;
+ int cols_num;
+
+ int min_pg_version;
+ int max_pg_version;
+} c_psql_query_t;
+
+typedef struct {
+ PGconn *conn;
+ c_complain_t conn_complaint;
+
+ int proto_version;
+
+ int max_params_num;
+
+ /* user configuration */
+ c_psql_query_t **queries;
+ int queries_num;
+
+ char *host;
+ char *port;
+ char *database;
+ char *user;
+ char *password;
+
+ char *sslmode;
+
+ char *krbsrvname;
+
+ char *service;
+} c_psql_database_t;
+
+static char *def_queries[] = {
+ "backends",
+ "transactions",
+ "queries",
+ "query_plans",
+ "table_states",
+ "disk_io",
+ "disk_usage"
+};
+static int def_queries_num = STATIC_ARRAY_SIZE (def_queries);
+
+static c_psql_query_t *queries = NULL;
+static int queries_num = 0;
+
+static c_psql_database_t *databases = NULL;
+static int databases_num = 0;
+
+static c_psql_query_t *c_psql_query_new (const char *name)
+{
+ c_psql_query_t *query;
+
+ ++queries_num;
+ if (NULL == (queries = (c_psql_query_t *)realloc (queries,
+ queries_num * sizeof (*queries)))) {
+ log_err ("Out of memory.");
+ exit (5);
+ }
+ query = queries + queries_num - 1;
+
+ query->name = sstrdup (name);
+ query->query = NULL;
+
+ query->params = NULL;
+ query->params_num = 0;
+
+ query->cols = NULL;
+ query->cols_num = 0;
+
+ query->min_pg_version = 0;
+ query->max_pg_version = INT_MAX;
+ return query;
+} /* c_psql_query_new */
+
+static void c_psql_query_delete (c_psql_query_t *query)
+{
+ int i;
+
+ sfree (query->name);
+ sfree (query->query);
+
+ sfree (query->params);
+ query->params_num = 0;
+
+ for (i = 0; i < query->cols_num; ++i) {
+ sfree (query->cols[i].type);
+ sfree (query->cols[i].type_instance);
+ }
+ sfree (query->cols);
+ query->cols_num = 0;
+ return;
+} /* c_psql_query_delete */
+
+static c_psql_query_t *c_psql_query_get (const char *name, int server_version)
+{
+ int i;
+
+ for (i = 0; i < queries_num; ++i)
+ if (0 == strcasecmp (name, queries[i].name)
+ && ((-1 == server_version)
+ || ((queries[i].min_pg_version <= server_version)
+ && (server_version <= queries[i].max_pg_version))))
+ return queries + i;
+ return NULL;
+} /* c_psql_query_get */
+
+static c_psql_database_t *c_psql_database_new (const char *name)
+{
+ c_psql_database_t *db;
+
+ ++databases_num;
+ if (NULL == (databases = (c_psql_database_t *)realloc (databases,
+ databases_num * sizeof (*databases)))) {
+ log_err ("Out of memory.");
+ exit (5);
+ }
+
+ db = databases + (databases_num - 1);
+
+ db->conn = NULL;
+
+ db->conn_complaint.last = 0;
+ db->conn_complaint.interval = 0;
+
+ db->proto_version = 0;
+
+ db->max_params_num = 0;
+
+ db->queries = NULL;
+ db->queries_num = 0;
+
+ db->database = sstrdup (name);
+ db->host = NULL;
+ db->port = NULL;
+ db->user = NULL;
+ db->password = NULL;
+
+ db->sslmode = NULL;
+
+ db->krbsrvname = NULL;
+
+ db->service = NULL;
+ return db;
+} /* c_psql_database_new */
+
+static void c_psql_database_delete (c_psql_database_t *db)
+{
+ PQfinish (db->conn);
+
+ sfree (db->queries);
+ db->queries_num = 0;
+
+ sfree (db->database);
+ sfree (db->host);
+ sfree (db->port);
+ sfree (db->user);
+ sfree (db->password);
+
+ sfree (db->sslmode);
+
+ sfree (db->krbsrvname);
+
+ sfree (db->service);
+ return;
+} /* c_psql_database_delete */
+
+static void submit (const c_psql_database_t *db,
+ const char *type, const char *type_instance,
+ value_t *values, size_t values_len)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+
+ vl.values = values;
+ vl.values_len = values_len;
+ vl.time = time (NULL);
+
+ if (C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
+ || (0 == strcmp (db->host, "localhost")))
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ else
+ sstrncpy (vl.host, db->host, sizeof (vl.host));
+
+ sstrncpy (vl.plugin, "postgresql", sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, db->database, sizeof (vl.plugin_instance));
+
+ sstrncpy (vl.type, type, sizeof (vl.type));
+
+ if (NULL != type_instance)
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+ return;
+} /* submit */
+
+static void submit_counter (const c_psql_database_t *db,
+ const char *type, const char *type_instance,
+ const char *value)
+{
+ value_t values[1];
+
+ if ((NULL == value) || ('\0' == *value))
+ return;
+
+ values[0].counter = atoll (value);
+ submit (db, type, type_instance, values, 1);
+ return;
+} /* submit_counter */
+
+static void submit_gauge (const c_psql_database_t *db,
+ const char *type, const char *type_instance,
+ const char *value)
+{
+ value_t values[1];
+
+ if ((NULL == value) || ('\0' == *value))
+ return;
+
+ values[0].gauge = atof (value);
+ submit (db, type, type_instance, values, 1);
+ return;
+} /* submit_gauge */
+
+static int c_psql_check_connection (c_psql_database_t *db)
+{
+ /* "ping" */
+ PQclear (PQexec (db->conn, "SELECT 42;"));
+
+ if (CONNECTION_OK != PQstatus (db->conn)) {
+ PQreset (db->conn);
+
+ /* trigger c_release() */
+ if (0 == db->conn_complaint.interval)
+ db->conn_complaint.interval = 1;
+
+ if (CONNECTION_OK != PQstatus (db->conn)) {
+ c_complain (LOG_ERR, &db->conn_complaint,
+ "Failed to connect to database %s: %s",
+ db->database, PQerrorMessage (db->conn));
+ return -1;
+ }
+
+ db->proto_version = PQprotocolVersion (db->conn);
+ if (3 > db->proto_version)
+ log_warn ("Protocol version %d does not support parameters.",
+ db->proto_version);
+ }
+
+ c_release (LOG_INFO, &db->conn_complaint,
+ "Successfully reconnected to database %s", PQdb (db->conn));
+ return 0;
+} /* c_psql_check_connection */
+
+static PGresult *c_psql_exec_query_params (c_psql_database_t *db,
+ c_psql_query_t *query)
+{
+ char *params[db->max_params_num];
+ int i;
+
+ assert (db->max_params_num >= query->params_num);
+
+ for (i = 0; i < query->params_num; ++i) {
+ switch (query->params[i]) {
+ case C_PSQL_PARAM_HOST:
+ params[i] = C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
+ ? "localhost" : db->host;
+ break;
+ case C_PSQL_PARAM_DB:
+ params[i] = db->database;
+ break;
+ case C_PSQL_PARAM_USER:
+ params[i] = db->user;
+ break;
+ default:
+ assert (0);
+ }
+ }
+
+ return PQexecParams (db->conn, query->query, query->params_num, NULL,
+ (const char *const *)((0 == query->params_num) ? NULL : params),
+ NULL, NULL, /* return text data */ 0);
+} /* c_psql_exec_query_params */
+
+static PGresult *c_psql_exec_query_noparams (c_psql_database_t *db,
+ c_psql_query_t *query)
+{
+ return PQexec (db->conn, query->query);
+} /* c_psql_exec_query_noparams */
+
+static int c_psql_exec_query (c_psql_database_t *db, int idx)
+{
+ c_psql_query_t *query;
+ PGresult *res;
+
+ int rows, cols;
+ int i;
+
+ if (idx >= db->queries_num)
+ return -1;
+
+ query = db->queries[idx];
+
+ if (3 <= db->proto_version)
+ res = c_psql_exec_query_params (db, query);
+ else if (0 == query->params_num)
+ res = c_psql_exec_query_noparams (db, query);
+ else {
+ log_err ("Connection to database \"%s\" does not support parameters "
+ "(protocol version %d) - cannot execute query \"%s\".",
+ db->database, db->proto_version, query->name);
+ return -1;
+ }
+
+ if (PGRES_TUPLES_OK != PQresultStatus (res)) {
+ log_err ("Failed to execute SQL query: %s",
+ PQerrorMessage (db->conn));
+ log_info ("SQL query was: %s", query->query);
+ PQclear (res);
+ return -1;
+ }
+
+ rows = PQntuples (res);
+ if (1 > rows)
+ return 0;
+
+ cols = PQnfields (res);
+ if (query->cols_num != cols) {
+ log_err ("SQL query returned wrong number of fields "
+ "(expected: %i, got: %i)", query->cols_num, cols);
+ log_info ("SQL query was: %s", query->query);
+ return -1;
+ }
+
+ for (i = 0; i < rows; ++i) {
+ int j;
+
+ for (j = 0; j < cols; ++j) {
+ c_psql_col_t col = query->cols[j];
+
+ char *value = PQgetvalue (res, i, j);
+
+ if (col.ds_type == DS_TYPE_COUNTER)
+ submit_counter (db, col.type, col.type_instance, value);
+ else if (col.ds_type == DS_TYPE_GAUGE)
+ submit_gauge (db, col.type, col.type_instance, value);
+ }
+ }
+ return 0;
+} /* c_psql_exec_query */
+
+static int c_psql_read (void)
+{
+ int success = 0;
+ int i;
+
+ for (i = 0; i < databases_num; ++i) {
+ c_psql_database_t *db = databases + i;
+
+ int j;
+
+ assert (NULL != db->database);
+
+ if (0 != c_psql_check_connection (db))
+ continue;
+
+ for (j = 0; j < db->queries_num; ++j)
+ c_psql_exec_query (db, j);
+
+ ++success;
+ }
+
+ if (! success)
+ return -1;
+ return 0;
+} /* c_psql_read */
+
+static int c_psql_shutdown (void)
+{
+ int i;
+
+ if ((NULL == databases) || (0 == databases_num))
+ return 0;
+
+ plugin_unregister_read ("postgresql");
+ plugin_unregister_shutdown ("postgresql");
+
+ for (i = 0; i < databases_num; ++i) {
+ c_psql_database_t *db = databases + i;
+ c_psql_database_delete (db);
+ }
+
+ sfree (databases);
+ databases_num = 0;
+
+ for (i = 0; i < queries_num; ++i) {
+ c_psql_query_t *query = queries + i;
+ c_psql_query_delete (query);
+ }
+
+ sfree (queries);
+ queries_num = 0;
+ return 0;
+} /* c_psql_shutdown */
+
+static int c_psql_init (void)
+{
+ int i;
+
+ if ((NULL == databases) || (0 == databases_num))
+ return 0;
+
+ for (i = 0; i < queries_num; ++i) {
+ c_psql_query_t *query = queries + i;
+ int j;
+
+ for (j = 0; j < query->cols_num; ++j) {
+ c_psql_col_t *col = query->cols + j;
+ const data_set_t *ds;
+
+ ds = plugin_get_ds (col->type);
+ if (NULL == ds) {
+ log_err ("Column: Unknown type \"%s\".", col->type);
+ c_psql_shutdown ();
+ return -1;
+ }
+
+ if (1 != ds->ds_num) {
+ log_err ("Column: Invalid type \"%s\" - types defining "
+ "one data source are supported only (got: %i).",
+ col->type, ds->ds_num);
+ c_psql_shutdown ();
+ return -1;
+ }
+
+ col->ds_type = ds->ds[0].type;
+ }
+ }
+
+ for (i = 0; i < databases_num; ++i) {
+ c_psql_database_t *db = databases + i;
+
+ char conninfo[4096];
+ char *buf = conninfo;
+ int buf_len = sizeof (conninfo);
+ int status;
+
+ char *server_host;
+ int server_version;
+
+ int j;
+
+ status = ssnprintf (buf, buf_len, "dbname = '%s'", db->database);
+ if (0 < status) {
+ buf += status;
+ buf_len -= status;
+ }
+
+ C_PSQL_PAR_APPEND (buf, buf_len, "host", db->host);
+ C_PSQL_PAR_APPEND (buf, buf_len, "port", db->port);
+ C_PSQL_PAR_APPEND (buf, buf_len, "user", db->user);
+ C_PSQL_PAR_APPEND (buf, buf_len, "password", db->password);
+ C_PSQL_PAR_APPEND (buf, buf_len, "sslmode", db->sslmode);
+ C_PSQL_PAR_APPEND (buf, buf_len, "krbsrvname", db->krbsrvname);
+ C_PSQL_PAR_APPEND (buf, buf_len, "service", db->service);
+
+ db->conn = PQconnectdb (conninfo);
+ if (0 != c_psql_check_connection (db))
+ continue;
+
+ db->proto_version = PQprotocolVersion (db->conn);
+
+ server_host = PQhost (db->conn);
+ server_version = PQserverVersion (db->conn);
+ log_info ("Sucessfully connected to database %s (user %s) "
+ "at server %s%s%s (server version: %d.%d.%d, "
+ "protocol version: %d, pid: %d)",
+ PQdb (db->conn), PQuser (db->conn),
+ C_PSQL_SOCKET3 (server_host, PQport (db->conn)),
+ C_PSQL_SERVER_VERSION3 (server_version),
+ db->proto_version, PQbackendPID (db->conn));
+
+ if (3 > db->proto_version)
+ log_warn ("Protocol version %d does not support parameters.",
+ db->proto_version);
+
+ /* Now that we know the PostgreSQL server version, we can get the
+ * right version of each query definition. */
+ for (j = 0; j < db->queries_num; ++j) {
+ c_psql_query_t *tmp;
+
+ tmp = c_psql_query_get (db->queries[j]->name, server_version);
+
+ if (tmp == db->queries[j])
+ continue;
+
+ if (NULL == tmp) {
+ log_err ("Query \"%s\" not found for server version %i - "
+ "please check your configuration.",
+ db->queries[j]->name, server_version);
+
+ if (db->queries_num - j - 1 > 0)
+ memmove (db->queries + j, db->queries + j + 1,
+ (db->queries_num - j - 1) * sizeof (*db->queries));
+
+ --db->queries_num;
+ --j;
+ continue;
+ }
+
+ db->queries[j] = tmp;
+ }
+ }
+
+ plugin_register_read ("postgresql", c_psql_read);
+ plugin_register_shutdown ("postgresql", c_psql_shutdown);
+ return 0;
+} /* c_psql_init */
+
+static int config_set_s (char *name, char **var, const oconfig_item_t *ci)
+{
+ if ((0 != ci->children_num) || (1 != ci->values_num)
+ || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+ log_err ("%s expects a single string argument.", name);
+ return 1;
+ }
+
+ sfree (*var);
+ *var = sstrdup (ci->values[0].value.string);
+ return 0;
+} /* config_set_s */
+
+static int config_set_i (char *name, int *var, const oconfig_item_t *ci)
+{
+ if ((0 != ci->children_num) || (1 != ci->values_num)
+ || (OCONFIG_TYPE_NUMBER != ci->values[0].type)) {
+ log_err ("%s expects a single number argument.", name);
+ return 1;
+ }
+
+ *var = (int)ci->values[0].value.number;
+ return 0;
+} /* config_set_i */
+
+static int config_set_param (c_psql_query_t *query, const oconfig_item_t *ci)
+{
+ c_psql_param_t param;
+ char *param_str;
+
+ if ((0 != ci->children_num) || (1 != ci->values_num)
+ || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+ log_err ("Param expects a single string argument.");
+ return 1;
+ }
+
+ param_str = ci->values[0].value.string;
+ if (0 == strcasecmp (param_str, "hostname"))
+ param = C_PSQL_PARAM_HOST;
+ else if (0 == strcasecmp (param_str, "database"))
+ param = C_PSQL_PARAM_DB;
+ else if (0 == strcasecmp (param_str, "username"))
+ param = C_PSQL_PARAM_USER;
+ else {
+ log_err ("Invalid parameter \"%s\".", param_str);
+ return 1;
+ }
+
+ ++query->params_num;
+ if (NULL == (query->params = (c_psql_param_t *)realloc (query->params,
+ query->params_num * sizeof (*query->params)))) {
+ log_err ("Out of memory.");
+ exit (5);
+ }
+
+ query->params[query->params_num - 1] = param;
+ return 0;
+} /* config_set_param */
+
+static int config_set_column (c_psql_query_t *query, const oconfig_item_t *ci)
+{
+ c_psql_col_t *col;
+
+ int i;
+
+ if ((0 != ci->children_num)
+ || (1 > ci->values_num) || (2 < ci->values_num)) {
+ log_err ("Column expects either one or two arguments.");
+ return 1;
+ }
+
+ for (i = 0; i < ci->values_num; ++i) {
+ if (OCONFIG_TYPE_STRING != ci->values[i].type) {
+ log_err ("Column expects either one or two string arguments.");
+ return 1;
+ }
+ }
+
+ ++query->cols_num;
+ if (NULL == (query->cols = (c_psql_col_t *)realloc (query->cols,
+ query->cols_num * sizeof (*query->cols)))) {
+ log_err ("Out of memory.");
+ exit (5);
+ }
+
+ col = query->cols + query->cols_num - 1;
+
+ col->ds_type = -1;
+
+ col->type = sstrdup (ci->values[0].value.string);
+ col->type_instance = (2 == ci->values_num)
+ ? sstrdup (ci->values[1].value.string) : NULL;
+ return 0;
+} /* config_set_column */
+
+static int set_query (c_psql_database_t *db, const char *name)
+{
+ c_psql_query_t *query;
+
+ query = c_psql_query_get (name, -1);
+ if (NULL == query) {
+ log_err ("Query \"%s\" not found - please check your configuration.",
+ name);
+ return 1;
+ }
+
+ ++db->queries_num;
+ if (NULL == (db->queries = (c_psql_query_t **)realloc (db->queries,
+ db->queries_num * sizeof (*db->queries)))) {
+ log_err ("Out of memory.");
+ exit (5);
+ }
+
+ if (query->params_num > db->max_params_num)
+ db->max_params_num = query->params_num;
+
+ db->queries[db->queries_num - 1] = query;
+ return 0;
+} /* set_query */
+
+static int config_set_query (c_psql_database_t *db, const oconfig_item_t *ci)
+{
+ if ((0 != ci->children_num) || (1 != ci->values_num)
+ || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+ log_err ("Query expects a single string argument.");
+ return 1;
+ }
+ return set_query (db, ci->values[0].value.string);
+} /* config_set_query */
+
+static int c_psql_config_query (oconfig_item_t *ci)
+{
+ c_psql_query_t *query;
+
+ int i;
+
+ if ((1 != ci->values_num)
+ || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+ log_err ("<Query> expects a single string argument.");
+ return 1;
+ }
+
+ query = c_psql_query_new (ci->values[0].value.string);
+
+ for (i = 0; i < ci->children_num; ++i) {
+ oconfig_item_t *c = ci->children + i;
+
+ if (0 == strcasecmp (c->key, "Query"))
+ config_set_s ("Query", &query->query, c);
+ else if (0 == strcasecmp (c->key, "Param"))
+ config_set_param (query, c);
+ else if (0 == strcasecmp (c->key, "Column"))
+ config_set_column (query, c);
+ else if (0 == strcasecmp (c->key, "MinPGVersion"))
+ config_set_i ("MinPGVersion", &query->min_pg_version, c);
+ else if (0 == strcasecmp (c->key, "MaxPGVersion"))
+ config_set_i ("MaxPGVersion", &query->max_pg_version, c);
+ else
+ log_warn ("Ignoring unknown config key \"%s\".", c->key);
+ }
+
+ for (i = 0; i < queries_num - 1; ++i) {
+ c_psql_query_t *q = queries + i;
+
+ if ((0 == strcasecmp (q->name, query->name))
+ && (q->min_pg_version <= query->max_pg_version)
+ && (query->min_pg_version <= q->max_pg_version)) {
+ log_err ("Ignoring redefinition (with overlapping version ranges) "
+ "of query \"%s\".", query->name);
+ c_psql_query_delete (query);
+ --queries_num;
+ return 1;
+ }
+ }
+
+ if (query->min_pg_version > query->max_pg_version) {
+ log_err ("Query \"%s\": MinPGVersion > MaxPGVersion.",
+ query->name);
+ c_psql_query_delete (query);
+ --queries_num;
+ return 1;
+ }
+
+ if (NULL == query->query) {
+ log_err ("Query \"%s\" does not include an SQL query string - "
+ "please check your configuration.", query->name);
+ c_psql_query_delete (query);
+ --queries_num;
+ return 1;
+ }
+ return 0;
+} /* c_psql_config_query */
+
+static int c_psql_config_database (oconfig_item_t *ci)
+{
+ c_psql_database_t *db;
+
+ int i;
+
+ if ((1 != ci->values_num)
+ || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+ log_err ("<Database> expects a single string argument.");
+ return 1;
+ }
+
+ db = c_psql_database_new (ci->values[0].value.string);
+
+ for (i = 0; i < ci->children_num; ++i) {
+ oconfig_item_t *c = ci->children + i;
+
+ if (0 == strcasecmp (c->key, "Host"))
+ config_set_s ("Host", &db->host, c);
+ else if (0 == strcasecmp (c->key, "Port"))
+ config_set_s ("Port", &db->port, c);
+ else if (0 == strcasecmp (c->key, "User"))
+ config_set_s ("User", &db->user, c);
+ else if (0 == strcasecmp (c->key, "Password"))
+ config_set_s ("Password", &db->password, c);
+ else if (0 == strcasecmp (c->key, "SSLMode"))
+ config_set_s ("SSLMode", &db->sslmode, c);
+ else if (0 == strcasecmp (c->key, "KRBSrvName"))
+ config_set_s ("KRBSrvName", &db->krbsrvname, c);
+ else if (0 == strcasecmp (c->key, "Service"))
+ config_set_s ("Service", &db->service, c);
+ else if (0 == strcasecmp (c->key, "Query"))
+ config_set_query (db, c);
+ else
+ log_warn ("Ignoring unknown config key \"%s\".", c->key);
+ }
+
+ if (NULL == db->queries) {
+ for (i = 0; i < def_queries_num; ++i)
+ set_query (db, def_queries[i]);
+ }
+ return 0;
+}
+
+static int c_psql_config (oconfig_item_t *ci)
+{
+ static int have_def_config = 0;
+
+ int i;
+
+ if (0 == have_def_config) {
+ oconfig_item_t *c;
+
+ have_def_config = 1;
+
+ c = oconfig_parse_file (C_PSQL_DEFAULT_CONF);
+ if (NULL == c)
+ log_err ("Failed to read default config ("C_PSQL_DEFAULT_CONF").");
+ else
+ c_psql_config (c);
+
+ if (NULL == queries)
+ log_err ("Default config ("C_PSQL_DEFAULT_CONF") did not define "
+ "any queries - please check your installation.");
+ }
+
+ for (i = 0; i < ci->children_num; ++i) {
+ oconfig_item_t *c = ci->children + i;
+
+ if (0 == strcasecmp (c->key, "Query"))
+ c_psql_config_query (c);
+ else if (0 == strcasecmp (c->key, "Database"))
+ c_psql_config_database (c);
+ else
+ log_warn ("Ignoring unknown config key \"%s\".", c->key);
+ }
+ return 0;
+} /* c_psql_config */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("postgresql", c_psql_config);
+ plugin_register_init ("postgresql", c_psql_init);
+} /* module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/postgresql_default.conf b/src/postgresql_default.conf
--- /dev/null
@@ -0,0 +1,93 @@
+# Pre-defined queries of collectd's postgresql plugin.
+
+<Query backends>
+ Query "SELECT count(*) \
+ FROM pg_stat_activity \
+ WHERE datname = $1;"
+
+ Param database
+
+ Column pg_numbackends
+</Query>
+
+<Query transactions>
+ Query "SELECT xact_commit, xact_rollback \
+ FROM pg_stat_database \
+ WHERE datname = $1;"
+
+ Param database
+
+ Column pg_xact commit
+ Column pg_xact rollback
+</Query>
+
+<Query queries>
+ Query "SELECT sum(n_tup_ins), sum(n_tup_upd), sum(n_tup_del) \
+ FROM pg_stat_user_tables;"
+
+ Column pg_n_tup_c ins
+ Column pg_n_tup_c upd
+ Column pg_n_tup_c del
+
+ MaxPGVersion 80299
+</Query>
+
+<Query queries>
+ Query "SELECT sum(n_tup_ins), sum(n_tup_upd), sum(n_tup_del), \
+ sum(n_tup_hot_upd) \
+ FROM pg_stat_user_tables;"
+
+ Column pg_n_tup_c ins
+ Column pg_n_tup_c upd
+ Column pg_n_tup_c del
+ Column pg_n_tup_c hot_upd
+
+ MinPGVersion 80300
+</Query>
+
+<Query query_plans>
+ Query "SELECT sum(seq_scan), sum(seq_tup_read), \
+ sum(idx_scan), sum(idx_tup_fetch) \
+ FROM pg_stat_user_tables;"
+
+ Column pg_scan seq
+ Column pg_scan seq_tup_read
+ Column pg_scan idx
+ Column pg_scan idx_tup_fetch
+</Query>
+
+<Query table_states>
+ Query "SELECT sum(n_live_tup), sum(n_dead_tup) \
+ FROM pg_stat_user_tables;"
+
+ Column pg_n_tup_g live
+ Column pg_n_tup_g dead
+
+ MinPGVersion 80300
+</Query>
+
+<Query disk_io>
+ Query "SELECT sum(heap_blks_read), sum(heap_blks_hit), \
+ sum(idx_blks_read), sum(idx_blks_hit), \
+ sum(toast_blks_read), sum(toast_blks_hit), \
+ sum(tidx_blks_read), sum(tidx_blks_hit) \
+ FROM pg_statio_user_tables;"
+
+ Column pg_blks heap_read
+ Column pg_blks heap_hit
+ Column pg_blks idx_read
+ Column pg_blks idx_hit
+ Column pg_blks toast_read
+ Column pg_blks toast_hit
+ Column pg_blks tidx_read
+ Column pg_blks tidx_hit
+</Query>
+
+<Query disk_usage>
+ Query "SELECT pg_database_size($1);"
+
+ Param database
+
+ Column pg_db_size
+</Query>
+
diff --git a/src/powerdns.c b/src/powerdns.c
index a0ad3a44e59ffdc339c6a2e32657e7d441f91018..189c46fec1bbf2cb7383096418da4b5649f94d97 100644 (file)
--- a/src/powerdns.c
+++ b/src/powerdns.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "powerdns", sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_instance != NULL)
sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* }}} static void submit */
static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
memset (&sa_unix, 0, sizeof (sa_unix));
sa_unix.sun_family = AF_UNIX;
- strncpy (sa_unix.sun_path,
+ sstrncpy (sa_unix.sun_path,
(local_sockpath != NULL) ? local_sockpath : PDNS_LOCAL_SOCKPATH,
sizeof (sa_unix.sun_path));
- sa_unix.sun_path[sizeof (sa_unix.sun_path) - 1] = 0;
status = unlink (sa_unix.sun_path);
if ((status != 0) && (errno != ENOENT))
}
item->sockaddr.sun_family = AF_UNIX;
- sstrncpy (item->sockaddr.sun_path, socket_temp, UNIX_PATH_MAX);
+ sstrncpy (item->sockaddr.sun_path, socket_temp,
+ sizeof (item->sockaddr.sun_path));
e = llentry_create (item->instance, item);
if (e == NULL)
diff --git a/src/processes.c b/src/processes.c
index c8376812445fce298cd37bd21ed2afad3a2d5e3d..f229804d95121de08a421ba8f8f30b39feb43a8a 100644 (file)
--- a/src/processes.c
+++ b/src/processes.c
/**
* collectd - src/processes.c
* Copyright (C) 2005 Lyonel Vincent
- * Copyright (C) 2006-2007 Florian Forster (Mach code)
+ * Copyright (C) 2006-2008 Florian Forster (Mach code)
+ * Copyright (C) 2008 Oleg King
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Authors:
* Lyonel Vincent <lyonel at ezix.org>
* Florian octo Forster <octo at verplant.org>
+ * Oleg King <king2 at kaluga.ru>
**/
#include "collectd.h"
# endif
/* #endif KERNEL_LINUX */
+#elif HAVE_LIBKVM_GETPROCS
+# include <kvm.h>
+# include <sys/user.h>
+# include <sys/proc.h>
+# if HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+# endif
+/* #endif HAVE_LIBKVM_GETPROCS */
+
#else
# error "No applicable input method."
#endif
+#if HAVE_REGEX_H
+# include <regex.h>
+#endif
+
#define BUFSIZE 256
static const char *config_keys[] =
{
"Process",
+ "ProcessMatch",
NULL
};
-static int config_keys_num = 1;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
typedef struct procstat_entry_s
{
typedef struct procstat
{
char name[PROCSTAT_NAME_LEN];
+#if HAVE_REGEX_H
+ regex_t *re;
+#endif
unsigned long num_proc;
unsigned long num_lwp;
#elif KERNEL_LINUX
static long pagesize_g;
-#endif /* KERNEL_LINUX */
+/* #endif KERNEL_LINUX */
-static void ps_list_register (const char *name)
+#elif HAVE_LIBKVM_GETPROCS
+/* no global variables */
+#endif /* HAVE_LIBKVM_GETPROCS */
+
+/* put name of process from config to list_head_g tree
+ list_head_g is a list of 'procstat_t' structs with
+ processes names we want to watch */
+static void ps_list_register (const char *name, const char *regexp)
{
procstat_t *new;
procstat_t *ptr;
+ int status;
- if ((new = (procstat_t *) malloc (sizeof (procstat_t))) == NULL)
+ new = (procstat_t *) malloc (sizeof (procstat_t));
+ if (new == NULL)
+ {
+ ERROR ("processes plugin: ps_list_register: malloc failed.");
return;
+ }
memset (new, 0, sizeof (procstat_t));
- strncpy (new->name, name, PROCSTAT_NAME_LEN);
+ sstrncpy (new->name, name, sizeof (new->name));
+
+#if HAVE_REGEX_H
+ if (regexp != NULL)
+ {
+ DEBUG ("ProcessMatch: adding \"%s\" as criteria to process %s.", regexp, name);
+ new->re = (regex_t *) malloc (sizeof (regex_t));
+ if (new->re == NULL)
+ {
+ ERROR ("processes plugin: ps_list_register: malloc failed.");
+ sfree (new);
+ return;
+ }
+ status = regcomp (new->re, regexp, REG_EXTENDED | REG_NOSUB);
+ if (status != 0)
+ {
+ DEBUG ("ProcessMatch: compiling the regular expression \"%s\" failed.", regexp);
+ sfree(new->re);
+ return;
+ }
+ }
+#else
+ if (regexp != NULL)
+ {
+ ERROR ("processes plugin: ps_list_register: "
+ "Regular expression \"%s\" found in config "
+ "file, but support for regular expressions "
+ "has been dispabled at compile time.",
+ regexp);
+ sfree (new);
+ return;
+ }
+#endif
+
for (ptr = list_head_g; ptr != NULL; ptr = ptr->next)
{
if (strcmp (ptr->name, name) == 0)
+ {
+ WARNING ("processes plugin: You have configured more "
+ "than one `Process' or "
+ "`ProcessMatch' with the same name. "
+ "All but the first setting will be "
+ "ignored.");
+ sfree (new->re);
+ sfree (new);
return;
+ }
+
if (ptr->next == NULL)
break;
}
list_head_g = new;
else
ptr->next = new;
-}
+} /* void ps_list_register */
-static procstat_t *ps_list_search (const char *name)
+/* try to match name against entry, returns 1 if success */
+static int ps_list_match (const char *name, const char *cmdline, procstat_t *ps)
{
- procstat_t *ptr;
+#if HAVE_REGEX_H
+ if (ps->re != NULL)
+ {
+ int status;
+ const char *str;
- for (ptr = list_head_g; ptr != NULL; ptr = ptr->next)
- if (strcmp (ptr->name, name) == 0)
- break;
+ str = cmdline;
+ if ((str == NULL) || (str[0] == 0))
+ str = name;
- return (ptr);
-}
+ assert (str != NULL);
+
+ status = regexec (ps->re, str,
+ /* nmatch = */ 0,
+ /* pmatch = */ NULL,
+ /* eflags = */ 0);
+ if (status == 0)
+ return (1);
+ }
+ else
+#endif
+ if (strcmp (ps->name, name) == 0)
+ return (1);
+
+ return (0);
+} /* int ps_list_match */
-static void ps_list_add (const char *name, procstat_entry_t *entry)
+/* add process entry to 'instances' of process 'name' (or refresh it) */
+static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t *entry)
{
procstat_t *ps;
procstat_entry_t *pse;
if (entry->id == 0)
return;
- if ((ps = ps_list_search (name)) == NULL)
- return;
-
- for (pse = ps->instances; pse != NULL; pse = pse->next)
- if ((pse->id == entry->id) || (pse->next == NULL))
- break;
-
- if ((pse == NULL) || (pse->id != entry->id))
+ for (ps = list_head_g; ps != NULL; ps = ps->next)
{
- procstat_entry_t *new;
+ if ((ps_list_match (name, cmdline, ps)) == 0)
+ continue;
- new = (procstat_entry_t *) malloc (sizeof (procstat_entry_t));
- if (new == NULL)
- return;
- memset (new, 0, sizeof (procstat_entry_t));
- new->id = entry->id;
+ for (pse = ps->instances; pse != NULL; pse = pse->next)
+ if ((pse->id == entry->id) || (pse->next == NULL))
+ break;
- if (pse == NULL)
- ps->instances = new;
- else
- pse->next = new;
-
- pse = new;
- }
+ if ((pse == NULL) || (pse->id != entry->id))
+ {
+ procstat_entry_t *new;
+
+ new = (procstat_entry_t *) malloc (sizeof (procstat_entry_t));
+ if (new == NULL)
+ return;
+ memset (new, 0, sizeof (procstat_entry_t));
+ new->id = entry->id;
+
+ if (pse == NULL)
+ ps->instances = new;
+ else
+ pse->next = new;
- pse->age = 0;
- pse->num_proc = entry->num_proc;
- pse->num_lwp = entry->num_lwp;
- pse->vmem_rss = entry->vmem_rss;
+ pse = new;
+ }
- ps->num_proc += pse->num_proc;
- ps->num_lwp += pse->num_lwp;
- ps->vmem_rss += pse->vmem_rss;
+ pse->age = 0;
+ pse->num_proc = entry->num_proc;
+ pse->num_lwp = entry->num_lwp;
+ pse->vmem_rss = entry->vmem_rss;
- if ((entry->vmem_minflt_counter == 0)
- && (entry->vmem_majflt_counter == 0))
- {
- pse->vmem_minflt_counter += entry->vmem_minflt;
- pse->vmem_minflt = entry->vmem_minflt;
+ ps->num_proc += pse->num_proc;
+ ps->num_lwp += pse->num_lwp;
+ ps->vmem_rss += pse->vmem_rss;
- pse->vmem_majflt_counter += entry->vmem_majflt;
- pse->vmem_majflt = entry->vmem_majflt;
- }
- else
- {
- if (entry->vmem_minflt_counter < pse->vmem_minflt_counter)
+ if ((entry->vmem_minflt_counter == 0)
+ && (entry->vmem_majflt_counter == 0))
{
- pse->vmem_minflt = entry->vmem_minflt_counter
- + (ULONG_MAX - pse->vmem_minflt_counter);
- }
- else
- {
- pse->vmem_minflt = entry->vmem_minflt_counter - pse->vmem_minflt_counter;
- }
- pse->vmem_minflt_counter = entry->vmem_minflt_counter;
+ pse->vmem_minflt_counter += entry->vmem_minflt;
+ pse->vmem_minflt = entry->vmem_minflt;
- if (entry->vmem_majflt_counter < pse->vmem_majflt_counter)
- {
- pse->vmem_majflt = entry->vmem_majflt_counter
- + (ULONG_MAX - pse->vmem_majflt_counter);
+ pse->vmem_majflt_counter += entry->vmem_majflt;
+ pse->vmem_majflt = entry->vmem_majflt;
}
else
{
- pse->vmem_majflt = entry->vmem_majflt_counter - pse->vmem_majflt_counter;
+ if (entry->vmem_minflt_counter < pse->vmem_minflt_counter)
+ {
+ pse->vmem_minflt = entry->vmem_minflt_counter
+ + (ULONG_MAX - pse->vmem_minflt_counter);
+ }
+ else
+ {
+ pse->vmem_minflt = entry->vmem_minflt_counter - pse->vmem_minflt_counter;
+ }
+ pse->vmem_minflt_counter = entry->vmem_minflt_counter;
+
+ if (entry->vmem_majflt_counter < pse->vmem_majflt_counter)
+ {
+ pse->vmem_majflt = entry->vmem_majflt_counter
+ + (ULONG_MAX - pse->vmem_majflt_counter);
+ }
+ else
+ {
+ pse->vmem_majflt = entry->vmem_majflt_counter - pse->vmem_majflt_counter;
+ }
+ pse->vmem_majflt_counter = entry->vmem_majflt_counter;
}
- pse->vmem_majflt_counter = entry->vmem_majflt_counter;
- }
-
- ps->vmem_minflt_counter += pse->vmem_minflt;
- ps->vmem_majflt_counter += pse->vmem_majflt;
- if ((entry->cpu_user_counter == 0)
- && (entry->cpu_system_counter == 0))
- {
- pse->cpu_user_counter += entry->cpu_user;
- pse->cpu_user = entry->cpu_user;
+ ps->vmem_minflt_counter += pse->vmem_minflt;
+ ps->vmem_majflt_counter += pse->vmem_majflt;
- pse->cpu_system_counter += entry->cpu_system;
- pse->cpu_system = entry->cpu_system;
- }
- else
- {
- if (entry->cpu_user_counter < pse->cpu_user_counter)
+ if ((entry->cpu_user_counter == 0)
+ && (entry->cpu_system_counter == 0))
{
- pse->cpu_user = entry->cpu_user_counter
- + (ULONG_MAX - pse->cpu_user_counter);
- }
- else
- {
- pse->cpu_user = entry->cpu_user_counter - pse->cpu_user_counter;
- }
- pse->cpu_user_counter = entry->cpu_user_counter;
+ pse->cpu_user_counter += entry->cpu_user;
+ pse->cpu_user = entry->cpu_user;
- if (entry->cpu_system_counter < pse->cpu_system_counter)
- {
- pse->cpu_system = entry->cpu_system_counter
- + (ULONG_MAX - pse->cpu_system_counter);
+ pse->cpu_system_counter += entry->cpu_system;
+ pse->cpu_system = entry->cpu_system;
}
else
{
- pse->cpu_system = entry->cpu_system_counter - pse->cpu_system_counter;
+ if (entry->cpu_user_counter < pse->cpu_user_counter)
+ {
+ pse->cpu_user = entry->cpu_user_counter
+ + (ULONG_MAX - pse->cpu_user_counter);
+ }
+ else
+ {
+ pse->cpu_user = entry->cpu_user_counter - pse->cpu_user_counter;
+ }
+ pse->cpu_user_counter = entry->cpu_user_counter;
+
+ if (entry->cpu_system_counter < pse->cpu_system_counter)
+ {
+ pse->cpu_system = entry->cpu_system_counter
+ + (ULONG_MAX - pse->cpu_system_counter);
+ }
+ else
+ {
+ pse->cpu_system = entry->cpu_system_counter - pse->cpu_system_counter;
+ }
+ pse->cpu_system_counter = entry->cpu_system_counter;
}
- pse->cpu_system_counter = entry->cpu_system_counter;
- }
- ps->cpu_user_counter += pse->cpu_user;
- ps->cpu_system_counter += pse->cpu_system;
+ ps->cpu_user_counter += pse->cpu_user;
+ ps->cpu_system_counter += pse->cpu_system;
+ }
}
+/* remove old entries from instances of processes in list_head_g */
static void ps_list_reset (void)
{
procstat_t *ps;
} /* for (ps = list_head_g; ps != NULL; ps = ps->next) */
}
+/* put all pre-defined 'Process' names from config to list_head_g tree */
static int ps_config (const char *key, const char *value)
{
if (strcasecmp (key, "Process") == 0)
{
- ps_list_register (value);
+ ps_list_register (value, NULL);
+ }
+ else if (strcasecmp (key, "ProcessMatch") == 0)
+ {
+ char *new_val;
+ char *fields[3];
+ int fields_num;
+
+ new_val = strdup (value);
+ if (new_val == NULL)
+ return (1);
+ fields_num = strsplit (new_val, fields,
+ STATIC_ARRAY_SIZE (fields));
+ if (fields_num != 2)
+ {
+ sfree (new_val);
+ return (1);
+ }
+ ps_list_register (fields[0], fields[1]);
+ sfree (new_val);
}
else
{
pagesize_g = sysconf(_SC_PAGESIZE);
DEBUG ("pagesize_g = %li; CONFIG_HZ = %i;",
pagesize_g, CONFIG_HZ);
-#endif /* KERNEL_LINUX */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKVM_GETPROCS
+/* no initialization */
+#endif /* HAVE_LIBKVM_GETPROCS */
return (0);
} /* int ps_init */
+/* submit global state (e.g.: qty of zombies, running, etc..) */
static void ps_submit_state (const char *state, double value)
{
value_t values[1];
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
- strncpy (vl.type_instance, state, sizeof (vl.type_instance));
+ sstrncpy (vl.type, "ps_state", sizeof (vl.type));
+ sstrncpy (vl.type_instance, state, sizeof (vl.type_instance));
- plugin_dispatch_values ("ps_state", &vl);
+ plugin_dispatch_values (&vl);
}
+/* 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];
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
+ sstrncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "ps_rss", sizeof (vl.type));
vl.values[0].gauge = ps->vmem_rss;
vl.values_len = 1;
- plugin_dispatch_values ("ps_rss", &vl);
+ plugin_dispatch_values (&vl);
+ sstrncpy (vl.type, "ps_cputime", sizeof (vl.type));
vl.values[0].counter = ps->cpu_user_counter;
vl.values[1].counter = ps->cpu_system_counter;
vl.values_len = 2;
- plugin_dispatch_values ("ps_cputime", &vl);
+ plugin_dispatch_values (&vl);
+ sstrncpy (vl.type, "ps_count", sizeof (vl.type));
vl.values[0].gauge = ps->num_proc;
vl.values[1].gauge = ps->num_lwp;
vl.values_len = 2;
- plugin_dispatch_values ("ps_count", &vl);
+ plugin_dispatch_values (&vl);
+ sstrncpy (vl.type, "ps_pagefaults", sizeof (vl.type));
vl.values[0].counter = ps->vmem_minflt_counter;
vl.values[1].counter = ps->vmem_majflt_counter;
vl.values_len = 2;
- plugin_dispatch_values ("ps_pagefaults", &vl);
+ plugin_dispatch_values (&vl);
DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; vmem_rss = %lu; "
"vmem_minflt_counter = %lu; vmem_majflt_counter = %lu; "
ps->cpu_user_counter, ps->cpu_system_counter);
} /* void ps_submit_proc_list */
+/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
#if KERNEL_LINUX
static int *ps_read_tasks (int pid)
{
DIR *dh;
struct dirent *ent;
- snprintf (dirname, 64, "/proc/%i/task", pid);
- dirname[63] = '\0';
+ ssnprintf (dirname, sizeof (dirname), "/proc/%i/task", pid);
if ((dh = opendir (dirname)) == NULL)
{
{
char filename[64];
char buffer[1024];
- FILE *fh;
char *fields[64];
char fields_len;
memset (ps, 0, sizeof (procstat_t));
- snprintf (filename, 64, "/proc/%i/stat", pid);
- filename[63] = '\0';
+ ssnprintf (filename, sizeof (filename), "/proc/%i/stat", pid);
- if ((fh = fopen (filename, "r")) == NULL)
+ i = read_file_contents (filename, buffer, sizeof(buffer) - 1);
+ if (i <= 0)
return (-1);
-
- if (fgets (buffer, 1024, fh) == NULL)
- {
- fclose (fh);
- return (-1);
- }
-
- fclose (fh);
+ buffer[i] = 0;
fields_len = strsplit (buffer, fields, 64);
if (fields_len < 24)
@@ -663,7 +784,9 @@ static int mach_get_task_name (task_t t, int *pid, char *name, size_t name_max_l
return (0);
}
#endif /* HAVE_THREAD_INFO */
+/* ------- end of additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
+/* do actual readings from kernel */
static int ps_read (void)
{
#if HAVE_THREAD_INFO
if (mach_get_task_name (task_list[task],
&task_pid,
task_name, PROCSTAT_NAME_LEN) == 0)
- ps = ps_list_search (task_name);
+ {
+ /* search for at least one match */
+ for (ps = list_head_g; ps != NULL; ps = ps->next)
+ /* FIXME: cmdline should be here instead of NULL */
+ if (ps_list_match (task_name, NULL, ps) == 1)
+ break;
+ }
/* Collect more detailed statistics for this process */
if (ps != NULL)
}
if (ps != NULL)
- ps_list_add (task_name, &pse);
+ /* FIXME: cmdline should be here instead of NULL */
+ ps_list_add (task_name, NULL, &pse);
} /* for (task_list) */
if ((status = vm_deallocate (port_task_self,
case 'W': paging++; break;
}
- ps_list_add (ps.name, &pse);
+ /* FIXME: cmdline should be here instead of NULL */
+ ps_list_add (ps.name, NULL, &pse);
}
closedir (proc);
for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
-#endif /* KERNEL_LINUX */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKVM_GETPROCS
+ int running = 0;
+ int sleeping = 0;
+ int zombies = 0;
+ int stopped = 0;
+ int blocked = 0;
+ int idle = 0;
+ int wait = 0;
+
+ kvm_t *kd;
+ char errbuf[1024];
+ char cmdline[ARG_MAX];
+ char *cmdline_ptr;
+ struct kinfo_proc *procs; /* array of processes */
+ char **argv;
+ int count; /* returns number of processes */
+ int i;
+
+ procstat_t *ps_ptr;
+ procstat_entry_t pse;
+
+ ps_list_reset ();
+
+ /* Open the kvm interface, get a descriptor */
+ kd = kvm_open (NULL, NULL, NULL, 0, errbuf);
+ if (kd == NULL)
+ {
+ ERROR ("processes plugin: Cannot open kvm interface: %s",
+ errbuf);
+ return (0);
+ }
+
+ /* Get the list of processes. */
+ procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count);
+ if (procs == NULL)
+ {
+ kvm_close (kd);
+ ERROR ("processes plugin: Cannot get kvm processes list: %s",
+ kvm_geterr(kd));
+ return (0);
+ }
+
+ /* Iterate through the processes in kinfo_proc */
+ for (i = 0; i < count; i++)
+ {
+ /* retrieve the arguments */
+ cmdline[0] = 0;
+ cmdline_ptr = NULL;
+
+ argv = kvm_getargv (kd, (const struct kinfo_proc *) &(procs[i]), 0);
+ if (argv != NULL)
+ {
+ int status;
+ int argc;
+
+ argc = 0;
+ while (argv[argc] != NULL)
+ argc++;
+
+ status = strjoin (cmdline, sizeof (cmdline),
+ argv, argc, " ");
+
+ if (status < 0)
+ {
+ WARNING ("processes plugin: Command line did "
+ "not fit into buffer.");
+ }
+ else
+ {
+ cmdline_ptr = &cmdline[0];
+ }
+ }
+
+ pse.id = procs[i].ki_pid;
+ pse.age = 0;
+
+ pse.num_proc = 1;
+ pse.num_lwp = procs[i].ki_numthreads;
+
+ pse.vmem_rss = procs[i].ki_rssize * getpagesize();
+ pse.vmem_minflt = 0;
+ pse.vmem_minflt_counter = procs[i].ki_rusage.ru_minflt;
+ pse.vmem_majflt = 0;
+ pse.vmem_majflt_counter = procs[i].ki_rusage.ru_majflt;
+
+ pse.cpu_user = 0;
+ pse.cpu_user_counter = procs[i].ki_rusage.ru_utime.tv_sec
+ * 1000
+ + procs[i].ki_rusage.ru_utime.tv_usec;
+ pse.cpu_system = 0;
+ pse.cpu_system_counter = procs[i].ki_rusage.ru_stime.tv_sec
+ * 1000
+ + procs[i].ki_rusage.ru_stime.tv_usec;
+
+ switch (procs[i].ki_stat)
+ {
+ case SSTOP: stopped++; break;
+ case SSLEEP: sleeping++; break;
+ case SRUN: running++; break;
+ case SIDL: idle++; break;
+ case SWAIT: wait++; break;
+ case SLOCK: blocked++; break;
+ case SZOMB: zombies++; break;
+ }
+
+ ps_list_add (procs[i].ki_comm, cmdline_ptr, &pse);
+ }
+
+ kvm_close(kd);
+
+ ps_submit_state ("running", running);
+ ps_submit_state ("sleeping", sleeping);
+ ps_submit_state ("zombies", zombies);
+ ps_submit_state ("stopped", stopped);
+ ps_submit_state ("blocked", blocked);
+ ps_submit_state ("idle", idle);
+ ps_submit_state ("wait", wait);
+
+ for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ ps_submit_proc_list (ps_ptr);
+#endif /* HAVE_LIBKVM_GETPROCS */
return (0);
} /* int ps_read */
diff --git a/src/rrdtool.c b/src/rrdtool.c
index 3b2c54fc9265bb49c05618164af4dc7d8f8ce121..2e1727a888e7d38bc9aca799f70f212ea617dbd2 100644 (file)
--- a/src/rrdtool.c
+++ b/src/rrdtool.c
/**
* collectd - src/rrdtool.c
- * Copyright (C) 2006,2007 Florian octo Forster
+ * Copyright (C) 2006-2008 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
enum
{
FLAG_NONE = 0x00,
- FLAG_QUEUED = 0x01
+ FLAG_QUEUED = 0x01,
+ FLAG_FLUSHQ = 0x02
} flags;
};
typedef struct rrd_cache_s rrd_cache_t;
+enum rrd_queue_dir_e
+{
+ QUEUE_INSERT_FRONT,
+ QUEUE_INSERT_BACK
+};
+typedef enum rrd_queue_dir_e rrd_queue_dir_t;
+
struct rrd_queue_s
{
char *filename;
"HeartBeat",
"RRARows",
"RRATimespan",
- "XFF"
+ "XFF",
+ "WritesPerSecond"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static int heartbeat = 0;
static int rrarows = 1200;
static double xff = 0.1;
+static double write_rate = 0.0;
/* XXX: If you need to lock both, cache_lock and queue_lock, at the same time,
* ALWAYS lock `cache_lock' first! */
static rrd_queue_t *queue_head = NULL;
static rrd_queue_t *queue_tail = NULL;
+static rrd_queue_t *flushq_head = NULL;
+static rrd_queue_t *flushq_tail = NULL;
static pthread_t queue_thread = 0;
static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t queue_cond = PTHREAD_COND_INITIALIZER;
if (rra_num >= rra_max)
break;
- if (snprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
+ if (ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
rra_types[j], xff,
cdp_len, cdp_num) >= sizeof (buffer))
{
sstrncpy (min, "U", sizeof (min));
}
else
- {
- snprintf (min, sizeof (min), "%lf", d->min);
- min[sizeof (min) - 1] = '\0';
- }
+ ssnprintf (min, sizeof (min), "%lf", d->min);
if (isnan (d->max))
{
sstrncpy (max, "U", sizeof (max));
}
else
- {
- snprintf (max, sizeof (max), "%lf", d->max);
- max[sizeof (max) - 1] = '\0';
- }
+ ssnprintf (max, sizeof (max), "%lf", d->max);
- status = snprintf (buffer, sizeof (buffer),
+ status = ssnprintf (buffer, sizeof (buffer),
"DS:%s:%s:%i:%s:%s",
d->name, type,
(heartbeat > 0) ? heartbeat : (2 * vl->interval),
#if HAVE_THREADSAFE_LIBRRD
static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
- int argc, char **argv)
+ int argc, const char **argv)
{
int status;
return (status);
} /* int srrd_create */
-static int srrd_update (char *filename, char *template, int argc, char **argv)
+static int srrd_update (char *filename, char *template,
+ int argc, const char **argv)
{
int status;
#else /* !HAVE_THREADSAFE_LIBRRD */
static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
- int argc, char **argv)
+ int argc, const char **argv)
{
int status;
@@ -395,10 +402,8 @@ static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
if (last_up == 0)
last_up = time (NULL) - 10;
- snprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
- pdp_step_str[sizeof (pdp_step_str) - 1] = '\0';
- snprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
- last_up_str[sizeof (last_up_str) - 1] = '\0';
+ ssnprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
+ ssnprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
new_argv[0] = "create";
new_argv[1] = filename;
return (status);
} /* int srrd_create */
-static int srrd_update (char *filename, char *template, int argc, char **argv)
+static int srrd_update (char *filename, char *template,
+ int argc, const char **argv)
{
int status;
@@ -513,7 +519,7 @@ static int rrd_create_file (char *filename, const data_set_t *ds, const value_li
status = srrd_create (filename,
(stepsize > 0) ? stepsize : vl->interval,
vl->time - 10,
- argc, argv);
+ argc, (const char **)argv);
free (argv);
ds_free (ds_num, ds_def);
memset (buffer, '\0', buffer_len);
- status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
+ status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
if ((status < 1) || (status >= buffer_len))
return (-1);
offset = status;
return (-1);
if (ds->ds[i].type == DS_TYPE_COUNTER)
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
":%llu", vl->values[i].counter);
else
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
":%lf", vl->values[i].gauge);
if ((status < 1) || (status >= (buffer_len - offset)))
if (datadir != NULL)
{
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
"%s/", datadir);
if ((status < 1) || (status >= buffer_len - offset))
return (-1);
offset += status;
}
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
"%s/", vl->host);
if ((status < 1) || (status >= buffer_len - offset))
return (-1);
offset += status;
if (strlen (vl->plugin_instance) > 0)
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
"%s-%s/", vl->plugin, vl->plugin_instance);
else
- status = snprintf (buffer + offset, buffer_len - offset,
+ status = ssnprintf (buffer + offset, buffer_len - offset,
"%s/", vl->plugin);
if ((status < 1) || (status >= buffer_len - offset))
return (-1);
offset += status;
if (strlen (vl->type_instance) > 0)
- status = snprintf (buffer + offset, buffer_len - offset,
- "%s-%s.rrd", ds->type, vl->type_instance);
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s-%s.rrd", vl->type, vl->type_instance);
else
- status = snprintf (buffer + offset, buffer_len - offset,
- "%s.rrd", ds->type);
+ status = ssnprintf (buffer + offset, buffer_len - offset,
+ "%s.rrd", vl->type);
if ((status < 1) || (status >= buffer_len - offset))
return (-1);
offset += status;
static void *rrd_queue_thread (void *data)
{
+ struct timeval tv_next_update;
+ struct timeval tv_now;
+
+ gettimeofday (&tv_next_update, /* timezone = */ NULL);
+
while (42)
{
rrd_queue_t *queue_entry;
int values_num;
int i;
- /* XXX: If you need to lock both, cache_lock and queue_lock, at
- * the same time, ALWAYS lock `cache_lock' first! */
-
- /* wait until an entry is available */
- pthread_mutex_lock (&queue_lock);
- while ((queue_head == NULL) && (do_shutdown == 0))
- pthread_cond_wait (&queue_cond, &queue_lock);
-
- /* We're in the shutdown phase */
- if (queue_head == NULL)
- {
- pthread_mutex_unlock (&queue_lock);
- break;
- }
-
- /* Dequeue the first entry */
- queue_entry = queue_head;
- if (queue_head == queue_tail)
- queue_head = queue_tail = NULL;
- else
- queue_head = queue_head->next;
+ pthread_mutex_lock (&queue_lock);
+ /* Wait for values to arrive */
+ while (true)
+ {
+ struct timespec ts_wait;
+ int status;
+
+ while ((flushq_head == NULL) && (queue_head == NULL)
+ && (do_shutdown == 0))
+ pthread_cond_wait (&queue_cond, &queue_lock);
+
+ if ((flushq_head == NULL) && (queue_head == NULL))
+ break;
+
+ /* Don't delay if there's something to flush */
+ if (flushq_head != NULL)
+ break;
+
+ /* Don't delay if we're shutting down */
+ if (do_shutdown != 0)
+ break;
+
+ /* Don't delay if no delay was configured. */
+ if (write_rate <= 0.0)
+ break;
+
+ gettimeofday (&tv_now, /* timezone = */ NULL);
+ status = timeval_sub_timespec (&tv_next_update, &tv_now,
+ &ts_wait);
+ /* We're good to go */
+ if (status != 0)
+ break;
+
+ /* We're supposed to wait a bit with this update, so we'll
+ * wait for the next addition to the queue or to the end of
+ * the wait period - whichever comes first. */
+ ts_wait.tv_sec = tv_next_update.tv_sec;
+ ts_wait.tv_nsec = 1000 * tv_next_update.tv_usec;
+
+ status = pthread_cond_timedwait (&queue_cond, &queue_lock,
+ &ts_wait);
+ if (status == ETIMEDOUT)
+ break;
+ } /* while (true) */
+
+ /* XXX: If you need to lock both, cache_lock and queue_lock, at
+ * the same time, ALWAYS lock `cache_lock' first! */
+
+ /* We're in the shutdown phase */
+ if ((flushq_head == NULL) && (queue_head == NULL))
+ {
+ pthread_mutex_unlock (&queue_lock);
+ break;
+ }
+
+ if (flushq_head != NULL)
+ {
+ /* Dequeue the first flush entry */
+ queue_entry = flushq_head;
+ if (flushq_head == flushq_tail)
+ flushq_head = flushq_tail = NULL;
+ else
+ flushq_head = flushq_head->next;
+ }
+ else /* if (queue_head != NULL) */
+ {
+ /* Dequeue the first regular entry */
+ queue_entry = queue_head;
+ if (queue_head == queue_tail)
+ queue_head = queue_tail = NULL;
+ else
+ queue_head = queue_head->next;
+ }
/* Unlock the queue again */
pthread_mutex_unlock (&queue_lock);
pthread_mutex_unlock (&cache_lock);
+ /* Update `tv_next_update' */
+ if (write_rate > 0.0)
+ {
+ gettimeofday (&tv_now, /* timezone = */ NULL);
+ tv_next_update.tv_sec = tv_now.tv_sec;
+ tv_next_update.tv_usec = tv_now.tv_usec
+ + ((suseconds_t) (1000000 * write_rate));
+ while (tv_next_update.tv_usec > 1000000)
+ {
+ tv_next_update.tv_sec++;
+ tv_next_update.tv_usec -= 1000000;
+ }
+ }
+
/* Write the values to the RRD-file */
- srrd_update (queue_entry->filename, NULL, values_num, values);
+ srrd_update (queue_entry->filename, NULL,
+ values_num, (const char **)values);
DEBUG ("rrdtool plugin: queue thread: Wrote %i values to %s",
values_num, queue_entry->filename);
return ((void *) 0);
} /* void *rrd_queue_thread */
-static int rrd_queue_cache_entry (const char *filename)
+static int rrd_queue_enqueue (const char *filename,
+ rrd_queue_t **head, rrd_queue_t **tail)
{
- rrd_queue_t *queue_entry;
+ rrd_queue_t *queue_entry;
- queue_entry = (rrd_queue_t *) malloc (sizeof (rrd_queue_t));
- if (queue_entry == NULL)
- return (-1);
+ queue_entry = (rrd_queue_t *) malloc (sizeof (rrd_queue_t));
+ if (queue_entry == NULL)
+ return (-1);
- queue_entry->filename = strdup (filename);
- if (queue_entry->filename == NULL)
- {
- free (queue_entry);
- return (-1);
- }
+ queue_entry->filename = strdup (filename);
+ if (queue_entry->filename == NULL)
+ {
+ free (queue_entry);
+ return (-1);
+ }
- queue_entry->next = NULL;
+ queue_entry->next = NULL;
- pthread_mutex_lock (&queue_lock);
- if (queue_tail == NULL)
- queue_head = queue_entry;
- else
- queue_tail->next = queue_entry;
- queue_tail = queue_entry;
- pthread_cond_signal (&queue_cond);
- pthread_mutex_unlock (&queue_lock);
+ pthread_mutex_lock (&queue_lock);
- DEBUG ("rrdtool plugin: Put `%s' into the update queue", filename);
+ if (*tail == NULL)
+ *head = queue_entry;
+ else
+ (*tail)->next = queue_entry;
+ *tail = queue_entry;
- return (0);
-} /* int rrd_queue_cache_entry */
+ pthread_cond_signal (&queue_cond);
+ pthread_mutex_unlock (&queue_lock);
+
+ return (0);
+} /* int rrd_queue_enqueue */
+
+static int rrd_queue_dequeue (const char *filename,
+ rrd_queue_t **head, rrd_queue_t **tail)
+{
+ rrd_queue_t *this;
+ rrd_queue_t *prev;
+
+ pthread_mutex_lock (&queue_lock);
+
+ prev = NULL;
+ this = *head;
+
+ while (this != NULL)
+ {
+ if (strcmp (this->filename, filename) == 0)
+ break;
+
+ prev = this;
+ this = this->next;
+ }
+
+ if (this == NULL)
+ {
+ pthread_mutex_unlock (&queue_lock);
+ return (-1);
+ }
+
+ if (prev == NULL)
+ *head = this->next;
+ else
+ prev->next = this->next;
+
+ if (this->next == NULL)
+ *tail = prev;
+
+ pthread_mutex_unlock (&queue_lock);
+
+ sfree (this->filename);
+ sfree (this);
+
+ return (0);
+} /* int rrd_queue_dequeue */
static void rrd_cache_flush (int timeout)
{
iter = c_avl_get_iterator (cache);
while (c_avl_iterator_next (iter, (void *) &key, (void *) &rc) == 0)
{
- if (rc->flags == FLAG_QUEUED)
+ if (rc->flags != FLAG_NONE)
continue;
else if ((now - rc->first_value) < timeout)
continue;
else if (rc->values_num > 0)
{
- if (rrd_queue_cache_entry (key) == 0)
+ int status;
+
+ status = rrd_queue_enqueue (key, &queue_head, &queue_tail);
+ if (status == 0)
rc->flags = FLAG_QUEUED;
}
else /* ancient and no values -> waste of memory */
cache_flush_last = now;
} /* void rrd_cache_flush */
+static int rrd_cache_flush_identifier (int timeout, const char *identifier)
+{
+ rrd_cache_t *rc;
+ time_t now;
+ int status;
+ char key[2048];
+
+ if (identifier == NULL)
+ {
+ rrd_cache_flush (timeout);
+ return (0);
+ }
+
+ now = time (NULL);
+
+ if (datadir == NULL)
+ snprintf (key, sizeof (key), "%s.rrd",
+ identifier);
+ else
+ snprintf (key, sizeof (key), "%s/%s.rrd",
+ datadir, identifier);
+ key[sizeof (key) - 1] = 0;
+
+ status = c_avl_get (cache, key, (void *) &rc);
+ if (status != 0)
+ {
+ WARNING ("rrdtool plugin: rrd_cache_flush_identifier: "
+ "c_avl_get (%s) failed. Does that file really exist?",
+ key);
+ return (status);
+ }
+
+ if (rc->flags == FLAG_FLUSHQ)
+ {
+ status = 0;
+ }
+ else if (rc->flags == FLAG_QUEUED)
+ {
+ rrd_queue_dequeue (key, &queue_head, &queue_tail);
+ status = rrd_queue_enqueue (key, &flushq_head, &flushq_tail);
+ if (status == 0)
+ rc->flags = FLAG_FLUSHQ;
+ }
+ else if ((now - rc->first_value) < timeout)
+ {
+ status = 0;
+ }
+ else if (rc->values_num > 0)
+ {
+ status = rrd_queue_enqueue (key, &flushq_head, &flushq_tail);
+ if (status == 0)
+ rc->flags = FLAG_FLUSHQ;
+ }
+
+ return (status);
+} /* int rrd_cache_flush_identifier */
+
static int rrd_cache_insert (const char *filename,
const char *value, time_t value_time)
{
}
DEBUG ("rrdtool plugin: rrd_cache_insert: file = %s; "
- "values_num = %i; age = %u;",
+ "values_num = %i; age = %lu;",
filename, rc->values_num,
- rc->last_value - rc->first_value);
+ (unsigned long)(rc->last_value - rc->first_value));
if ((rc->last_value - rc->first_value) >= cache_timeout)
{
/* XXX: If you need to lock both, cache_lock and queue_lock, at
* the same time, ALWAYS lock `cache_lock' first! */
- if (rc->flags != FLAG_QUEUED)
+ if (rc->flags == FLAG_NONE)
{
- if (rrd_queue_cache_entry (filename) == 0)
+ int status;
+
+ status = rrd_queue_enqueue (filename, &queue_head, &queue_tail);
+ if (status == 0)
rc->flags = FLAG_QUEUED;
}
else
((time (NULL) - cache_flush_last) > cache_flush_timeout))
rrd_cache_flush (cache_flush_timeout);
-
pthread_mutex_unlock (&cache_lock);
return (0);
char values[512];
int status;
+ if (0 != strcmp (ds->type, vl->type)) {
+ ERROR ("rrdtool plugin: DS type does not match value list type");
+ return -1;
+ }
+
if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
return (-1);
return (status);
} /* int rrd_write */
-static int rrd_flush (const int timeout)
+static int rrd_flush (int timeout, const char *identifier)
{
pthread_mutex_lock (&cache_lock);
return (0);
}
- rrd_cache_flush (timeout);
+ rrd_cache_flush_identifier (timeout, identifier);
+
pthread_mutex_unlock (&cache_lock);
return (0);
} /* int rrd_flush */
}
xff = tmp;
}
+ else if (strcasecmp ("WritesPerSecond", key) == 0)
+ {
+ double wps = atof (value);
+
+ if (wps < 0.0)
+ {
+ fprintf (stderr, "rrdtool: `WritesPerSecond' must be "
+ "greater than or equal to zero.");
+ return (1);
+ }
+ else if (wps == 0.0)
+ {
+ write_rate = 0.0;
+ }
+ else
+ {
+ write_rate = 1.0 / wps;
+ }
+ }
else
{
return (-1);
diff --git a/src/sensors.c b/src/sensors.c
index 0968e311fb170c63ba8c01727ed8ea7e423bf733..5ed82a8c64836cf08e881743343877f04391d575 100644 (file)
--- a/src/sensors.c
+++ b/src/sensors.c
if (chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
{
- status = snprintf (buf, buf_size,
+ status = ssnprintf (buf, buf_size,
"%s-isa-%04x",
chip->prefix,
chip->addr);
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (match_key, sizeof (match_key), "%s/%s-%s",
+ status = ssnprintf (match_key, sizeof (match_key), "%s/%s-%s",
plugin_instance, type, type_instance);
if (status < 1)
return;
- match_key[sizeof (match_key) - 1] = '\0';
if (sensor_list != NULL)
{
vl.values_len = 1;
vl.time = time (NULL);
- strncpy (vl.host, hostname_g, sizeof (vl.host));
- vl.host[sizeof (vl.host) - 1] = '\0';
- strncpy (vl.plugin, "sensors", sizeof (vl.plugin));
- vl.plugin[sizeof (vl.plugin) - 1] = '\0';
- strncpy (vl.plugin_instance, plugin_instance,
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "sensors", sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
- vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void sensors_submit */
static int sensors_read (void)
sizeof (plugin_instance), fl->chip);
if (status < 0)
continue;
- plugin_instance[sizeof (plugin_instance) - 1] = '\0';
- strncpy (type_instance, fl->data->name,
+ sstrncpy (type_instance, fl->data->name,
sizeof (type_instance));
- type_instance[sizeof (type_instance) - 1] = '\0';
sensors_submit (plugin_instance,
sensor_type_name_map[fl->type],
sizeof (plugin_instance), fl->chip);
if (status < 0)
continue;
- plugin_instance[sizeof (plugin_instance) - 1] = '\0';
- strncpy (type_instance, fl->feature->name,
+ sstrncpy (type_instance, fl->feature->name,
sizeof (type_instance));
- type_instance[sizeof (type_instance) - 1] = '\0';
if (fl->feature->type == SENSORS_FEATURE_IN)
type = "voltage";
diff --git a/src/serial.c b/src/serial.c
index 4f08a346eb542fee24e84d3f4918fcc73552a4fb..1c874e52177e919d59056126015da12edf760109 100644 (file)
--- a/src/serial.c
+++ b/src/serial.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "serial", sizeof (vl.plugin));
- strncpy (vl.type_instance, type_instance,
+ sstrncpy (vl.type, "serial_octets", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance,
sizeof (vl.type_instance));
- plugin_dispatch_values ("serial_octets", &vl);
+ plugin_dispatch_values (&vl);
}
static int serial_read (void)
diff --git a/src/snmp.c b/src/snmp.c
index 408defa9b4ea385336d66d429d10560422fb6b59..4d6e76947a37ef983c7180debff49dfc1c25f6c0 100644 (file)
--- a/src/snmp.c
+++ b/src/snmp.c
@@ -198,7 +198,8 @@ static int csnmp_config_add_data_instance (data_definition_t *dd, oconfig_item_t
else
{
/* Instance is a simple string */
- strncpy (dd->instance.string, ci->values[0].value.string, DATA_MAX_NAME_LEN - 1);
+ sstrncpy (dd->instance.string, ci->values[0].value.string,
+ sizeof (dd->instance.string));
}
return (0);
temp += (uint32_t) vl->val.counter64->low;
DEBUG ("snmp plugin: Parsed int64 value is %"PRIu64".", temp);
}
+ else if (vl->type == ASN_OCTET_STR)
+ {
+ /* We'll handle this later.. */
+ }
else
{
WARNING ("snmp plugin: I don't know the ASN type `%i'", (int) vl->type);
defined = 0;
}
- if (type == DS_TYPE_COUNTER)
+ if (vl->type == ASN_OCTET_STR)
+ {
+ char *endptr;
+
+ endptr = NULL;
+ if (vl->val.string != NULL)
+ {
+ char string[64];
+ size_t string_length;
+
+ string_length = sizeof (string) - 1;
+ if (vl->val_len < string_length)
+ string_length = vl->val_len;
+
+ /* The strings we get from the Net-SNMP library may not be null
+ * terminated. That is why we're using `membpy' here and not `strcpy'.
+ * `string_length' is set to `vl->val_len' which holds the length of the
+ * string. -octo */
+ memcpy (string, vl->val.string, string_length);
+ string[string_length] = 0;
+
+ if (type == DS_TYPE_COUNTER)
+ {
+ ret.counter = (counter_t) strtoll (string, &endptr, /* base = */ 0);
+ DEBUG ("snmp plugin: csnmp_value_list_to_value: String to counter: %s -> %llu",
+ string, (unsigned long long) ret.counter);
+ }
+ else if (type == DS_TYPE_GAUGE)
+ {
+ ret.gauge = (gauge_t) strtod (string, &endptr);
+ DEBUG ("snmp plugin: csnmp_value_list_to_value: String to gauge: %s -> %g",
+ string, (double) ret.gauge);
+ }
+ }
+
+ /* Check if an error occurred */
+ if ((vl->val.string == NULL) || (endptr == (char *) vl->val.string))
+ {
+ if (type == DS_TYPE_COUNTER)
+ ret.counter = 0;
+ else if (type == DS_TYPE_GAUGE)
+ ret.gauge = NAN;
+ }
+ }
+ else if (type == DS_TYPE_COUNTER)
{
ret.counter = temp;
}
char *ptr;
size_t instance_len;
+ memset (il->instance, 0, sizeof (il->instance));
instance_len = sizeof (il->instance) - 1;
if (instance_len > vb->val_len)
instance_len = vb->val_len;
- strncpy (il->instance, (char *) ((vb->type == ASN_OCTET_STR)
+ sstrncpy (il->instance, (char *) ((vb->type == ASN_OCTET_STR)
? vb->val.string
: vb->val.bitstring),
- instance_len);
- il->instance[instance_len] = '\0';
+ instance_len + 1);
for (ptr = il->instance; *ptr != '\0'; ptr++)
{
else
{
value_t val = csnmp_value_list_to_value (vb, DS_TYPE_COUNTER, 1.0, 0.0);
- snprintf (il->instance, sizeof (il->instance),
+ ssnprintf (il->instance, sizeof (il->instance),
"%llu", val.counter);
}
- il->instance[sizeof (il->instance) - 1] = '\0';
/* TODO: Debugging output */
@@ -907,8 +955,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
return (-1);
}
- strncpy (vl.host, host->name, sizeof (vl.host));
- vl.host[sizeof (vl.host) - 1] = '\0';
+ sstrncpy (vl.host, host->name, sizeof (vl.host));
sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin));
vl.interval = host->interval;
@@ -972,30 +1019,28 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
|| (instance_list_ptr->subid == value_table_ptr[0]->subid));
#endif
+ sstrncpy (vl.type, data->type, sizeof (vl.type));
+
{
char temp[DATA_MAX_NAME_LEN];
if (instance_list_ptr == NULL)
- snprintf (temp, sizeof (temp), "%u",
- (uint32_t) subid);
+ ssnprintf (temp, sizeof (temp), "%u", (uint32_t) subid);
else
- strncpy (temp, instance_list_ptr->instance,
- sizeof (temp));
- temp[sizeof (temp) - 1] = '\0';
+ sstrncpy (temp, instance_list_ptr->instance, sizeof (temp));
if (data->instance_prefix == NULL)
- strncpy (vl.type_instance, temp, sizeof (vl.type_instance));
+ sstrncpy (vl.type_instance, temp, sizeof (vl.type_instance));
else
- snprintf (vl.type_instance, sizeof (vl.type_instance), "%s%s",
+ ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s%s",
data->instance_prefix, temp);
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
}
for (i = 0; i < data->values_len; i++)
vl.values[i] = value_table_ptr[i]->value;
/* If we get here `vl.type_instance' and all `vl.values' have been set */
- plugin_dispatch_values (data->type, &vl);
+ plugin_dispatch_values (&vl);
subid++;
} /* while (have_more != 0) */
@@ -1292,11 +1337,10 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
vl.values[i].gauge = NAN;
}
- strncpy (vl.host, host->name, sizeof (vl.host));
- vl.host[sizeof (vl.host) - 1] = '\0';
+ sstrncpy (vl.host, host->name, sizeof (vl.host));
sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin));
- strncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+ sstrncpy (vl.type, data->type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance));
vl.interval = host->interval;
@@ -1354,8 +1398,8 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
snmp_free_pdu (res);
res = NULL;
- DEBUG ("snmp plugin: -> plugin_dispatch_values (%s, &vl);", data->type);
- plugin_dispatch_values (data->type, &vl);
+ DEBUG ("snmp plugin: -> plugin_dispatch_values (&vl);");
+ plugin_dispatch_values (&vl);
sfree (vl.values);
return (0);
diff --git a/src/swap.c b/src/swap.c
index 7fa72dc92458ae6d2993cd897eaeb1110a599990..8c09e35f2f0246b43877b5fefd3d3062e6cd512f 100644 (file)
--- a/src/swap.c
+++ b/src/swap.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type, "swap", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values ("swap", &vl);
+ plugin_dispatch_values (&vl);
} /* void swap_submit */
static int swap_read (void)
diff --git a/src/tape.c b/src/tape.c
index 5b5cdb4641d9d176599e689c195d8d36d923b113..caca537b0038be024f2771d979f3eeeb289ce53d 100644 (file)
--- a/src/tape.c
+++ b/src/tape.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "tape", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, plugin_instance,
+ sstrncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void tape_submit */
static int tape_read (void)
diff --git a/src/tcpconns.c b/src/tcpconns.c
index 2e1159229da7c3d67b32a18133839e9aea019be2..d39a6c32d4e1ce828e9f6de516f3999b7124b220 100644 (file)
--- a/src/tcpconns.c
+++ b/src/tcpconns.c
* Florian octo Forster <octo at verplant.org>
**/
+/**
+ * Code within `HAVE_LIBKVM_NLIST' blocks is provided under the following
+ * license:
+ *
+ * $collectd: parts of tcpconns.c, 2008/08/08 03:48:30 Michael Stapelberg $
+ * $OpenBSD: inet.c,v 1.100 2007/06/19 05:28:30 ray Exp $
+ * $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $
+ *
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
#include "collectd.h"
#include "common.h"
#include "plugin.h"
-#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME
+#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !HAVE_LIBKVM_NLIST
# error "No applicable input method."
#endif
# include <netinet/tcpip.h>
# include <netinet/tcp_seq.h>
# include <netinet/tcp_var.h>
-#endif /* HAVE_SYSCTLBYNAME */
+/* #endif HAVE_SYSCTLBYNAME */
+
+/* This is for OpenBSD and possibly NetBSD. */
+#elif HAVE_LIBKVM_NLIST
+# include <sys/queue.h>
+# include <sys/socket.h>
+# include <net/route.h>
+# include <netinet/in.h>
+# include <netinet/in_systm.h>
+# include <netinet/ip.h>
+# include <netinet/in_pcb.h>
+# include <netinet/tcp.h>
+# include <netinet/tcp_timer.h>
+# include <netinet/tcp_var.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+# include <nlist.h>
+# include <kvm.h>
+#endif /* HAVE_LIBKVM_NLIST */
#if KERNEL_LINUX
static const char *tcp_state[] =
# define TCP_STATE_LISTEN 1
# define TCP_STATE_MIN 0
# define TCP_STATE_MAX 10
-#endif /* HAVE_SYSCTLBYNAME */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif HAVE_LIBKVM_NLIST
+static const char *tcp_state[] =
+{
+ "CLOSED",
+ "LISTEN",
+ "SYN_SENT",
+ "SYN_RECV",
+ "ESTABLISHED",
+ "CLOSE_WAIT",
+ "FIN_WAIT1",
+ "CLOSING",
+ "LAST_ACK",
+ "FIN_WAIT2",
+ "TIME_WAIT"
+};
+
+static kvm_t *kvmd;
+static u_long inpcbtable_off = 0;
+struct inpcbtable *inpcbtable_ptr = NULL;
+
+# define TCP_STATE_LISTEN 1
+# define TCP_STATE_MIN 1
+# define TCP_STATE_MAX 10
+#endif /* HAVE_LIBKVM_NLIST */
#define PORT_COLLECT_LOCAL 0x01
#define PORT_COLLECT_REMOTE 0x02
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "tcpconns", sizeof (vl.plugin));
+ sstrncpy (vl.type, "tcp_connections", sizeof (vl.type));
if (((port_collect_listening != 0) && (pe->flags & PORT_IS_LISTENING))
|| (pe->flags & PORT_COLLECT_LOCAL))
{
- snprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
"%"PRIu16"-local", pe->port);
- vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
for (i = 1; i <= TCP_STATE_MAX; i++)
{
vl.values[0].gauge = pe->count_local[i];
- strncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+ sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
- plugin_dispatch_values ("tcp_connections", &vl);
+ plugin_dispatch_values (&vl);
}
}
if (pe->flags & PORT_COLLECT_REMOTE)
{
- snprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
"%"PRIu16"-remote", pe->port);
- vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
for (i = 1; i <= TCP_STATE_MAX; i++)
{
vl.values[0].gauge = pe->count_remote[i];
- strncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+ sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
- plugin_dispatch_values ("tcp_connections", &vl);
+ plugin_dispatch_values (&vl);
}
}
} /* void conn_submit */
/* #endif KERNEL_LINUX */
#elif HAVE_SYSCTLBYNAME
-#endif /* HAVE_SYSCTLBYNAME */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif HAVE_LIBKVM_NLIST
+#endif /* HAVE_LIBKVM_NLIST */
static int conn_config (const char *key, const char *value)
{
return (0);
} /* int conn_read */
-#endif /* HAVE_SYSCTLBYNAME */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif HAVE_LIBKVM_NLIST
+static int kread (u_long addr, void *buf, int size)
+{
+ int status;
+
+ status = kvm_read (kvmd, addr, buf, size);
+ if (status != size)
+ {
+ ERROR ("tcpconns plugin: kvm_read failed (got %i, expected %i): %s\n",
+ status, size, kvm_geterr (kvmd));
+ return (-1);
+ }
+ return (0);
+} /* int kread */
+
+static int conn_init (void)
+{
+ char buf[_POSIX2_LINE_MAX];
+ struct nlist nl[] =
+ {
+#define N_TCBTABLE 0
+ { "_tcbtable" },
+ { "" }
+ };
+ int status;
+
+ kvmd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, buf);
+ if (kvmd == NULL)
+ {
+ ERROR ("tcpconns plugin: kvm_openfiles failed: %s", buf);
+ return (-1);
+ }
+
+ status = kvm_nlist (kvmd, nl);
+ if (status < 0)
+ {
+ ERROR ("tcpconns plugin: kvm_nlist failed with status %i.", status);
+ return (-1);
+ }
+
+ if (nl[N_TCBTABLE].n_type == 0)
+ {
+ ERROR ("tcpconns plugin: Error looking up kernel's namelist: "
+ "N_TCBTABLE is invalid.");
+ return (-1);
+ }
+
+ inpcbtable_off = (u_long) nl[N_TCBTABLE].n_value;
+ inpcbtable_ptr = (struct inpcbtable *) nl[N_TCBTABLE].n_value;
+
+ return (0);
+} /* int conn_init */
+
+static int conn_read (void)
+{
+ struct inpcbtable table;
+ struct inpcb *head;
+ struct inpcb *next;
+ struct inpcb inpcb;
+ struct tcpcb tcpcb;
+ int status;
+
+ conn_reset_port_entry ();
+
+ /* Read the pcbtable from the kernel */
+ status = kread (inpcbtable_off, &table, sizeof (table));
+ if (status != 0)
+ return (-1);
+
+ /* Get the `head' pcb */
+ head = (struct inpcb *) &(inpcbtable_ptr->inpt_queue);
+ /* Get the first pcb */
+ next = CIRCLEQ_FIRST (&table.inpt_queue);
+
+ while (next != head)
+ {
+ /* Read the pcb pointed to by `next' into `inpcb' */
+ kread ((u_long) next, &inpcb, sizeof (inpcb));
+
+ /* Advance `next' */
+ next = CIRCLEQ_NEXT (&inpcb, inp_queue);
+
+ /* Ignore sockets, that are not connected. */
+ if (!(inpcb.inp_flags & INP_IPV6)
+ && (inet_lnaof(inpcb.inp_laddr) == INADDR_ANY))
+ continue;
+ if ((inpcb.inp_flags & INP_IPV6)
+ && IN6_IS_ADDR_UNSPECIFIED (&inpcb.inp_laddr6))
+ continue;
+
+ kread ((u_long) inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
+ conn_handle_ports (ntohs(inpcb.inp_lport), ntohs(inpcb.inp_fport), tcpcb.t_state);
+ } /* while (next != head) */
+
+ conn_submit_all ();
+
+ return (0);
+}
+#endif /* HAVE_LIBKVM_NLIST */
void module_register (void)
{
config_keys, config_keys_num);
#if KERNEL_LINUX
plugin_register_init ("tcpconns", conn_init);
+#elif HAVE_SYSCTLBYNAME
+ /* no initialization */
+#elif HAVE_LIBKVM_NLIST
+ plugin_register_init ("tcpconns", conn_init);
#endif
plugin_register_read ("tcpconns", conn_read);
} /* void module_register */
/*
- * vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
+ * vim: set shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker :
*/
diff --git a/src/teamspeak2.c b/src/teamspeak2.c
index 52a1007ed4fcddd300955d3dbd55c40268830e53..5cd427afc2bb5ccb0c173d8791401e51fe682707 100644 (file)
--- a/src/teamspeak2.c
+++ b/src/teamspeak2.c
if (plugin_instance != NULL)
sstrncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
-
+
+ sstrncpy (vl.type, type, sizeof (vl.type));
+
if (type_instance != NULL)
sstrncpy (vl.type_instance, type_instance,
sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void tss2_submit_gauge */
static void tss2_submit_io (const char *plugin_instance, const char *type,
if (plugin_instance != NULL)
sstrncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
-
- plugin_dispatch_values (type, &vl);
+
+ sstrncpy (vl.type, type, sizeof (vl.type));
+
+ plugin_dispatch_values (&vl);
} /* void tss2_submit_gauge */
static void tss2_close_socket (void)
@@ -372,8 +376,7 @@ static int tss2_select_vserver (FILE *read_fh, FILE *write_fh, vserver_list_t *v
int status;
/* Send request */
- snprintf (command, sizeof (command), "sel %i\r\n", vserver->port);
- command[sizeof (command) - 1] = 0;
+ ssnprintf (command, sizeof (command), "sel %i\r\n", vserver->port);
status = tss2_send_request (write_fh, command);
if (status != 0)
else
{
/* Request server information */
- snprintf (plugin_instance, sizeof (plugin_instance), "vserver%i",
+ ssnprintf (plugin_instance, sizeof (plugin_instance), "vserver%i",
vserver->port);
- plugin_instance[sizeof (plugin_instance) - 1] = 0;
/* Select the server */
status = tss2_select_vserver (read_fh, write_fh, vserver);
diff --git a/src/thermal.c b/src/thermal.c
--- /dev/null
+++ b/src/thermal.c
@@ -0,0 +1,272 @@
+/**
+ * collectd - src/thermal.c
+ * Copyright (C) 2008 Michał Mirosław
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Michał Mirosław <mirq-linux at rere.qmqm.pl>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_ignorelist.h"
+
+#if !KERNEL_LINUX
+# error "This module is for Linux only."
+#endif
+
+const char *const dirname_sysfs = "/sys/class/thermal";
+const char *const dirname_procfs = "/proc/acpi/thermal_zone";
+
+static char force_procfs = 0;
+static ignorelist_t *device_list;
+static value_list_t vl_temp_template = VALUE_LIST_STATIC;
+static value_list_t vl_state_template = VALUE_LIST_STATIC;
+
+enum dev_type {
+ TEMP = 0,
+ COOLING_DEV
+};
+
+static void thermal_submit (const char *plugin_instance, enum dev_type dt,
+ gauge_t value)
+{
+ value_list_t vl = (dt == TEMP) ? vl_temp_template : vl_state_template;
+ value_t vt;
+
+ vt.gauge = value;
+
+ vl.values = &vt;
+ vl.time = time (NULL);
+ sstrncpy (vl.plugin, "thermal", sizeof(vl.plugin));
+ sstrncpy (vl.plugin_instance, plugin_instance,
+ sizeof(vl.plugin_instance));
+ sstrncpy (vl.type, (dt == TEMP) ? "temperature" : "gauge",
+ sizeof (vl.type));
+
+ plugin_dispatch_values (&vl);
+}
+
+static int thermal_sysfs_device_read (const char *dir, const char *name,
+ void *user_data)
+{
+ char filename[256];
+ char data[1024];
+ int len;
+ int ok = 0;
+
+ if (device_list && ignorelist_match (device_list, name))
+ return -1;
+
+ len = snprintf (filename, sizeof (filename), "%s/%s/temp", dirname_sysfs, name);
+ if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
+ return -1;
+
+ len = 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);
+ ++ok;
+ }
+ }
+
+ len = snprintf (filename, sizeof (filename), "%s/%s/cur_state", dirname_sysfs, name);
+ if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
+ return -1;
+
+ len = 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);
+ ++ok;
+ }
+ }
+
+ return ok ? 0 : -1;
+}
+
+static int thermal_procfs_device_read (const char *dir, const char *name,
+ void *user_data)
+{
+ const char str_temp[] = "temperature:";
+ char filename[256];
+ char data[1024];
+ int len;
+
+ if (device_list && ignorelist_match (device_list, name))
+ return -1;
+
+ /**
+ * rechot ~ # cat /proc/acpi/thermal_zone/THRM/temperature
+ * temperature: 55 C
+ */
+
+ len = snprintf (filename, sizeof (filename), "%s/%s/temperature", dirname_procfs, name);
+ if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
+ return -1;
+
+ len = read_file_contents (filename, data, sizeof(data));
+ if (len > sizeof(str_temp) && data[--len] == '\n' && !strncmp(data, str_temp, sizeof(str_temp)-1)) {
+ char *endptr = NULL;
+ double temp;
+ double celsius, add;
+
+ if (data[--len] == 'C') {
+ add = 0;
+ celsius = 1;
+ } else if (data[len] == 'F') {
+ add = -32;
+ celsius = 5/9;
+ } else if (data[len] == 'K') {
+ add = -273.15;
+ celsius = 1;
+ } else
+ return -1;
+
+ while (len > 0 && data[--len] == ' ')
+ ;
+ data[len + 1] = 0;
+
+ while (len > 0 && data[--len] != ' ')
+ ;
+ ++len;
+
+ errno = 0;
+ temp = (strtod (data + len, &endptr) + add) * celsius;
+
+ if (endptr != data + len && errno == 0) {
+ thermal_submit(name, TEMP, temp);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static const char *config_keys[] = {
+ "Device",
+ "IgnoreSelected",
+ "ForceUseProcfs"
+};
+
+static int thermal_config (const char *key, const char *value)
+{
+ if (device_list == NULL)
+ device_list = ignorelist_create (1);
+
+ if (strcasecmp (key, "Device") == 0)
+ {
+ if (ignorelist_add (device_list, value))
+ {
+ ERROR ("thermal plugin: "
+ "Cannot add value to ignorelist.");
+ return 1;
+ }
+ }
+ else if (strcasecmp (key, "IgnoreSelected") == 0)
+ {
+ ignorelist_set_invert (device_list, 1);
+ if ((strcasecmp (value, "True") == 0)
+ || (strcasecmp (value, "Yes") == 0)
+ || (strcasecmp (value, "On") == 0))
+ ignorelist_set_invert (device_list, 0);
+ }
+ else if (strcasecmp (key, "ForceUseProcfs") == 0)
+ {
+ force_procfs = 0;
+ if ((strcasecmp (value, "True") == 0)
+ || (strcasecmp (value, "Yes") == 0)
+ || (strcasecmp (value, "On") == 0))
+ force_procfs = 1;
+ }
+ else
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int thermal_sysfs_read (void)
+{
+ return walk_directory (dirname_sysfs, thermal_sysfs_device_read,
+ /* user_data = */ NULL);
+}
+
+static int thermal_procfs_read (void)
+{
+ return walk_directory (dirname_procfs, thermal_procfs_device_read,
+ /* user_data = */ NULL);
+}
+
+static int thermal_init (void)
+{
+ int ret = -1;
+
+ if (!force_procfs && access (dirname_sysfs, R_OK | X_OK) == 0) {
+ ret = plugin_register_read ("thermal", thermal_sysfs_read);
+ } else if (access (dirname_procfs, R_OK | X_OK) == 0) {
+ ret = plugin_register_read ("thermal", thermal_procfs_read);
+ }
+
+ if (!ret) {
+ vl_temp_template.values_len = 1;
+ vl_temp_template.interval = interval_g;
+ sstrncpy (vl_temp_template.host, hostname_g,
+ sizeof(vl_temp_template.host));
+ sstrncpy (vl_temp_template.plugin, "thermal",
+ sizeof(vl_temp_template.plugin));
+ sstrncpy (vl_temp_template.type_instance, "temperature",
+ sizeof(vl_temp_template.type_instance));
+
+ vl_state_template = vl_temp_template;
+ sstrncpy (vl_state_template.type_instance, "cooling_state",
+ sizeof(vl_state_template.type_instance));
+ }
+
+ return ret;
+}
+
+static int thermal_shutdown (void)
+{
+ ignorelist_free (device_list);
+
+ return 0;
+}
+
+void module_register (void)
+{
+ plugin_register_config ("thermal", thermal_config,
+ config_keys, STATIC_ARRAY_SIZE(config_keys));
+ plugin_register_init ("thermal", thermal_init);
+ plugin_register_shutdown ("thermal", thermal_shutdown);
+}
+
diff --git a/src/types.db b/src/types.db
index 97c170b7dd90fef053ad105d1b82f866a56e3376..c8d2f8a1f233d8529b5cd2a85a4f7648f79254ba 100644 (file)
--- a/src/types.db
+++ b/src/types.db
apache_requests count:COUNTER:0:134217728
apache_scoreboard count:GAUGE:0:65535
bitrate value:GAUGE:0:4294967295
+bytes value:GAUGE:0:U
cache_result value:COUNTER:0:4294967295
-cache_size value:GAUGE:0:4294967295
+cache_size value:GAUGE:0:4294967295
charge value:GAUGE:0:U
connections value:COUNTER:0:U
counter value:COUNTER:U:U
email_size value:GAUGE:0:U
entropy entropy:GAUGE:0:4294967295
fanspeed value:GAUGE:0:U
+files value:GAUGE:0:U
frequency frequency:GAUGE:0:U
frequency_offset ppm:GAUGE:-1000000:1000000
gauge value:GAUGE:U:U
nginx_connections value:GAUGE:0:U
nginx_requests value:COUNTER:0:134217728
percent percent:GAUGE:0:100.1
+pg_blks value:COUNTER:0:U
+pg_db_size value:GAUGE:0:U
+pg_n_tup_c value:COUNTER:0:U
+pg_n_tup_g value:GAUGE:0:U
+pg_numbackends value:GAUGE:0:U
+pg_scan value:COUNTER:0:U
+pg_xact value:COUNTER:0:U
ping ping:GAUGE:0:65535
players value:GAUGE:0:1000000
power value:GAUGE:0:U
diff --git a/src/types_list.c b/src/types_list.c
index 3be792d5ca11bbd741f9b599a517c9cfea7da9ac..7600c346ecc1e8c901460a029c2ead4c167e5576 100644 (file)
--- a/src/types_list.c
+++ b/src/types_list.c
if (buf_len < 11)
{
- ERROR ("parse_ds: (buf_len = %u) < 11", buf_len);
+ ERROR ("parse_ds: (buf_len = %zu) < 11", buf_len);
return (-1);
}
return (-1);
}
- strncpy (dsrc->name, fields[0], sizeof (dsrc->name));
- dsrc->name[sizeof (dsrc->name) - 1] = '\0';
+ sstrncpy (dsrc->name, fields[0], sizeof (dsrc->name));
if (strcasecmp (fields[1], "GAUGE") == 0)
dsrc->type = DS_TYPE_GAUGE;
memset (ds, '\0', sizeof (data_set_t));
- strncpy (ds->type, fields[0], sizeof (ds->type));
- ds->type[sizeof (ds->type) - 1] = '\0';
+ sstrncpy (ds->type, fields[0], sizeof (ds->type));
ds->ds_num = fields_num - 1;
ds->ds = (data_source_t *) calloc (ds->ds_num, sizeof (data_source_t));
diff --git a/src/unixsock.c b/src/unixsock.c
index d80091b1bd18bfffd290ae4c7a54b6086131605f..d800906ecc9e76c544486ce41f6f03b2762d1c81 100644 (file)
--- a/src/unixsock.c
+++ b/src/unixsock.c
memset (&sa, '\0', sizeof (sa));
sa.sun_family = AF_UNIX;
- strncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
- sizeof (sa.sun_path) - 1);
+ sstrncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+ sizeof (sa.sun_path));
/* unlink (sa.sun_path); */
DEBUG ("unixsock plugin: socket path = %s", sa.sun_path);
{
int fd;
FILE *fhin, *fhout;
- char buffer[1024];
- char *fields[128];
- int fields_num;
fd = *((int *) arg);
free (arg);
arg = NULL;
- DEBUG ("Reading from fd #%i", fd);
+ DEBUG ("unixsock plugin: us_handle_client: Reading from fd #%i", fd);
fhin = fdopen (fd, "r");
if (fhin == NULL)
while (42)
{
- int len;
+ char buffer[1024];
+ char buffer_copy[1024];
+ char *fields[128];
+ int fields_num;
+ int len;
errno = 0;
if (fgets (buffer, sizeof (buffer), fhin) == NULL)
if (len == 0)
continue;
- DEBUG ("fgets -> buffer = %s; len = %i;", buffer, len);
+ sstrncpy (buffer_copy, buffer, sizeof (buffer_copy));
- fields_num = strsplit (buffer, fields,
+ fields_num = strsplit (buffer_copy, fields,
sizeof (fields) / sizeof (fields[0]));
if (fields_num < 1)
if (strcasecmp (fields[0], "getval") == 0)
{
- handle_getval (fhout, fields, fields_num);
+ handle_getval (fhout, buffer);
}
else if (strcasecmp (fields[0], "putval") == 0)
{
- handle_putval (fhout, fields, fields_num);
+ handle_putval (fhout, buffer);
}
else if (strcasecmp (fields[0], "listval") == 0)
{
- handle_listval (fhout, fields, fields_num);
+ handle_listval (fhout, buffer);
}
else if (strcasecmp (fields[0], "putnotif") == 0)
{
- handle_putnotif (fhout, fields, fields_num);
+ handle_putnotif (fhout, buffer);
}
else if (strcasecmp (fields[0], "flush") == 0)
{
- handle_flush (fhout, fields, fields_num);
+ handle_flush (fhout, buffer);
}
else
{
}
} /* while (fgets) */
- DEBUG ("Exiting..");
+ DEBUG ("unixsock plugin: us_handle_client: Exiting..");
fclose (fhin);
fclose (fhout);
diff --git a/src/users.c b/src/users.c
index d0bd63cdb540ef2bc8d5e145e386f2590e604ef7..1231075a324803bd3fa866396c62563763496e67 100644 (file)
--- a/src/users.c
+++ b/src/users.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "users", sizeof (vl.plugin));
+ sstrncpy (vl.type, "users", sizeof (vl.plugin));
- plugin_dispatch_values ("users", &vl);
+ plugin_dispatch_values (&vl);
} /* void users_submit */
static int users_read (void)
diff --git a/src/utils_cache.c b/src/utils_cache.c
index 6d96516900c7f9d03d1cc39a2b3abef8c89a96f8..241aa726c55bf775159f96b7b448b68f574ae8fe 100644 (file)
--- a/src/utils_cache.c
+++ b/src/utils_cache.c
return (-1);
}
- snprintf (n.message, sizeof (n.message),
+ ssnprintf (n.message, sizeof (n.message),
"%s has not been updated for %i seconds.", name,
(int) (n.time - ce->last_update));
pthread_mutex_unlock (&cache_lock);
- n.message[sizeof (n.message) - 1] = '\0';
plugin_dispatch_notification (&n);
return (0);
}
else
{
- WARNING ("uc_check_timeout: ut_check_interesting (%s) returned ",
+ WARNING ("uc_check_timeout: ut_check_interesting (%s) returned "
"invalid status %i.",
keys[i], status);
}
n.severity = NOTIF_OKAY;
n.time = vl->time;
- snprintf (n.message, sizeof (n.message),
+ ssnprintf (n.message, sizeof (n.message),
"Received a value for %s. It was missing for %u seconds.",
name, (unsigned int) update_delay);
- n.message[sizeof (n.message) - 1] = '\0';
plugin_dispatch_notification (&n);
if (ret_num != ds->ds_num)
{
ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
- "but uc_get_rate_by_name returned %i.",
+ "but uc_get_rate_by_name returned %zu.",
ds->type, ds->ds_num, ret_num);
sfree (ret);
return (NULL);
diff --git a/src/utils_cmd_flush.c b/src/utils_cmd_flush.c
index 6fa8b7bf00b5d0b68979b4e828e1f7093e32f5dc..0e7b350f581f02f07ccaf234c1ec0c225011b33d 100644 (file)
--- a/src/utils_cmd_flush.c
+++ b/src/utils_cmd_flush.c
#include "collectd.h"
#include "common.h"
#include "plugin.h"
+#include "utils_parse_option.h"
#define print_to_socket(fh, ...) \
if (fprintf (fh, __VA_ARGS__) < 0) { \
return -1; \
}
-int handle_flush (FILE *fh, char **fields, int fields_num)
+static int add_to_array (char ***array, int *array_num, char *value)
+{
+ char **temp;
+
+ temp = (char **) realloc (*array, sizeof (char *) * (*array_num + 1));
+ if (temp == NULL)
+ return (-1);
+
+ *array = temp;
+ (*array)[*array_num] = value;
+ (*array_num)++;
+
+ return (0);
+} /* int add_to_array */
+
+int handle_flush (FILE *fh, char *buffer)
{
int success = 0;
int error = 0;
int timeout = -1;
+ char **plugins = NULL;
+ int plugins_num = 0;
+ char **identifiers = NULL;
+ int identifiers_num = 0;
int i;
- for (i = 1; i < fields_num; i++)
+ if ((fh == NULL) || (buffer == NULL))
+ return (-1);
+
+ DEBUG ("utils_cmd_flush: handle_flush (fh = %p, buffer = %s);",
+ (void *) fh, buffer);
+
+ if (strncasecmp ("FLUSH", buffer, strlen ("FLUSH")) != 0)
{
- char *option = fields[i];
- int status = 0;
+ print_to_socket (fh, "-1 Cannot parse command.\n");
+ return (-1);
+ }
+ buffer += strlen ("FLUSH");
+
+ while (*buffer != 0)
+ {
+ char *opt_key;
+ char *opt_value;
+ int status;
- if (strncasecmp ("plugin=", option, strlen ("plugin=")) == 0)
+ opt_key = NULL;
+ opt_value = NULL;
+ status = parse_option (&buffer, &opt_key, &opt_value);
+ if (status != 0)
{
- char *plugin = option + strlen ("plugin=");
+ print_to_socket (fh, "-1 Parsing options failed.\n");
+ sfree (plugins);
+ sfree (identifiers);
+ return (-1);
+ }
- if (0 == plugin_flush_one (timeout, plugin))
- ++success;
- else
- ++error;
+ if (strcasecmp ("plugin", opt_key) == 0)
+ {
+ add_to_array (&plugins, &plugins_num, opt_value);
}
- else if (strncasecmp ("timeout=", option, strlen ("timeout=")) == 0)
+ else if (strcasecmp ("identifier", opt_key) == 0)
{
- char *endptr = NULL;
- char *value = option + strlen ("timeout=");
-
+ add_to_array (&identifiers, &identifiers_num, opt_value);
+ }
+ else if (strcasecmp ("timeout", opt_key) == 0)
+ {
+ char *endptr;
+
errno = 0;
- timeout = strtol (value, &endptr, 0);
+ endptr = NULL;
+ timeout = strtol (opt_value, &endptr, 0);
- if ((endptr == value) || (0 != errno))
- status = -1;
- else if (0 >= timeout)
+ if ((endptr == opt_value) || (errno != 0))
+ {
+ print_to_socket (fh, "-1 Invalid value for option `timeout': "
+ "%s\n", opt_value);
+ sfree (plugins);
+ sfree (identifiers);
+ return (-1);
+ }
+ else if (timeout <= 0)
timeout = -1;
}
else
- status = -1;
-
- if (status != 0)
{
- print_to_socket (fh, "-1 Cannot parse option %s\n", option);
+ print_to_socket (fh, "-1 Cannot parse option %s\n", opt_key);
+ sfree (plugins);
+ sfree (identifiers);
return (-1);
}
+ } /* while (*buffer != 0) */
+
+ /* Add NULL entries for `any plugin' and/or `any value' if nothing was
+ * specified. */
+ if (plugins_num == 0)
+ add_to_array (&plugins, &plugins_num, NULL);
+
+ if (identifiers_num == 0)
+ add_to_array (&identifiers, &identifiers_num, NULL);
+
+ for (i = 0; i < plugins_num; i++)
+ {
+ char *plugin;
+ int j;
+
+ plugin = plugins[i];
+
+ for (j = 0; j < identifiers_num; j++)
+ {
+ char *identifier;
+ int status;
+
+ identifier = identifiers[j];
+ status = plugin_flush (plugin, timeout, identifier);
+ if (status == 0)
+ success++;
+ else
+ error++;
+ }
}
if ((success + error) > 0)
}
else
{
- plugin_flush_all (timeout);
+ plugin_flush (NULL, timeout, NULL);
print_to_socket (fh, "0 Done\n");
}
+ sfree (plugins);
+ sfree (identifiers);
return (0);
} /* int handle_flush */
diff --git a/src/utils_cmd_flush.h b/src/utils_cmd_flush.h
index 334f0862f5df284154ff4649431b1bc11633b294..dccafd1534255307701d030a82b706cbbacf797d 100644 (file)
--- a/src/utils_cmd_flush.h
+++ b/src/utils_cmd_flush.h
#ifndef UTILS_CMD_FLUSH_H
#define UTILS_CMD_FLUSH_H 1
-int handle_flush (FILE *fh, char **fields, int fields_num);
+int handle_flush (FILE *fh, char *buffer);
#endif /* UTILS_CMD_FLUSH_H */
diff --git a/src/utils_cmd_getval.c b/src/utils_cmd_getval.c
index 470d3022e4881dfa8b8f32b282ff260ce511aac2..186ef9b56d60b6385fde3336316bc0462008c474 100644 (file)
--- a/src/utils_cmd_getval.c
+++ b/src/utils_cmd_getval.c
#include "plugin.h"
#include "utils_cache.h"
+#include "utils_parse_option.h"
#define print_to_socket(fh, ...) \
if (fprintf (fh, __VA_ARGS__) < 0) { \
return -1; \
}
-int handle_getval (FILE *fh, char **fields, int fields_num)
+int handle_getval (FILE *fh, char *buffer)
{
+ char *command;
+ char *identifier;
+ char *identifier_copy;
+
char *hostname;
char *plugin;
char *plugin_instance;
gauge_t *values;
size_t values_num;
- char *identifier_copy;
-
const data_set_t *ds;
int status;
int i;
- if (fields_num != 2)
+ if ((fh == NULL) || (buffer == NULL))
+ return (-1);
+
+ DEBUG ("utils_cmd_getval: handle_getval (fh = %p, buffer = %s);",
+ (void *) fh, buffer);
+
+ command = NULL;
+ status = parse_string (&buffer, &command);
+ if (status != 0)
{
- DEBUG ("unixsock plugin: Wrong number of fields: %i", fields_num);
- print_to_socket (fh, "-1 Wrong number of fields: Got %i, expected 2.\n",
- fields_num);
+ print_to_socket (fh, "-1 Cannot parse command.\n");
return (-1);
}
- DEBUG ("unixsock plugin: Got query for `%s'", fields[1]);
+ assert (command != NULL);
- if (strlen (fields[1]) < strlen ("h/p/t"))
+ if (strcasecmp ("GETVAL", command) != 0)
{
- print_to_socket (fh, "-1 Invalied identifier, %s\n", fields[1]);
+ print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
+ return (-1);
+ }
+
+ identifier = NULL;
+ status = parse_string (&buffer, &identifier);
+ if (status != 0)
+ {
+ print_to_socket (fh, "-1 Cannot parse identifier.\n");
+ return (-1);
+ }
+ assert (identifier != NULL);
+
+ if (*buffer != 0)
+ {
+ print_to_socket (fh, "-1 Garbage after end of command: %s\n", buffer);
return (-1);
}
/* parse_identifier() modifies its first argument,
* returning pointers into it */
- identifier_copy = sstrdup (fields[1]);
+ identifier_copy = sstrdup (identifier);
status = parse_identifier (identifier_copy, &hostname,
&plugin, &plugin_instance,
&type, &type_instance);
if (status != 0)
{
- DEBUG ("unixsock plugin: Cannot parse `%s'", fields[1]);
- print_to_socket (fh, "-1 Cannot parse identifier.\n");
+ DEBUG ("handle_getval: Cannot parse identifier `%s'.", identifier);
+ print_to_socket (fh, "-1 Cannot parse identifier `%s'.\n", identifier);
sfree (identifier_copy);
return (-1);
}
ds = plugin_get_ds (type);
if (ds == NULL)
{
- DEBUG ("unixsock plugin: plugin_get_ds (%s) == NULL;", type);
+ DEBUG ("handle_getval: plugin_get_ds (%s) == NULL;", type);
print_to_socket (fh, "-1 Type `%s' is unknown.\n", type);
sfree (identifier_copy);
return (-1);
values = NULL;
values_num = 0;
- status = uc_get_rate_by_name (fields[1], &values, &values_num);
+ status = uc_get_rate_by_name (identifier, &values, &values_num);
if (status != 0)
{
print_to_socket (fh, "-1 No such value\n");
diff --git a/src/utils_cmd_getval.h b/src/utils_cmd_getval.h
index d7bd1151c2c52b515852f0100e82b68f6fe59b5a..86134cdf9a19b1e542662352161a8e51c35bad9f 100644 (file)
--- a/src/utils_cmd_getval.h
+++ b/src/utils_cmd_getval.h
#ifndef UTILS_CMD_GETVAL_H
#define UTILS_CMD_GETVAL_H 1
-int handle_getval (FILE *fh, char **fields, int fields_num);
+int handle_getval (FILE *fh, char *buffer);
#endif /* UTILS_CMD_GETVAL_H */
index 6f03e757ac57b5c5d397c12821d7e6d2f45ee8c8..bca83a9996a220870fd9651555e1d56bad090397 100644 (file)
--- a/src/utils_cmd_listval.c
+++ b/src/utils_cmd_listval.c
#include "utils_cmd_listval.h"
#include "utils_cache.h"
+#include "utils_parse_option.h"
#define print_to_socket(fh, ...) \
if (fprintf (fh, __VA_ARGS__) < 0) { \
return -1; \
}
-int handle_listval (FILE *fh, char **fields, int fields_num)
+int handle_listval (FILE *fh, char *buffer)
{
+ char *command;
char **names = NULL;
time_t *times = NULL;
size_t number = 0;
size_t i;
int status;
- if (fields_num != 1)
+ DEBUG ("utils_cmd_listval: handle_listval (fh = %p, buffer = %s);",
+ (void *) fh, buffer);
+
+ command = NULL;
+ status = parse_string (&buffer, &command);
+ if (status != 0)
+ {
+ print_to_socket (fh, "-1 Cannot parse command.\n");
+ return (-1);
+ }
+ assert (command != NULL);
+
+ if (strcasecmp ("LISTVAL", command) != 0)
+ {
+ print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
+ return (-1);
+ }
+
+ if (*buffer != 0)
{
- DEBUG ("command listval: us_handle_listval: Wrong number of fields: %i",
- fields_num);
- print_to_socket (fh, "-1 Wrong number of fields: Got %i, expected 1.\n",
- fields_num);
+ print_to_socket (fh, "-1 Garbage after end of command: %s\n", buffer);
return (-1);
}
index c918796262a979cbc7779950cfe3a7b7356ba41e..73146e785b6b4bd6cd854871fc1f333549c994da 100644 (file)
--- a/src/utils_cmd_listval.h
+++ b/src/utils_cmd_listval.h
#ifndef UTILS_CMD_LISTVAL_H
#define UTILS_CMD_LISTVAL_H 1
-int handle_listval (FILE *fh, char **fields, int fields_num);
+int handle_listval (FILE *fh, char *buffer);
#endif /* UTILS_CMD_LISTVAL_H */
index eb7d60bc88657dfb5df94fec66940482c3d7b5c3..5a9faff2321e315188e370c7b5508fb17a108576 100644 (file)
--- a/src/utils_cmd_putnotif.c
+++ b/src/utils_cmd_putnotif.c
#include "common.h"
#include "plugin.h"
+#include "utils_parse_option.h"
+
#define print_to_socket(fh, ...) \
if (fprintf (fh, __VA_ARGS__) < 0) { \
char errbuf[1024]; \
return -1; \
}
-static int parse_option_severity (notification_t *n, char *value)
+static int set_option_severity (notification_t *n, const char *value)
{
if (strcasecmp (value, "Failure") == 0)
n->severity = NOTIF_FAILURE;
return (-1);
return (0);
-} /* int parse_option_severity */
+} /* int set_option_severity */
-static int parse_option_time (notification_t *n, char *value)
+static int set_option_time (notification_t *n, const char *value)
{
time_t tmp;
n->time = tmp;
return (0);
-} /* int parse_option_time */
+} /* int set_option_time */
-static int parse_option (notification_t *n, char *buffer)
+static int set_option (notification_t *n, const char *option, const char *value)
{
- char *option = buffer;
- char *value;
-
- if ((n == NULL) || (option == NULL))
+ if ((n == NULL) || (option == NULL) || (value == NULL))
return (-1);
- value = strchr (option, '=');
- if (value == NULL)
- return (-1);
- *value = '\0'; value++;
+ DEBUG ("utils_cmd_putnotif: set_option (option = %s, value = %s);",
+ option, value);
if (strcasecmp ("severity", option) == 0)
- return (parse_option_severity (n, value));
+ return (set_option_severity (n, value));
else if (strcasecmp ("time", option) == 0)
- return (parse_option_time (n, value));
+ return (set_option_time (n, value));
+ else if (strcasecmp ("message", option) == 0)
+ sstrncpy (n->message, value, sizeof (n->message));
else if (strcasecmp ("host", option) == 0)
sstrncpy (n->host, value, sizeof (n->host));
else if (strcasecmp ("plugin", option) == 0)
return (1);
return (0);
-} /* int parse_option */
+} /* int set_option */
-static int parse_message (notification_t *n, char **fields, int fields_num)
+int handle_putnotif (FILE *fh, char *buffer)
{
+ char *command;
+ notification_t n;
int status;
- /* Strip off the leading `message=' */
- fields[0] += strlen ("message=");
-
- status = strjoin (n->message, sizeof (n->message), fields, fields_num, " ");
- if (status < 0)
+ if ((fh == NULL) || (buffer == NULL))
return (-1);
- return (0);
-} /* int parse_message */
+ DEBUG ("utils_cmd_putnotif: handle_putnotif (fh = %p, buffer = %s);",
+ (void *) fh, buffer);
-int handle_putnotif (FILE *fh, char **fields, int fields_num)
-{
- notification_t n;
- int status;
- int i;
+ command = NULL;
+ status = parse_string (&buffer, &command);
+ if (status != 0)
+ {
+ print_to_socket (fh, "-1 Cannot parse command.\n");
+ return (-1);
+ }
+ assert (command != NULL);
- /* Required fields: `PUTNOTIF', severity, time, message */
- if (fields_num < 4)
+ if (strcasecmp ("PUTNOTIF", command) != 0)
{
- DEBUG ("cmd putnotif: Wrong number of fields: %i", fields_num);
- print_to_socket (fh, "-1 Wrong number of fields: Got %i, "
- "expected at least 4.\n",
- fields_num);
+ print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
return (-1);
}
memset (&n, '\0', sizeof (n));
status = 0;
- for (i = 1; i < fields_num; i++)
+ while (*buffer != 0)
{
- if (strncasecmp (fields[i], "message=", strlen ("message=")) == 0)
+ char *key;
+ char *value;
+
+ status = parse_option (&buffer, &key, &value);
+ if (status != 0)
{
- status = parse_message (&n, fields + i, fields_num - i);
- if (status != 0)
- {
- print_to_socket (fh, "-1 Error parsing the message. Have you hit the "
- "limit of %u bytes?\n", (unsigned int) sizeof (n.message));
- }
+ print_to_socket (fh, "-1 Malformed option.\n");
break;
}
- else
+
+ status = set_option (&n, key, value);
+ if (status != 0)
{
- status = parse_option (&n, fields[i]);
- if (status != 0)
- {
- print_to_socket (fh, "-1 Error parsing option `%s'\n", fields[i]);
- break;
- }
+ print_to_socket (fh, "-1 Error parsing option `%s'\n", key);
+ break;
}
} /* for (i) */
index 08b3bb37682f96c0862e7d69d29bc57af0c038f9..8d5475b92fc3b75ccd20c28e84b873ebb00fe79a 100644 (file)
--- a/src/utils_cmd_putnotif.h
+++ b/src/utils_cmd_putnotif.h
#ifndef UTILS_CMD_PUTNOTIF_H
#define UTILS_CMD_PUTNOTIF_H 1
-int handle_putnotif (FILE *fh, char **fields, int fields_num);
+int handle_putnotif (FILE *fh, char *buffer);
/* vim: set shiftwidth=2 softtabstop=2 tabstop=8 : */
diff --git a/src/utils_cmd_putval.c b/src/utils_cmd_putval.c
index 16a09b1b71093c7eb5752e4c28772fc34800a667..91b70160f063590e477cd415253e38d1099abc1b 100644 (file)
--- a/src/utils_cmd_putval.c
+++ b/src/utils_cmd_putval.c
/**
* collectd - src/utils_cms_putval.c
- * Copyright (C) 2007 Florian octo Forster
+ * Copyright (C) 2007,2008 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#include "common.h"
#include "plugin.h"
+#include "utils_parse_option.h"
+
#define print_to_socket(fh, ...) \
if (fprintf (fh, __VA_ARGS__) < 0) { \
char errbuf[1024]; \
}
static int parse_value (const data_set_t *ds, value_list_t *vl,
- const char *type,
FILE *fh, char *buffer)
{
char *dummy;
return (-1);
}
- plugin_dispatch_values (type, vl);
+ plugin_dispatch_values (vl);
return (0);
} /* int parse_value */
-static int parse_option (value_list_t *vl, char *buffer)
+static int set_option (value_list_t *vl, const char *key, const char *value)
{
- char *option = buffer;
- char *value;
-
- if ((vl == NULL) || (option == NULL))
- return (-1);
-
- value = strchr (option, '=');
- if (value == NULL)
+ if ((vl == NULL) || (key == NULL) || (value == NULL))
return (-1);
- *value = '\0'; value++;
- if (strcasecmp ("interval", option) == 0)
+ if (strcasecmp ("interval", key) == 0)
{
- vl->interval = atoi (value);
- if (vl->interval <= 0)
- vl->interval = interval_g;
+ int tmp;
+ char *endptr;
+
+ endptr = NULL;
+ errno = 0;
+ tmp = strtol (value, &endptr, 0);
+
+ if ((errno == 0) && (endptr != NULL)
+ && (endptr != value) && (tmp > 0))
+ vl->interval = tmp;
}
else
return (1);
return (0);
} /* int parse_option */
-int handle_putval (FILE *fh, char **fields, int fields_num)
+int handle_putval (FILE *fh, char *buffer)
{
+ char *command;
+ char *identifier;
char *hostname;
char *plugin;
char *plugin_instance;
char *type;
char *type_instance;
int status;
- int i;
+ int values_submitted;
char *identifier_copy;
const data_set_t *ds;
value_list_t vl = VALUE_LIST_INIT;
- if (fields_num < 3)
+ DEBUG ("utils_cmd_putval: handle_putval (fh = %p, buffer = %s);",
+ (void *) fh, buffer);
+
+ command = NULL;
+ status = parse_string (&buffer, &command);
+ if (status != 0)
{
- DEBUG ("cmd putval: Wrong number of fields: %i",
- fields_num);
- print_to_socket (fh, "-1 Wrong number of fields: Got %i, "
- "expected at least 3.\n",
- fields_num);
+ print_to_socket (fh, "-1 Cannot parse command.\n");
return (-1);
}
+ assert (command != NULL);
+
+ if (strcasecmp ("PUTVAL", command) != 0)
+ {
+ print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
+ return (-1);
+ }
+
+ identifier = NULL;
+ status = parse_string (&buffer, &identifier);
+ if (status != 0)
+ {
+ print_to_socket (fh, "-1 Cannot parse identifier.\n");
+ return (-1);
+ }
+ assert (identifier != NULL);
/* parse_identifier() modifies its first argument,
* returning pointers into it */
- identifier_copy = sstrdup (fields[1]);
+ identifier_copy = sstrdup (identifier);
status = parse_identifier (identifier_copy, &hostname,
&plugin, &plugin_instance,
&type, &type_instance);
if (status != 0)
{
- DEBUG ("cmd putval: Cannot parse `%s'", fields[1]);
- print_to_socket (fh, "-1 Cannot parse identifier.\n");
+ DEBUG ("handle_putval: Cannot parse identifier `%s'.",
+ identifier);
+ print_to_socket (fh, "-1 Cannot parse identifier `%s'.\n",
+ identifier);
sfree (identifier_copy);
return (-1);
}
sstrncpy (vl.host, hostname, sizeof (vl.host));
sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (plugin_instance != NULL)
sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
if (type_instance != NULL)
ds = plugin_get_ds (type);
if (ds == NULL) {
+ print_to_socket (fh, "-1 Type `%s' isn't defined.\n", type);
sfree (identifier_copy);
return (-1);
}
+ /* Free identifier_copy */
+ hostname = NULL;
+ plugin = NULL; plugin_instance = NULL;
+ type = NULL; type_instance = NULL;
+ sfree (identifier_copy);
+
vl.values_len = ds->ds_num;
vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t));
if (vl.values == NULL)
{
print_to_socket (fh, "-1 malloc failed.\n");
- sfree (identifier_copy);
return (-1);
}
/* All the remaining fields are part of the optionlist. */
- for (i = 2; i < fields_num; i++)
+ values_submitted = 0;
+ while (*buffer != 0)
{
- if (strchr (fields[i], ':') != NULL)
+ char *string = NULL;
+ char *value = NULL;
+
+ status = parse_option (&buffer, &string, &value);
+ if (status < 0)
{
- /* It's parse_value's job to write an error to `fh'.
- * This is not the case with `parse_option below.
- * Neither will write an success message. */
- if (parse_value (ds, &vl, type, fh, fields[i]) != 0)
- break;
+ /* parse_option failed, buffer has been modified.
+ * => we need to abort */
+ print_to_socket (fh, "-1 Misformatted option.\n");
+ return (-1);
}
- else if (strchr (fields[i], '=') != NULL)
+ else if (status == 0)
{
- if (parse_option (&vl, fields[i]) != 0)
- {
- print_to_socket (fh, "-1 Error parsing option `%s'\n",
- fields[i]);
- break;
- }
+ assert (string != NULL);
+ assert (value != NULL);
+ set_option (&vl, string, value);
+ continue;
}
- else
+ /* else: parse_option but buffer has not been modified. This is
+ * the default if no `=' is found.. */
+
+ status = parse_string (&buffer, &string);
+ if (status != 0)
{
- WARNING ("cmd putval: handle_putval: "
- "Cannot parse field #%i `%s'; "
- "Ignoring it.\n",
- i, fields[i]);
+ print_to_socket (fh, "-1 Misformatted value.\n");
+ return (-1);
}
- }
+ assert (string != NULL);
+
+ status = parse_value (ds, &vl, fh, string);
+ if (status != 0)
+ {
+ /* An error has already been printed. */
+ return (-1);
+ }
+ values_submitted++;
+ } /* while (*buffer != 0) */
/* Done parsing the options. */
- if (i == fields_num)
- print_to_socket (fh, "0 Success\n");
+ print_to_socket (fh, "0 Success: %i %s been dispatched.\n",
+ values_submitted,
+ (values_submitted == 1) ? "value has" : "values have");
sfree (vl.values);
- sfree (identifier_copy);
return (0);
} /* int handle_putval */
diff --git a/src/utils_cmd_putval.h b/src/utils_cmd_putval.h
index 2ae45323eed7f2581b6a4d5cec489247ba39c4af..9ba52cc8d80f8a98b54dfaf25755179e9594849a 100644 (file)
--- a/src/utils_cmd_putval.h
+++ b/src/utils_cmd_putval.h
#ifndef UTILS_CMD_PUTVAL_H
#define UTILS_CMD_PUTVAL_H 1
-int handle_putval (FILE *fh, char **fields, int fields_num);
+int handle_putval (FILE *fh, char *buffer);
#endif /* UTILS_CMD_PUTVAL_H */
diff --git a/src/utils_complain.c b/src/utils_complain.c
--- /dev/null
+++ b/src/utils_complain.c
@@ -0,0 +1,101 @@
+/**
+ * collectd - src/utils_complain.c
+ * Copyright (C) 2006-2007 Florian octo Forster
+ * Copyright (C) 2008 Sebastian tokkee Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ * Sebastian tokkee Harl <sh at tokkee.org>
+ **/
+
+#include "utils_complain.h"
+#include "plugin.h"
+
+/* vcomplain returns 0 if it did not report, 1 else */
+static int vcomplain (int level, c_complain_t *c,
+ const char *format, va_list ap)
+{
+ time_t now;
+ char message[512];
+
+ now = time (NULL);
+
+ if (c->last + c->interval > now)
+ return 0;
+
+ c->last = now;
+
+ if (c->interval < interval_g)
+ c->interval = interval_g;
+ else
+ c->interval *= 2;
+
+ if (c->interval > 86400)
+ c->interval = 86400;
+
+ vsnprintf (message, sizeof (message), format, ap);
+ message[sizeof (message) - 1] = '\0';
+
+ plugin_log (level, message);
+ return 1;
+} /* vcomplain */
+
+void c_complain (int level, c_complain_t *c, const char *format, ...)
+{
+ va_list ap;
+
+ /* reset the old interval */
+ if (c->interval < 0)
+ c->interval *= -1;
+
+ va_start (ap, format);
+ vcomplain (level, c, format, ap);
+ va_end (ap);
+} /* c_complain */
+
+void c_complain_once (int level, c_complain_t *c, const char *format, ...)
+{
+ va_list ap;
+
+ if (c->interval < 0)
+ return;
+
+ va_start (ap, format);
+ if (vcomplain (level, c, format, ap))
+ c->interval *= -1;
+ va_end (ap);
+} /* c_complain_once */
+
+void c_do_release (int level, c_complain_t *c, const char *format, ...)
+{
+ char message[512];
+ va_list ap;
+
+ if (c->interval == 0)
+ return;
+
+ c->interval = 0;
+
+ va_start (ap, format);
+ vsnprintf (message, sizeof (message), format, ap);
+ message[sizeof (message) - 1] = '\0';
+ va_end (ap);
+
+ plugin_log (level, message);
+} /* c_release */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/utils_complain.h b/src/utils_complain.h
--- /dev/null
+++ b/src/utils_complain.h
@@ -0,0 +1,96 @@
+/**
+ * collectd - src/utils_complain.h
+ * Copyright (C) 2006-2007 Florian octo Forster
+ * Copyright (C) 2008 Sebastian tokkee Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ * Sebastian tokkee Harl <sh at tokkee.org>
+ **/
+
+#ifndef UTILS_COMPLAIN_H
+#define UTILS_COMPLAIN_H 1
+
+#include <time.h>
+
+typedef struct
+{
+ /* time of the last report */
+ time_t last;
+
+ /* how long to wait until reporting again
+ * 0 indicates that the complaint is no longer valid
+ * < 0 indicates that the complaint has been reported once
+ * => c_complain_once will not report again
+ * => c_complain uses the absolute value to reset the old value */
+ int interval;
+} c_complain_t;
+
+#define C_COMPLAIN_INIT { 0, 0 }
+
+/*
+ * NAME
+ * c_complain
+ *
+ * DESCRIPTION
+ * Complain about something. This function will report a message (usually
+ * indicating some error condition) using the collectd logging mechanism.
+ * When this function is called again, reporting the message again will be
+ * deferred by an increasing interval (up to one day) to prevent flooding
+ * the logs. A call to `c_release' resets the counter.
+ *
+ * PARAMETERS
+ * `level' The log level passed to `plugin_log'.
+ * `c' Identifier for the complaint.
+ * `format' Message format - see the documentation of printf(3).
+ */
+void c_complain (int level, c_complain_t *c, const char *format, ...);
+
+/*
+ * NAME
+ * c_complain_once
+ *
+ * DESCRIPTION
+ * Complain about something once. This function will not report anything
+ * again, unless `c_release' has been called in between. If used after some
+ * calls to `c_complain', it will report again on the next interval and stop
+ * after that.
+ *
+ * See `c_complain' for further details and a description of the parameters.
+ */
+void c_complain_once (int level, c_complain_t *c, const char *format, ...);
+
+/*
+ * NAME
+ * c_release
+ *
+ * DESCRIPTION
+ * Release a complaint. This will report a message once, marking the
+ * complaint as released.
+ *
+ * See `c_complain' for a description of the parameters.
+ */
+void c_do_release (int level, c_complain_t *c, const char *format, ...);
+#define c_release(level, c, ...) \
+ do { \
+ if ((c)->interval != 0) \
+ c_do_release(level, c, __VA_ARGS__); \
+ } while (0)
+
+#endif /* UTILS_COMPLAIN_H */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/utils_dns.c b/src/utils_dns.c
index 9b001517c80945f1d5e5e4d643c867f31a07ab54..f2ab3377ed43bf60dc40584e7dfbe3773cfdca9a 100644 (file)
--- a/src/utils_dns.c
+++ b/src/utils_dns.c
*/
#include "collectd.h"
+#include "common.h"
#if HAVE_NETINET_IN_SYSTM_H
# include <netinet/in_systm.h>
if (0 != x)
return 0;
if ('\0' == qh.qname[0])
- strncpy (qh.qname, ".", sizeof (qh.qname));
+ sstrncpy (qh.qname, ".", sizeof (qh.qname));
while ((t = strchr(qh.qname, '\n')))
*t = ' ';
while ((t = strchr(qh.qname, '\r')))
case T_ANY: return ("ANY"); /* ... 255 */
#endif /* __BIND >= 19950621 */
default:
- snprintf (buf, 32, "#%i", t);
- buf[31] = '\0';
+ ssnprintf (buf, sizeof (buf), "#%i", t);
return (buf);
}; /* switch (t) */
/* NOTREACHED */
return "Update";
break;
default:
- snprintf(buf, 30, "Opcode%d", o);
+ ssnprintf(buf, sizeof (buf), "Opcode%d", o);
return buf;
}
/* NOTREACHED */
#endif /* RFC2136 rcodes */
#endif /* __BIND >= 19950621 */
default:
- snprintf (buf, 32, "RCode%i", rcode);
- buf[31] = '\0';
+ ssnprintf (buf, sizeof (buf), "RCode%i", rcode);
return (buf);
}
/* Never reached */
diff --git a/src/utils_ignorelist.c b/src/utils_ignorelist.c
index 689b4a42fd7c506f7dd4a4321071a62e9a9705c0..de42d0fa399035e0f2e3930866d2be670557fc72 100644 (file)
--- a/src/utils_ignorelist.c
+++ b/src/utils_ignorelist.c
/* We need to copy `entry' since it's const */
entry_copy_size = entry_len - 1;
entry_copy = smalloc (entry_copy_size);
- strncpy (entry_copy, entry + 1, entry_copy_size);
- entry_copy[entry_copy_size - 1] = 0;
+ sstrncpy (entry_copy, entry + 1, entry_copy_size);
DEBUG("I'm about to add regex entry: %s", entry_copy);
ret = ignorelist_append_regex(il, entry_copy);
diff --git a/src/utils_mount.c b/src/utils_mount.c
index 44ad7ea8642f98a222140ce9ced1babd7afdb39d..c53431f1a6458e8902b25ff2537f545e536b6269 100644 (file)
--- a/src/utils_mount.c
+++ b/src/utils_mount.c
* (This is useful, if the cdrom on /dev/hdc must not
* be accessed.)
*/
- snprintf(device, sizeof(device), "%s/%s",
+ ssnprintf(device, sizeof(device), "%s/%s",
DEVLABELDIR, ptname);
if(!get_label_uuid(device, &label, uuid)) {
uuidcache_addentry(sstrdup(device),
return r;
} /* char *cu_mount_getoptionvalue(char *line, char *keyword) */
-
-
int
cu_mount_type(const char *type)
{
return CUMT_UNKNOWN;
} /* int cu_mount_type(const char *type) */
-
-
diff --git a/src/utils_parse_option.c b/src/utils_parse_option.c
--- /dev/null
+++ b/src/utils_parse_option.c
@@ -0,0 +1,153 @@
+/**
+ * collectd - src/utils_parse_option.c
+ * Copyright (C) 2008 Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_parse_option.h"
+
+int parse_string (char **ret_buffer, char **ret_string)
+{
+ char *buffer;
+ char *string;
+
+ buffer = *ret_buffer;
+
+ /* Eat up leading spaces. */
+ string = buffer;
+ while (isspace ((int) *string))
+ string++;
+ if (*string == 0)
+ return (1);
+
+ /* A quoted string */
+ if (*string == '"')
+ {
+ char *dst;
+
+ string++;
+ if (*string == 0)
+ return (1);
+
+ dst = string;
+ buffer = string;
+ while ((*buffer != '"') && (*buffer != 0))
+ {
+ /* Un-escape backslashes */
+ if (*buffer == '\\')
+ {
+ buffer++;
+ /* Catch a backslash at the end of buffer */
+ if (*buffer == 0)
+ return (-1);
+ }
+ *dst = *buffer;
+ buffer++;
+ dst++;
+ }
+ /* No quote sign has been found */
+ if (*buffer == 0)
+ return (-1);
+
+ *dst = 0;
+ dst++;
+ *buffer = 0;
+ buffer++;
+
+ /* Check for trailing spaces. */
+ if ((*buffer != 0) && !isspace ((int) *buffer))
+ return (-1);
+ }
+ else /* an unquoted string */
+ {
+ buffer = string;
+ while ((*buffer != 0) && !isspace ((int) *buffer))
+ buffer++;
+ if (*buffer != 0)
+ {
+ *buffer = 0;
+ buffer++;
+ }
+ }
+
+ /* Eat up trailing spaces */
+ while (isspace ((int) *buffer))
+ buffer++;
+
+ *ret_buffer = buffer;
+ *ret_string = string;
+
+ return (0);
+} /* int parse_string */
+
+/*
+ * parse_option
+ * ------------
+ * Parses an ``option'' as used with the unixsock and exec commands. An
+ * option is of the form:
+ * name0="value"
+ * name1="value with \"quotes\""
+ * name2="value \\ backslash"
+ * However, if the value does *not* contain a space character, you can skip
+ * the quotes.
+ */
+int parse_option (char **ret_buffer, char **ret_key, char **ret_value)
+{
+ char *buffer;
+ char *key;
+ char *value;
+ int status;
+
+ buffer = *ret_buffer;
+
+ /* Eat up leading spaces */
+ key = buffer;
+ while (isspace ((int) *key))
+ key++;
+ if (*key == 0)
+ return (1);
+
+ /* Look for the equal sign */
+ buffer = key;
+ while (isalnum ((int) *buffer))
+ buffer++;
+ if ((*buffer != '=') || (buffer == key))
+ return (1);
+ *buffer = 0;
+ buffer++;
+ /* Empty values must be written as "" */
+ if (isspace ((int) *buffer) || (*buffer == 0))
+ return (-1);
+
+ status = parse_string (&buffer, &value);
+ if (status != 0)
+ return (-1);
+
+ /* NB: parse_string will have eaten up all trailing spaces. */
+
+ *ret_buffer = buffer;
+ *ret_key = key;
+ *ret_value = value;
+
+ return (0);
+} /* int parse_option */
+
+/* vim: set sw=2 ts=8 tw=78 et : */
diff --git a/src/utils_parse_option.h b/src/utils_parse_option.h
--- /dev/null
+++ b/src/utils_parse_option.h
@@ -0,0 +1,30 @@
+/**
+ * collectd - src/utils_parse_option.h
+ * Copyright (C) 2008 Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#ifndef UTILS_PARSE_OPTION
+#define UTILS_PARSE_OPTION 1
+
+int parse_string (char **ret_buffer, char **ret_string);
+int parse_option (char **ret_buffer, char **ret_key, char **ret_value);
+
+#endif /* UTILS_PARSE_OPTION */
+
+/* vim: set sw=2 ts=8 tw=78 et : */
diff --git a/src/utils_tail_match.c b/src/utils_tail_match.c
index 34fe2dced95c91fc5a493dc71a724248ceec45a1..f518b1cd9172304d0319851b78c862c48a6a2388 100644 (file)
--- a/src/utils_tail_match.c
+++ b/src/utils_tail_match.c
sstrncpy (vl.plugin, data->plugin, sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, data->plugin_instance,
sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, data->type, sizeof (vl.type));
sstrncpy (vl.type_instance, data->type_instance,
sizeof (vl.type_instance));
- plugin_dispatch_values (data->type, &vl);
+ plugin_dispatch_values (&vl);
if (match_value->ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
{
diff --git a/src/utils_threshold.c b/src/utils_threshold.c
index ddce42210a20f3fd2b9d40a89702a8192aa79502..68b85a37468bb639e5ea0c5f96c1615b162b7984 100644 (file)
--- a/src/utils_threshold.c
+++ b/src/utils_threshold.c
return (-1);
}
- strncpy (th->type_instance, ci->values[0].value.string,
+ sstrncpy (th->type_instance, ci->values[0].value.string,
sizeof (th->type_instance));
- th->type_instance[sizeof (th->type_instance) - 1] = '\0';
return (0);
} /* int ut_config_type_instance */
}
memcpy (&th, th_orig, sizeof (th));
- strncpy (th.type, ci->values[0].value.string, sizeof (th.type));
- th.type[sizeof (th.type) - 1] = '\0';
+ sstrncpy (th.type, ci->values[0].value.string, sizeof (th.type));
th.warning_min = NAN;
th.warning_max = NAN;
return (-1);
}
- strncpy (th->plugin_instance, ci->values[0].value.string,
+ sstrncpy (th->plugin_instance, ci->values[0].value.string,
sizeof (th->plugin_instance));
- th->plugin_instance[sizeof (th->plugin_instance) - 1] = '\0';
return (0);
} /* int ut_config_plugin_instance */
}
memcpy (&th, th_orig, sizeof (th));
- strncpy (th.plugin, ci->values[0].value.string, sizeof (th.plugin));
- th.plugin[sizeof (th.plugin) - 1] = '\0';
+ sstrncpy (th.plugin, ci->values[0].value.string, sizeof (th.plugin));
for (i = 0; i < ci->children_num; i++)
{
}
memcpy (&th, th_orig, sizeof (th));
- strncpy (th.host, ci->values[0].value.string, sizeof (th.host));
- th.host[sizeof (th.host) - 1] = '\0';
+ sstrncpy (th.host, ci->values[0].value.string, sizeof (th.host));
for (i = 0; i < ci->children_num; i++)
{
*/
/* }}} */
-static threshold_t *threshold_search (const data_set_t *ds,
- const value_list_t *vl)
+static threshold_t *threshold_search (const value_list_t *vl)
{
threshold_t *th;
if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance,
- ds->type, vl->type_instance)) != NULL)
+ vl->type, vl->type_instance)) != NULL)
return (th);
else if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance,
- ds->type, NULL)) != NULL)
+ vl->type, NULL)) != NULL)
return (th);
else if ((th = threshold_get (vl->host, vl->plugin, NULL,
- ds->type, vl->type_instance)) != NULL)
+ vl->type, vl->type_instance)) != NULL)
return (th);
else if ((th = threshold_get (vl->host, vl->plugin, NULL,
- ds->type, NULL)) != NULL)
+ vl->type, NULL)) != NULL)
return (th);
else if ((th = threshold_get (vl->host, "", NULL,
- ds->type, vl->type_instance)) != NULL)
+ vl->type, vl->type_instance)) != NULL)
return (th);
else if ((th = threshold_get (vl->host, "", NULL,
- ds->type, NULL)) != NULL)
+ vl->type, NULL)) != NULL)
return (th);
else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance,
- ds->type, vl->type_instance)) != NULL)
+ vl->type, vl->type_instance)) != NULL)
return (th);
else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance,
- ds->type, NULL)) != NULL)
+ vl->type, NULL)) != NULL)
return (th);
else if ((th = threshold_get ("", vl->plugin, NULL,
- ds->type, vl->type_instance)) != NULL)
+ vl->type, vl->type_instance)) != NULL)
return (th);
else if ((th = threshold_get ("", vl->plugin, NULL,
- ds->type, NULL)) != NULL)
+ vl->type, NULL)) != NULL)
return (th);
else if ((th = threshold_get ("", "", NULL,
- ds->type, vl->type_instance)) != NULL)
+ vl->type, vl->type_instance)) != NULL)
return (th);
else if ((th = threshold_get ("", "", NULL,
- ds->type, NULL)) != NULL)
+ vl->type, NULL)) != NULL)
return (th);
return (NULL);
n.time = vl->time;
- status = snprintf (buf, bufsize, "Host %s, plugin %s",
+ status = ssnprintf (buf, bufsize, "Host %s, plugin %s",
vl->host, vl->plugin);
buf += status;
bufsize -= status;
if (vl->plugin_instance[0] != '\0')
{
- status = snprintf (buf, bufsize, " (instance %s)",
+ status = ssnprintf (buf, bufsize, " (instance %s)",
vl->plugin_instance);
buf += status;
bufsize -= status;
}
- status = snprintf (buf, bufsize, " type %s", ds->type);
+ status = ssnprintf (buf, bufsize, " type %s", vl->type);
buf += status;
bufsize -= status;
if (vl->type_instance[0] != '\0')
{
- status = snprintf (buf, bufsize, " (instance %s)",
+ status = ssnprintf (buf, bufsize, " (instance %s)",
vl->type_instance);
buf += status;
bufsize -= status;
}
+ plugin_notification_meta_add_string (&n, "DataSource",
+ ds->ds[ds_index].name);
+ plugin_notification_meta_add_double (&n, "CurrentValue", values[ds_index]);
+ plugin_notification_meta_add_double (&n, "WarningMin", th->warning_min);
+ plugin_notification_meta_add_double (&n, "WarningMax", th->warning_max);
+ plugin_notification_meta_add_double (&n, "FailureMin", th->failure_min);
+ plugin_notification_meta_add_double (&n, "FailureMax", th->failure_max);
+
/* Send an okay notification */
if (state == STATE_OKAY)
{
- status = snprintf (buf, bufsize, ": All data sources are within range again.");
+ status = ssnprintf (buf, bufsize, ": All data sources are within range again.");
buf += status;
bufsize -= status;
}
{
if (!isnan (min) && !isnan (max))
{
- status = snprintf (buf, bufsize, ": Data source \"%s\" is currently "
+ status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
"%f. That is within the %s region of %f and %f.",
ds->ds[ds_index].name, values[ds_index],
(state == STATE_ERROR) ? "failure" : "warning",
}
else
{
- status = snprintf (buf, bufsize, ": Data source \"%s\" is currently "
+ status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
"%f. That is %s the %s threshold of %f.",
ds->ds[ds_index].name, values[ds_index],
isnan (min) ? "below" : "above",
}
else /* is not inverted */
{
- status = snprintf (buf, bufsize, ": Data source \"%s\" is currently "
+ status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently "
"%f. That is %s the %s threshold of %f.",
ds->ds[ds_index].name, values[ds_index],
(values[ds_index] < min) ? "below" : "above",
plugin_dispatch_notification (&n);
+ plugin_notification_meta_free (&n);
return (0);
} /* }}} int ut_report_state */
/* Is this lock really necessary? So far, thresholds are only inserted at
* startup. -octo */
pthread_mutex_lock (&threshold_lock);
- th = threshold_search (ds, vl);
+ th = threshold_search (vl);
pthread_mutex_unlock (&threshold_lock);
if (th == NULL)
return (0);
memset (&ds, '\0', sizeof (ds));
memset (&vl, '\0', sizeof (vl));
- strncpy (vl.host, host, sizeof (vl.host));
- vl.host[sizeof (vl.host) - 1] = '\0';
- strncpy (vl.plugin, plugin, sizeof (vl.plugin));
- vl.plugin[sizeof (vl.plugin) - 1] = '\0';
+ sstrncpy (vl.host, host, sizeof (vl.host));
+ sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
if (plugin_instance != NULL)
- {
- strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
- }
- strncpy (ds.type, type, sizeof (ds.type));
- ds.type[sizeof (ds.type) - 1] = '\0';
+ sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (ds.type, type, sizeof (ds.type));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_instance != NULL)
- {
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
- }
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
sfree (name_copy);
host = plugin = plugin_instance = type = type_instance = NULL;
- th = threshold_search (&ds, &vl);
+ th = threshold_search (&vl);
if (th == NULL)
return (0);
if ((th->flags & UT_FLAG_PERSIST) == 0)
diff --git a/src/uuid.c b/src/uuid.c
index d54301a223bee899c430f4f1d19de617e8b78a4a..e0de0d9b314ed53575b7e5f00b08921a03834642 100644 (file)
--- a/src/uuid.c
+++ b/src/uuid.c
char *uuid = uuid_get_local ();
if (uuid) {
- strncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
- hostname_g[DATA_MAX_NAME_LEN-1] = '\0';
+ sstrncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
sfree (uuid);
return 0;
}
diff --git a/src/vmem.c b/src/vmem.c
index 5341e1594798b9eb24b0826f489e87054ad80a78..25f7c70cd3c15b581f0f22f3252e921c82373c33 100644 (file)
--- a/src/vmem.c
+++ b/src/vmem.c
sstrncpy (vl.plugin, "vmem", sizeof (vl.plugin));
if (plugin_instance != NULL)
sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
if (type_instance != NULL)
sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void vmem_submit */
static void submit_two (const char *plugin_instance, const char *type,
diff --git a/src/vserver.c b/src/vserver.c
index 7188b13e366b3b4b0f40bd4b8dbe5e8418b1bcd7..dac4392693159ad63dc1a095536b5a4cbefe9d09 100644 (file)
--- a/src/vserver.c
+++ b/src/vserver.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "if_octets", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values ("if_octets", &vl);
+ plugin_dispatch_values (&vl);
} /* void traffic_submit */
static void load_submit (const char *plugin_instance,
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "load", sizeof (vl.type));
- plugin_dispatch_values ("load", &vl);
+ plugin_dispatch_values (&vl);
}
static void submit_gauge (const char *plugin_instance, const char *type,
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void submit_gauge */
static inline long long __get_sock_bytes(const char *s)
continue;
/* socket message accounting */
- len = snprintf (file, BUFSIZE, PROCDIR "/%s/cacct", dent->d_name);
- if ((len < 0) || (len >= BUFSIZE))
+ len = ssnprintf (file, sizeof (file),
+ PROCDIR "/%s/cacct", dent->d_name);
+ if ((len < 0) || (len >= sizeof (file)))
continue;
if (NULL == (fh = fopen (file, "r")))
}
/* thread information and load */
- len = snprintf (file, BUFSIZE, PROCDIR "/%s/cvirt", dent->d_name);
- if ((len < 0) || (len >= BUFSIZE))
+ len = ssnprintf (file, sizeof (file),
+ PROCDIR "/%s/cvirt", dent->d_name);
+ if ((len < 0) || (len >= sizeof (file)))
continue;
if (NULL == (fh = fopen (file, "r")))
}
/* processes and memory usage */
- len = snprintf (file, BUFSIZE, PROCDIR "/%s/limit", dent->d_name);
- if ((len < 0) || (len >= BUFSIZE))
+ len = ssnprintf (file, sizeof (file),
+ PROCDIR "/%s/limit", dent->d_name);
+ if ((len < 0) || (len >= sizeof (file)))
continue;
if (NULL == (fh = fopen (file, "r")))
diff --git a/src/wireless.c b/src/wireless.c
index 0edaf458688bcddd3dcce19c42652be93ece2e52..21bbcb401b141e0c09bb7f2a1cb8ce1db5f881b6 100644 (file)
--- a/src/wireless.c
+++ b/src/wireless.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "wireless", sizeof (vl.plugin));
- strncpy (vl.plugin_instance, plugin_instance,
+ sstrncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void wireless_submit */
#define POWER_MIN -90.0
diff --git a/src/xmms.c b/src/xmms.c
index 7f3edf0a27fd762d3b18f93ff4c8f2a0a8a05a16..09786fc9282b6f01bd8568750b771e4f8df039ea 100644 (file)
--- a/src/xmms.c
+++ b/src/xmms.c
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "xmms", sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
- plugin_dispatch_values (type, &vl);
+ plugin_dispatch_values (&vl);
} /* void cxmms_submit */
int cxmms_read (void)
diff --git a/version-gen.sh b/version-gen.sh
index a9157cdef03cfdf52ac19cc75956ae387c17c019..246c7a895a45a426c3e81cf94f6bea2991bd8d99 100755 (executable)
--- a/version-gen.sh
+++ b/version-gen.sh
#!/bin/sh
-DEFAULT_VERSION="4.4.3.git"
+DEFAULT_VERSION="4.5.0.git"
VERSION="$( git describe 2> /dev/null | sed -e 's/^collectd-//' )"