author | Florian Forster <octo@collectd.org> | |
Mon, 28 Nov 2016 20:48:36 +0000 (21:48 +0100) | ||
committer | Florian Forster <octo@collectd.org> | |
Mon, 28 Nov 2016 20:48:36 +0000 (21:48 +0100) |
277 files changed:
diff --git a/.clang-format b/.clang-format
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,5 @@
+---
+BasedOnStyle: LLVM
+IncludeCategories:
+ - Regex: '"collectd.h"'
+ - Priority: -1
diff --git a/.github/issue_template.md b/.github/issue_template.md
--- /dev/null
@@ -0,0 +1,16 @@
+* Version of collectd:
+* Operating system / distribution:
+
+## Expected behavior
+
+(Description of the behavior / output that you expected)
+
+## Actual behavior
+
+(Description of the behavior / output that you observed)
+
+## Steps to reproduce
+
+* step 1
+* step 2
+* step 3
diff --git a/.gitignore b/.gitignore
index 54eaa9748ef6240a0e8cd12650275d6536892f53..8154d73329ba87a31d90b4182d815f447ddabe21 100644 (file)
--- a/.gitignore
+++ b/.gitignore
config.log
config.status
libtool
-src/.deps
src/collectd.conf
src/config.h
src/libcollectdclient/libcollectdclient.pc
*.lo
*.o
.libs/
-src/collectd
+.deps/
src/collectd-nagios
src/collectd-tg
src/collectdctl
# protobuf stuff:
src/*.pb-c.[ch]
+src/*.grpc.pb.cc
+src/*.pb.cc
+src/*.pb.h
# make dist stuff:
/collectd-*.tar.gz
# python stuff
*.pyc
-# tag stuff
-src/tags
-
# backup stuff
*~
-# tests stuff
-src/tests/.deps/
-src/tests/mock/.deps/
-src/tests/.dirstamp
-src/tests/mock/.dirstamp
-test*.log
-# new daemon repo
-src/daemon/.deps/
-src/daemon/.dirstamp
+# lint stuff
+*.ln
+
+#ide stuff
+.vscode
+
+# cscope stuff
+cscope.*
+
+# Unit tests
+src/daemon/test-suite.log
+src/tests/
+src/test-suite.log
+test_*
+
+# src/daemon/...
src/daemon/collectd
diff --git a/.travis.yml b/.travis.yml
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,56 @@
+sudo: required
+dist: trusty
+compiler:
+ - gcc
+ - clang
+language: c
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install -qq --no-install-recommends
+ iptables-dev
+ libatasmart-dev
+ libcap-dev
+ libcurl4-gnutls-dev
+ libdbi0-dev
+ libesmtp-dev
+ libganglia1-dev
+ libgcrypt11-dev
+ libglib2.0-dev
+ libhiredis-dev
+ libi2c-dev
+ libldap2-dev
+ libltdl-dev
+ liblvm2-dev
+ libmemcached-dev
+ libmnl-dev
+ libmodbus-dev
+ libmosquitto0-dev
+ libmysqlclient-dev
+ libnotify-dev
+ libopenipmi-dev
+ liboping-dev
+ libow-dev
+ libpcap-dev
+ libperl-dev
+ libpq-dev
+ libprotobuf-c0-dev
+ librabbitmq-dev
+ librdkafka-dev
+ librrd-dev
+ libsensors4-dev
+ libsigrok-dev
+ libsnmp-dev
+ libstatgrab-dev
+ libtokyocabinet-dev
+ libtokyotyrant-dev
+ libudev-dev
+ libupsclient-dev
+ libvarnish-dev
+ libvirt-dev
+ libxml2-dev
+ libyajl-dev
+ linux-libc-dev
+ perl
+ protobuf-c-compiler
+ python-dev
+script: sh build.sh && ./configure --with-python=/usr/bin/python && make distcheck DISTCHECK_CONFIGURE_FLAGS="--with-python=/usr/bin/python"
index 3f63c3dcd5591c72131b4bfa3dc579d9bc5e36cc..28220e79a6e7e6c723f7dfddcc29bb64990094ed 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
Florian "octo" Forster <octo at verplant.org>
- Initial author.
+Marc Fournier <marc.fournier at camptocamp.com>
+ - Various fixes to the varnish plugin.
+ - RPM specfile maintenance.
+ - libmnl support in the netlink plugin.
+ - linux support in the zfs_arc plugin.
+ - openldap plugin.
+ - continuous integration system.
+
+Pierre-Yves Ritschard <pyr at spootnik.org>
+ - Write-Riemann plugin.
+ - Write-Graphite plugin: Notification support.
+ - Write-Kafka plugin.
+ - Log-Logstash plugin.
+ - Normalization in the CPU plugin.
+ - Relative values in the Load plugin.
+
+Ruben Kerkhof <ruben at rubenkerkhof.com>
+ - Bugfixes and enhancements in many places all around the project.
+ - Fedora and EPEL packages.
+
Sebastian "tokkee" Harl <sh at tokkee.org>
- Bugfixes and enhancements in many places all around the project.
+ - grpc plugin.
- perl plugin.
+ - postgresql plugin.
- users plugin.
- vserver plugin.
- Debian package.
- The version 3 `log' mode.
- Many Solaris related hints and fixes.
+Claudius Zingerli <gitmail at zeuz.ch>
+ - chrony plugin.
+
Cyril Feraudet <cyril at feraudet.com>
- ethstat plugin.
+Dagobert Michelsen <dam at opencsw.org>
+ - zone plugin.
+ - Many Solaris related hints and fixes.
+
Dan Berrange <berrange at redhat.com>
- uuid plugin.
Franck Lombardi
- UNIX socket code for the memcached plugin.
+Gergely Nagy <algernon at madhouse-project.org>
+ - Write-Riemann plugin.
+
Jason Pepas <cell at ices.utexas.edu>
- nfs plugin.
Jiri Tyr <jiri.tyr at gmail.com>
- fhcount plugin.
+Julien Ammous <j.ammous at gmail.com>
+ - Lua plugin.
+
Kevin Bowling <kbowling at llnw.com>
- write_tsdb plugin for http://opentsdb.net/
+ swap
- Various AIX-related fixes and hacks.
-Marc Fournier <marc.fournier at camptocamp.com>
- - Various fixes to the varnish plugin.
- - RPM specfile update.
- - libmnl support in the netlink plugin.
- - linux support in the zfs_arc plugin.
- - openldap plugin.
-
Marco Chiappero <marco at absence.it>
- uptime plugin.
- ip6tables support in the iptables plugin.
- openvpn plugin (support for more status file formats)
+Mathijs Möhlmann <collectd at mmrc.nl>
+ - zone plugin.
+
Michael Hanselmann <public at hansmi.ch>
- md plugin.
Mirko Buffoni <briareos at eswat.org>
- Port/Socket selection in the MySQL plugin.
+Nicolas Jourden <nicolas.jourden at laposte.net>
+ - gps plugin.
+
Niki W. Waibel <niki.waibel at newlogic.com>
- Initial autotools fixes.
- libltdl code.
- `ReportByDevice' option of the df plugin.
- write_http plugin.
+Pavel Rochnyack <pavel2000 at ngs.ru>
+ - xencpu plugin.
+ - Bugfixes and enhancements in many places all around the project.
+
Peter Holik <peter at holik.at>
- cpufreq plugin.
- multimeter plugin.
Phoenix Kayo <kayo.k11.4 at gmail.com>
- pinba plugin.
-Pierre-Yves Ritschard <pyr at spootnik.org>
- - Write-Riemann plugin.
- - Write-Graphite plugin: Notification support.
- - Write-Kafka plugin.
- - Log-Logstash plugin.
- - Normalization in the CPU plugin.
- - Relative values in the Load plugin.
-
Piotr Hosowicz <the55 at wp.pl>
- SMF manifest for collectd.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,57 @@
+# Contribution guidelines
+
+Thanks for taking the time to contribute to the [collectd
+project](https://collectd.org/)! This document tries to give some guidance to
+make the process of contributing to *collectd* as pleasant and possible.
+
+## Bug reports
+
+Please report bugs as [GitHub
+Issues](https://github.com/collectd/collectd/issues). Try to answer the
+following questions:
+
+* Which version of *collectd* are you using?
+* Which operating system (distribution) are you using at which version?
+* What is the expected behavior / output?
+* What is the actual (observed) behavior / output?
+* How can we reproduce the problem you're having?
+* If *collectd* crashes, try to get a
+ [stack trace](https://collectd.org/wiki/index.php/Core_file).
+
+Please monitor your issue for a couple of days and reply to questions. To keep
+the project manageable have to do some housekeeping, meaning we will close
+issues that have become stale.
+
+## Code contributions
+
+Please open a [GitHub Pull Request](https://github.com/collectd/collectd/pulls)
+(PR) to contribute bug fixes, features, cleanups, new plugins, … Patches sent to
+the mailing list have a tendency to fall through the cracks.
+
+* *Focus:* Fix *one thing* in your PR. The smaller your change, the faster it
+ will be reviewed and merged.
+* *Coding style:* Please run `clang-format -style=file -i $FILE` on new files.
+ For existing files, please blend into surrounding code, i.e. mimic the
+ coding style of the code around your changes.
+* *Documentation:* New config options need to be documented in two places: the
+ manpage (`src/collectd.conf.pod`) and the example config
+ (`src/collectd.conf.in`).
+* *Continuous integration:* Once your PR is created, our continuous
+ integration environment will try to build it on a number of platforms. If
+ this reports a failure, please investigate and fix the problem. We will at
+ best do a very casual review for failing PRs.
+* *Don't rebase:* Rebasing your branch destroys the review history. If a review
+ takes a long time, we may ask you to rebase on a more recent *master*, but
+ please don't do it without being asked.
+* *types.db:* One of the most common mistakes made by new contributors is the
+ addition of (many) new *types* in the file `src/types.db`. The majority of
+ usecases can be met with one of the existing entries. If you plan to add new
+ entries to `src/types.db`, you should talk to us early in the design
+ process.
+
+## Other resources
+
+* [Mailing list](http://mailman.verplant.org/listinfo/collectd)
+* [#collectd IRC channel](https://webchat.freenode.net/?channels=#collectd)
+ on *freenode*.
+* [Old patch submission guideline](https://collectd.org/wiki/index.php/Submitting_patches)
diff --git a/ChangeLog b/ChangeLog
index 87645451d42f6fae791a7c7d38236dcce2ede6c8..771ce9c663be509dea1637e75e53c7902b1feaac 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+2016-10-07, Version 5.6.1
+ * Build system: Unnecessary linking of the Write Graphite plugin with
+ libyajl has been removed. Thanks to Marc Fournier.
+ Debian#839771, #1976
+ * collectd: A bug in the "FlushInterval" option that caused a
+ segmentation fault in the Write HTTP plugin has been fixed. Thanks to
+ Florian Forster. #1954
+ * Apache plugin: A syntax error has been fixed. Thanks to Florian
+ Forster.
+ * cURL-JSON plugin: A segmentation fault that occurred when handling
+ JSON with unexpected structure has been fixed. Thanks to Florian
+ Forster. #1896
+ * PostgreSQL plugin: Handling of "NULL" values in the "query_plans" and
+ "query_plans_by_table" queries has been fixed. Thanks to Bernd
+ Zeimetz. #1905
+ * RRDCacheD plugin: Reconnection behavior has been added. Thanks to
+ Sebastian Harl. Debian#657877
+ * VServer plugin: Use of a deprecated API ("readdir_r()") has been
+ fixed. Thanks to Sebastian Harl.
+ * Write Graphite plugin: Make default values configurable at compile
+ time again. Thanks to Florian Forster. #1953
+ * Write HTTP plugin: A bug has been fixed that lead to flush callbacks
+ being registered twice. Thanks to Florian Forster. #1955
+
+2016-09-11, Version 5.6.0
+ * Build system: An option to to avoid building the DF plugin against XFS
+ has been added. Thanks to Ruben Kerkhof. #1878
+ * Build system: Autoconf ≥ 2.60, a C99-capable compiler and pkg-config
+ are now required. Thanks to Ruben Kerkhof.
+ * Build system: Building with "-Werror" is now optional. Thanks to Ruben
+ Kerkhof. #1222
+ * Build system: Many compilation issues on non-Linux platforms have been
+ fixed, leading to wider plugin support. Thanks to Ruben Kerkhof,
+ Dagobert Michelsen, Havard Eidnes and Robert Viduya.
+ * Build system: The configuration summary now also ends up in
+ config.log. Thanks to Sebastian Harl.
+ * collectd: All command-line options now override global options from
+ the config file. Thanks to Sebastian Harl. #366
+ * collectd: A number of unit tests for commonly used functions have been
+ added. Thanks to Florian Forster.
+ * collectd: Plugins start up and read timeouts are now logged. Thanks to
+ Marc Fournier. #1293, #1254
+ * collectd: Support for a timeout has been added to "FLUSH" callbacks.
+ Thanks to Manuel Luis Sanmartín Rozada.
+ * collectd: The "-T" command line switch now reports more errors. Thanks
+ to Corey Kosak. #1642
+ * collectd: The max size of value list elements ("DATA_MAX_NAME_LEN")
+ has been doubled and is now configurable at build time. Thanks to Amy
+ Lin, Florian Forster and Radu Brumariu. #1120
+ * Set target: The "MetaData" option has been added. Thanks to Yves
+ Mettier and Kevin Bowling. #1106, #1656, #1913
+ * AMQP, Write_HTTP, Write_Kafka plugins: Support for libyajl < 2 has
+ been added. Thanks to Florian Forster.
+ * APC UPS plugin: Parsing of end markers has been fixed. Thanks to
+ Florian Forster #617
+ * APC UPS plugin: The "PersistentConnection" option has been added.
+ Thanks to Florian Forster #617
+ * ceph, DNS, Exec, IPTables, Ping, turbostat plugins: When running
+ unprivileged, these plugins will now warn about insuffiscient
+ permissions or capabilities(7). Thanks to Marc Fournier. #1530
+ * Chrony plugin: This new plugin collects NTP data from the chrony NTP
+ server. Thanks to Claudius Zingerli. #1548
+ * cpusleep plugin: This new plugin measures time spent by CPU in deep
+ sleep mode. Thanks to Rinigus. #1826
+ * CPU plugin: The "ReportNumCpu" option has been added. Thanks to Fabien
+ Wernli.
+ * cURL, cURL-JSON, cURL-XML plugins: The new "Statistics" reports
+ various per-HTTP connection timers. Thanks to Sebastian Harl. #1004
+ * DBI plugin: The "Interval" option has been added to "Database" blocks.
+ Thanks to Michal Bebjak.
+ * Disk plugin: Support for FreeBSD has been added. Thanks to Xin Li,
+ Brad Davis, Ruben Kerfhof and Kevin Bowling.
+ * Empty Counter match: Support for derives has been implemented. Thanks
+ to Florian Forster. #1813
+ * GenericJMX plugin: Support for TabularData and the "PluginName" option
+ have been added. Thanks to David Crane. #1290, #1291
+ * GPS plugin: This new plugin reports the number of sattelites seen by
+ and precision of a GPS receiver. Thanks to Nicolas Jourden. #1346
+ * gRPC plugin: This new client and server plugin allows sending and
+ receiving metrics using the gRPC protocol. Comparable to the UnixSock
+ plugin, but using TCP and TLS. Thanks to Sebastian Harl and Florian
+ Forster.
+ * Interface plugin: Reporting dropped packets has been added. Thanks to
+ Marc Falzon. #1555
+ * Interface plugin: The "ReportInactive" has been added, letting users
+ skip inactive network interfaces. Thanks to Rinigus. #1791
+ * Interface plugin: The new, Solaris-only "UniqueName" option has been
+ added. Thanks to Yoga Ramalingam. #1416
+ * Lua plugin: This new language binding allows writing plugins using the
+ Lua programming language. Thanks to Julien Ammous, Florian Forster and
+ Ruben Kerkhof.
+ * Memory plugin: Reporting of ARC memory on Solaris has been added.
+ Thanks to Brian ONeill.
+ * MQTT plugin: This new plugin sends metrics to and/or receives metrics
+ from an MQTT broker. Thanks to Marc Falzon, Jan-Piet Mens, Nicholas
+ Humfrey and Florian Forster. #805, #1124
+ * MySQL plugin: Connection to the database server can now be done over
+ SSL. Thanks to Brian Lalor. #1256
+ * MySQL plugin: Monitoring slow queries has been added. Thanks to skob.
+ #1773
+ * MySQL plugin: mysql_bpool_pages-flushed has been renamed to
+ mysql_bpool_counters-pages_flushed because the value is cumulative.
+ Thanks to Marek Becka.
+ * MySQL plugin: Support for Galera statistics has been added. Thanks to
+ Rachid Zarouali. #1849
+ * MySQL plugin: Support for InnoDB metrics was improved. Thanks to Aman
+ Gupta. #1111
+ * MySQL plugin: The "mysql_sort" type has been split into 3 different
+ types. Thanks to Pavel Rochnyack. #1592
+ * Network plugin: Decryption error logging has been improved. Thanks to
+ Pavel Rochnyack. #1735
+ * Notify Nagios plugin: This new plugin sends notifications to Nagios as
+ a passive check result. Thanks to Florian Forster.
+ * NTPd plugin: The plugin now detects if the ntp daemon reports
+ nanoseconds instead of microseconds. Thanks to Matwey V. Kornilov.
+ #1783
+ * OpenLDAP plugin: Several connection-related improvements have been
+ made. Thanks to Marc Fournier. #1308
+ * OpenLDAP plugin: Support for "simple authentication" has been added.
+ Thanks to Marek Becka. #1087
+ * Ping plugin: The "Size" option has been added, allowing the ICMP data
+ payload size to be configured. Thanks to Witold Baryluk. #1395
+ * PostgreSQL, DBI, Oracle plugins: The new "PluginInstanceFrom" option
+ has been added. Thanks to Pavel Rochnyack. #1707
+ * PowerDNS plugin: The recursor metrics have been updated to 3.7.3 and
+ missing rr types have been added. Thanks to Ruben Kerkhof.
+ * Processes plugin: Counting of context switches was added for Linux.
+ Thanks to Manuel Luis Sanmartín Rozada. #1036
+ * Processes plugin: Improve reliability of thread counts on Linux.
+ Thanks to Manuel Luis Sanmartín Rozada.
+ * Python plugin: Minimal Python version requirement has been bumped to
+ 2.6. Thanks to Ruben Kerkhof. #1864
+ * Redis plugin: Several additional metrics are now collected. Thanks to
+ Marc Falzon and Matteo Contrini. #1807, #1483
+ * Sensors plugin: The "UseLabels" option has been added. Thanks to
+ Christian Fetzer.
+ * SMART plugin: The new "IgnoreSleepMode" option has been added. Thanks
+ to Scott Talbert. #1770
+ * SMART plugin: The new "UseSerial" option allows identifying devices in
+ a stable way. Thanks to Scott Talbert. #1794
+ * SNMP plugin: The "IpAddress" can now be used for instances. Thanks to
+ Vincent Bernat. #1397
+ * StatsD plugin: Latency calculation histogram is now able to shrink
+ automatically to optimal size. Thanks to Pavel Rochnyack. #1622
+ * StatsD plugin: The "CounterSum" option has been added. Thanks to
+ Florian Forster. #929, #1282, #1311
+ * UUID plugin: The plugin now also looks in in smbios system table and
+ "/sys/class/dmi". Thanks to Ruben Kerkhof. #1490
+ * virt plugin: The "PluginInstanceFormat" option has been added. Thanks
+ to Ruben Kerkhof. #1100
+ * Write Graphite plugin: The "ReconnectInterval" option has been added.
+ Thanks to Toni Moreno and Florian Forster.
+ * Write HTTP plugin: A KairosDB formatter has been added. Thanks to
+ Aurélien Rougemont. #1809
+ * Write HTTP plugin: Notifications are now handled by this plugin.
+ Thanks to Florian Forster.
+ * Write HTTP plugin: The "LogHttpError" option has been added. Thanks to
+ vzubko.
+ * Write HTTP plugin: The new "Headers" option allows setting custom HTTP
+ headers in outgoing requests. Thanks to Brandon Arp. #1634
+ * Write Kafka plugin: Key handling has been made more comprehensive and
+ reliable. Thanks to Florian Forster, Pierre-Yves Ritschard and Vincent
+ Bernat. #1765, #1695, #1393
+ * Write Redis plugin: The "Database", "MaxSetSize", "Prefix" and
+ "StoreRates" options have been added. Thanks to Brian Kelly and
+ Sebastian Pfahl.
+ * Write Riemann plugin: The new "BatchFlushTimeout" and "Timeout" option
+ have been added. Thanks to Pierre-Yves Ritschard and Gergely Nagy.
+ * Write Riemann plugin: This plugin now requires the riemann-c-client
+ library, version 1.6.0+. This adds support for submitting values to
+ Riemann over TLS. Thanks to Gergely Nagy. #986
+ * Write TSDB, Write Sensu, Write Riemann, Write Graphite, Write TSDB
+ plugin: TCP keepalive is now enabled, helping graceful recovery from
+ unclean network disconnections. Thanks to Marc Fournier. #1549
+ * XenCPU plugin: This new plugin collects XEN Hypervisor CPU stats.
+ Thanks to Pavel Rochnyack. #1608
+ * ZFS ARC plugin: Several new statistics have been added and a couple of
+ obsolete ones removed. Thanks to Brad Davis, Brian ONeill and Ruben
+ Kerkhof.
+ * Zone plugin: This new plugin reads per-zone CPU usage on Solaris.
+ Thanks to Mathijs Mohlmann and Dagobert Michelsen.
+
2016-11-28, Version 5.5.3
* collectd: Write threads are stopped before shutdown callbacks are
called. Thanks to Florian Forster. #1110
diff --git a/Makefile.am b/Makefile.am
index b79ea1cabfbdc562cfcd46983771b1351d6a5d23..03bdd39a3500abf9cd514b02881583510b392238 100644 (file)
--- a/Makefile.am
+++ b/Makefile.am
SUBDIRS += libltdl
endif
-SUBDIRS += src bindings .
+SUBDIRS += proto src bindings .
AM_CPPFLAGS = $(LTDLINCL)
-EXTRA_DIST = contrib version-gen.sh
+EXTRA_DIST = contrib version-gen.sh testwrapper.sh
install-exec-hook:
$(mkinstalldirs) $(DESTDIR)$(localstatedir)/run
index 3e2c0233adc3ea9ccfbcbbf072c107a0f6dcbd5b..ee909d640c328868f37a9ea04d9414443343ecc8 100644 (file)
--- a/README
+++ b/README
collectd - System information collection daemon
=================================================
-http://collectd.org/
+https://collectd.org/
About
-----
- cgroups
CPU accounting information for process groups under Linux.
+ - chrony
+ Chrony daemon statistics: Local clock drift, offset to peers, etc.
+
- conntrack
Number of nf_conntrack entries.
- cpufreq
CPU frequency (For laptops with speed step or a similar technology)
+ - cpusleep
+ CPU sleep: Time spent in suspend (For mobile devices which enter suspend automatically)
+
- curl
Parse statistics from websites using regular expressions.
- gmond
Receive multicast traffic from Ganglia instances.
+ - gps
+ Monitor gps related data through gpsd.
+
+ - grpc
+ Receive values over the network using the gRPC framework.
+
- hddtemp
Hard disk temperatures using hddtempd.
Detailed CPU statistics of the “Logical Partitions” virtualization
technique built into IBM's POWER processors.
+ - lua
+ The Lua plugin implements a Lua interpreter into collectd. This
+ makes it possible to write plugins in Lua which are executed by
+ collectd without the need to start a heavy interpreter every interval.
+ See collectd-lua(5) for details.
+
- lvm
Size of “Logical Volumes” (LV) and “Volume Groups” (VG) of Linux'
“Logical Volume Manager” (LVM).
Reads values from Modbus/TCP enabled devices. Supports reading values
from multiple "slaves" so gateway devices can be used.
+ - mqtt
+ Publishes and subscribes to MQTT topics.
+
- multimeter
Information provided by serial multimeters, such as the `Metex
M-4650CR'.
- wireless
Link quality of wireless cards. Linux only.
+ - xencpu
+ XEN Hypervisor CPU stats.
+
- xmms
Bitrate and frequency of music played with XMMS.
- zfs_arc
Statistics for ZFS' “Adaptive Replacement Cache” (ARC).
+ - zone
+ Measures the percentage of cpu load per container (zone) under Solaris 10
+ and higher
+
- zookeeper
Read data from Zookeeper's MNTR command.
diskspace but is extremely portable and can be analysed with almost
every program that can analyse anything. Even Microsoft's Excel..
+ - lua
+ It's possible to implement write plugins in Lua using the Lua
+ plugin. See collectd-lua(5) for details.
+
- network
Send the data to a remote host to save the data somehow. This is useful
for large setups where the data should be saved by a dedicated machine.
Send an E-mail with the notification message to the configured
recipients.
+ - notify_nagios
+ Submit notifications as passive check results to a local nagios instance.
+
- exec
Execute a program or script to handle the notification.
See collectd-exec(5).
Used by the `gmond' plugin to process data received from Ganglia.
<http://ganglia.info/>
+ * libgrpc (optional)
+ Used by the `grpc' plugin. gRPC requires a C++ compiler supporting the
+ C++11 standard.
+ <https://grpc.io/>
+
* libgcrypt (optional)
Used by the `network' plugin for encryption and authentication.
<http://www.gnupg.org/>
+ * libgps (optional)
+ Used by the `gps' plugin.
+ <http://developer.berlios.de/projects/gpsd/>
+
* libhal (optional)
If present, the `uuid' plugin will check for UUID from HAL.
<http://hal.freedesktop.org/>
Used by the `openldap' plugin.
<http://www.openldap.org/>
+ * liblua (optional)
+ Used by the `lua' plugin. Currently, Lua 5.1 and later are supported.
+ <https://www.lua.org/>
+
* liblvm2 (optional)
Used by the `lvm' plugin.
<ftp://sources.redhat.com/pub/lvm2/>
The PostgreSQL C client library used by the `postgresql' plugin.
<http://www.postgresql.org/>
+ * libprotobuf, protoc 3.0+ (optional)
+ Used by the `grpc' plugin to generate service stubs and code to handle
+ network packets of collectd's protobuf-based network protocol.
+ <https://developers.google.com/protocol-buffers/>
+
* libprotobuf-c, protoc-c (optional)
Used by the `pinba' plugin to generate a parser for the network packets
- sent by the Pinba PHP extension, and by the `write_riemann' plugin to
- generate events to be sent to a Riemann server.
+ sent by the Pinba PHP extension.
<http://code.google.com/p/protobuf-c/>
* libpython (optional)
- Used by the `python' plugin. Currently, Python 2.3 and later and Python 3
+ Used by the `python' plugin. Currently, Python 2.6 and later and Python 3
are supported.
<http://www.python.org/>
`virt' plugins.
<http://xmlsoft.org/>
+ * libxen (optional)
+ Used by the `xencpu' plugin.
+ <http://xenbits.xensource.com/>
+
* libxmms (optional)
<http://www.xmms.org/>
`varnish' plugin.
<http://varnish-cache.org>
+ * riemann-c-client (optional)
+ For the `write_riemann' plugin.
+ <https://github.com/algernon/riemann-c-client>
+
Configuring / Compiling / Installing
------------------------------------
library checks succeed.
If this doesn't work for you, you have the possibility to specify CPP-flags,
- C-flags and LD-flags for the ‘Java’ plugin by hand, using the following three
- (environment) variables:
+ C-flags, LD-flags and LIBS for the ‘Java’ plugin by hand, using the
+ following environment variables:
- JAVA_CPPFLAGS
- JAVA_CFLAGS
- JAVA_LDFLAGS
+ - JAVA_LIBS
For example (shortened for demonstration purposes):
./configure JAVA_CPPFLAGS="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
- Adding "-ljvm" to the JAVA_LDFLAGS is done automatically, you don't have to
+ Adding "-ljvm" to JAVA_LIBS is done automatically, you don't have to
do that.
Generating the configure script
- bison
- libtool
- libtool-ltdl
+- pkg-config
The `build.sh' script takes no arguments.
Sebastian tokkee Harl <sh at tokkee.org>,
and many contributors (see `AUTHORS').
- Please send bug reports and patches to the mailing list, see `Contact'
- above.
-
+ Please use GitHub reporting bugs and submitting pull requests.
+ See CONTRIBUTING.md for details.
diff --git a/bindings/java/org/collectd/java/GenericJMXConfConnection.java b/bindings/java/org/collectd/java/GenericJMXConfConnection.java
index ea0f2fa2e54a1a3eabe7ca65517ac336c60ca40d..887c289562ac09ed17a3aac76efcea88394b1393 100644 (file)
private String _host = null;
private String _instance_prefix = null;
private String _service_url = null;
- private MBeanServerConnection _jmx_connection = null;
+ private JMXConnector _jmx_connector = null;
+ private MBeanServerConnection _mbean_connection = null;
private List<GenericJMXConfMBean> _mbeans = null;
/*
return Collectd.getHostname();
} /* }}} String getHost */
-private void connect () /* {{{ */
-{
- JMXServiceURL service_url;
- JMXConnector connector;
- Map environment;
+ private void connect () /* {{{ */
+ {
+ JMXServiceURL service_url;
+ Map<String,Object> environment;
- if (_jmx_connection != null)
- return;
+ // already connected
+ if (this._jmx_connector != null) {
+ return;
+ }
- environment = null;
- if (this._password != null)
- {
- String[] credentials;
+ environment = null;
+ if (this._password != null)
+ {
+ String[] credentials;
- if (this._username == null)
- this._username = new String ("monitorRole");
+ if (this._username == null)
+ this._username = new String ("monitorRole");
- credentials = new String[] { this._username, this._password };
+ credentials = new String[] { this._username, this._password };
- environment = new HashMap ();
- environment.put (JMXConnector.CREDENTIALS, credentials);
- environment.put(JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader());
- }
+ environment = new HashMap<String,Object> ();
+ environment.put (JMXConnector.CREDENTIALS, credentials);
+ environment.put (JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader());
+ }
- try
- {
- service_url = new JMXServiceURL (this._service_url);
- connector = JMXConnectorFactory.connect (service_url, environment);
- _jmx_connection = connector.getMBeanServerConnection ();
- }
- catch (Exception e)
+ try
+ {
+ service_url = new JMXServiceURL (this._service_url);
+ this._jmx_connector = JMXConnectorFactory.connect (service_url, environment);
+ this._mbean_connection = _jmx_connector.getMBeanServerConnection ();
+ }
+ catch (Exception e)
+ {
+ Collectd.logError ("GenericJMXConfConnection: "
+ + "Creating MBean server connection failed: " + e);
+ disconnect ();
+ return;
+ }
+ } /* }}} void connect */
+
+ private void disconnect () /* {{{ */
{
- Collectd.logError ("GenericJMXConfConnection: "
- + "Creating MBean server connection failed: " + e);
- return;
- }
-} /* }}} void connect */
+ try
+ {
+ if (this._jmx_connector != null) {
+ this._jmx_connector.close();
+ }
+ }
+ catch (Exception e)
+ {
+ // It's fine if close throws an exception
+ }
-/*
- * public methods
- *
- * <Connection>
- * Host "tomcat0.mycompany"
- * ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi"
- * Collect "java.lang:type=GarbageCollector,name=Copy"
- * Collect "java.lang:type=Memory"
- * </Connection>
- *
- */
+ this._jmx_connector = null;
+ this._mbean_connection = null;
+ } /* }}} void disconnect */
+
+ /*
+ * public methods
+ *
+ * <Connection>
+ * Host "tomcat0.mycompany"
+ * ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi"
+ * Collect "java.lang:type=GarbageCollector,name=Copy"
+ * Collect "java.lang:type=Memory"
+ * </Connection>
+ *
+ */
public GenericJMXConfConnection (OConfigItem ci) /* {{{ */
throws IllegalArgumentException
{
{
PluginData pd;
+ // try to connect
connect ();
- if (this._jmx_connection == null)
+ if (this._mbean_connection == null)
return;
Collectd.logDebug ("GenericJMXConfConnection.query: "
{
int status;
- status = this._mbeans.get (i).query (this._jmx_connection, pd,
+ status = this._mbeans.get (i).query (this._mbean_connection, pd,
this._instance_prefix);
if (status != 0)
{
- this._jmx_connection = null;
+ disconnect ();
return;
}
} /* for */
diff --git a/bindings/java/org/collectd/java/GenericJMXConfValue.java b/bindings/java/org/collectd/java/GenericJMXConfValue.java
index 4b42c91171036ca70d213d0f1131373f79b7f572..63b76282ecfa7ddbb38bfec94440876c33275230 100644 (file)
import java.util.Arrays;
import java.util.List;
+import java.util.Collection;
import java.util.Set;
import java.util.Iterator;
import java.util.ArrayList;
import javax.management.ObjectName;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
import javax.management.openmbean.InvalidKeyException;
import org.collectd.api.Collectd;
private List<String> _attributes;
private String _instance_prefix;
private List<String> _instance_from;
+ private String _plugin_name;
private boolean _is_table;
/**
{
if (value instanceof CompositeData)
return (queryAttributeRecursive ((CompositeData) value, attrName));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive ((TabularData) value, attrName));
+ else
+ return (null);
+ }
+ } /* }}} queryAttributeRecursive */
+
+ private Object queryAttributeRecursive (TabularData parent, /* {{{ */
+ List<String> attrName)
+ {
+ String key;
+ Object value = null;
+
+ key = attrName.remove (0);
+
+ @SuppressWarnings("unchecked")
+ Collection<CompositeData> table = (Collection<CompositeData>) parent.values();
+ for (CompositeData compositeData : table)
+ {
+ if (key.equals(compositeData.get("key")))
+ {
+ value = compositeData.get("value");
+ }
+ }
+ if (null == value)
+ {
+ return (null);
+ }
+
+ if (attrName.size () == 0)
+ {
+ return (value);
+ }
+ else
+ {
+ if (value instanceof CompositeData)
+ return (queryAttributeRecursive ((CompositeData) value, attrName));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive ((TabularData) value, attrName));
else
return (null);
}
{
if (value instanceof CompositeData)
return (queryAttributeRecursive((CompositeData) value, attrNameList));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive((TabularData) value, attrNameList));
else if (value instanceof OpenType)
{
OpenType ot = (OpenType) value;
else
{
Collectd.logError ("GenericJMXConfValue: Received object of "
- + "unknown class.");
+ + "unknown class. " + attrName + " " + ((value == null)?"null":value.getClass().getName()));
return (null);
}
}
this._attributes = new ArrayList<String> ();
this._instance_prefix = null;
this._instance_from = new ArrayList<String> ();
+ this._plugin_name = null;
this._is_table = false;
/*
if (tmp != null)
this._instance_from.add (tmp);
}
+ else if (child.getKey ().equalsIgnoreCase ("PluginName"))
+ {
+ String tmp = getConfigString (child);
+ if (tmp != null)
+ this._plugin_name = tmp;
+ }
else
throw (new IllegalArgumentException ("Unknown option: "
+ child.getKey ()));
vl = new ValueList (pd);
vl.setType (this._ds_name);
+ if (this._plugin_name != null)
+ {
+ vl.setPlugin (this._plugin_name);
+ }
/*
* Build the instnace prefix from the fixed string prefix and the
index 5e79d2682ecbb723ff094f1d12add49b15b72a76..304bbbc3ceccfdcaf7a5980de7dd46287ee8f3b6 100644 (file)
sub _escape_argument
{
- local $_ = shift;
+ my $arg = shift;
- return $_ if /^\w+$/;
+ return $arg if $arg =~ /^\w+$/;
- s#\\#\\\\#g;
- s#"#\\"#g;
- return "\"$_\"";
+ $arg =~ s#\\#\\\\#g;
+ $arg =~ s#"#\\"#g;
+ return "\"$arg\"";
}
# Send a command on a socket, including any required argument escaping.
return $cbdata;
}
+# Send a raw message on a socket.
+# Returns true upon success and false otherwise.
+sub _send_message
+{
+ my ($self, $msg) = @_;
+
+ my $fh = $self->{'sock'} or confess ('object has no filehandle');
+
+ $msg .= "\n" unless $msg =~/\n$/;
+
+ #1024 is default buffer size at unixsock.c us_handle_client()
+ warn "Collectd::Unixsock->_send_message(\$msg): message is too long!" if length($msg) > 1024;
+
+ _debug "-> $msg";
+ $fh->print($msg);
+
+ $msg = <$fh>;
+ chomp ($msg);
+ _debug "<- $msg\n";
+
+ my ($status, $error) = split / /, $msg, 2;
+ return 1 if $status == 0;
+
+ $self->{error} = $error;
+ return;
+}
=head1 PUBLIC METHODS
. _escape_argument ($identifier)
. $interval
. ' ' . _escape_argument ($values) . "\n";
- _debug "-> $msg";
- $fh->print($msg);
- $msg = <$fh>;
- chomp $msg;
- _debug "<- $msg\n";
-
- ($status, $msg) = split / /, $msg, 2;
- return 1 if $status == 0;
-
- $self->{error} = $msg;
- return;
+ return $self->_send_message($msg);
} # putval
=item I<$res> = I<$self>-E<gt>B<listval_filter> ( C<%identifier> )
. join (' ', map { $_ . '=' . _escape_argument ($args{$_}) } keys %args)
. "\n";
- _debug "-> $msg";
- $fh->print($msg);
-
- $msg = <$fh>;
- chomp $msg;
- _debug "<- $msg\n";
-
- ($status, $msg) = split / /, $msg, 2;
- return 1 if $status == 0;
-
- $self->{error} = $msg;
- return;
+ return $self->_send_message($msg);
} # putnotif
=item I<$self>-E<gt>B<flush> (B<timeout> =E<gt> I<$timeout>, B<plugins> =E<gt> [...], B<identifier> =E<gt> [...]);
my $fh = $self->{sock} or confess;
- my $status = 0;
my $msg = "FLUSH";
$msg .= " timeout=$args{timeout}" if defined $args{timeout};
if ($args{identifier})
{
+ my $pre = $msg;
for my $identifier (@{$args{identifier}})
{
my $ident_str;
}
$ident_str = _create_identifier ($identifier) or return;
- $msg .= ' identifier=' . _escape_argument ($ident_str);
+ $ident_str = ' identifier=' . _escape_argument ($ident_str);
+
+ if (length($msg)+length($ident_str) >= 1023) { #1024 - 1 byte for \n
+ $self->_send_message($msg) or return;
+ $msg = $pre;
+ }
+
+ $msg .= $ident_str;
}
}
-
- $msg .= "\n";
-
- _debug "-> $msg";
- $fh->print($msg);
-
- $msg = <$fh>;
- chomp ($msg);
- _debug "<- $msg\n";
-
- ($status, $msg) = split / /, $msg, 2;
- return 1 if $status == 0;
-
- $self->{error} = $msg;
- return;
+
+ return $self->_send_message($msg);
}
sub error
index 2f7818b15799cb650e6d2288072286f4426ac583..4e94f8e8d235f53fa742bd716a1b738b6aade28f 100644 (file)
my ($nresults, $resultdata) = @$results;
my $r = $s->getval(%{Collectd::Unixsock::_parse_identifier($attr)});
is(ref $r, 'HASH', "Got a result for $attr");
- is(scalar keys $r, $nresults, "$nresults result result for $attr");
+ is(scalar keys %$r, $nresults, "$nresults result result for $attr");
is_deeply($r, $resultdata, "Data or $attr matches");
}
diff --git a/build.sh b/build.sh
index 20854b13b7d88cf6aa90f5ce990fd07370fff56c..57f3d4449a99bef83b75b50f425dc548bc9ead60 100755 (executable)
--- a/build.sh
+++ b/build.sh
done
}
-check_for_application lex yacc autoheader aclocal automake autoconf
+check_for_application lex bison autoheader aclocal automake autoconf
# Actually we don't need the pkg-config executable, but we need the M4 macros.
# We check for `pkg-config' here and hope that M4 macros will then be
diff --git a/configure.ac b/configure.ac
index 7748be86c84c505b812172543d04871233731f42..a4603a9bbe2e1e90b40f1aec5523237bfeb8bc8c 100644 (file)
--- a/configure.ac
+++ b/configure.ac
dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ([2.60])
AC_INIT([collectd],[m4_esyscmd(./version-gen.sh)])
-AC_CONFIG_SRCDIR(src/)
+AC_CONFIG_SRCDIR(src/target_set.c)
AC_CONFIG_HEADERS(src/config.h)
AC_CONFIG_AUX_DIR([libltdl/config])
AM_CONDITIONAL([BUILD_INCLUDED_LTDL], [test "x$LTDLDEPS" != "x"])
-AM_INIT_AUTOMAKE([tar-pax dist-bzip2 foreign])
+AM_INIT_AUTOMAKE([subdir-objects tar-pax dist-bzip2 no-dist-gzip foreign])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_LANG(C)
#
# Checks for programs.
#
-AC_PROG_CC
+AC_PROG_CC_C99([],
+ [AC_MSG_ERROR([No compiler found that supports C99])]
+)
+AC_PROG_CXX
AC_PROG_CPP
AC_PROG_EGREP
AC_PROG_INSTALL
AC_PROG_LEX
AC_PROG_YACC
+AC_PATH_PROG([VALGRIND], [valgrind])
+
# Warn when pkg.m4 is missing
m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
AC_MSG_ERROR([bison is missing and you do not have ${srcdir}/src/liboconfig/parser.c. Please install bison])
fi
-AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no])
-if test "x$have_protoc_c" = "xno"
-then
- have_protoc_c="no (protoc-c compiler not found)"
+AC_ARG_VAR([PROTOC], [path to the protoc binary])
+AC_PATH_PROG([PROTOC], [protoc])
+have_protoc3="no"
+if test "x$PROTOC" != "x"; then
+ AC_MSG_CHECKING([for protoc 3.0.0+])
+ if $PROTOC --version | $EGREP libprotoc.3 >/dev/null; then
+ protoc3="yes (`$PROTOC --version`)"
+ have_protoc3="yes"
+ else
+ protoc3="no (`$PROTOC --version`)"
+ fi
+ AC_MSG_RESULT([$protoc3])
fi
+AM_CONDITIONAL(HAVE_PROTOC3, test "x$have_protoc3" = "xyes")
-if test "x$have_protoc_c" = "xyes"
-then
- AC_CHECK_HEADERS([protobuf-c/protobuf-c.h google/protobuf-c/protobuf-c.h],
- [have_protoc_c="yes"; break],
- [have_protoc_c="no (<google/protobuf-c/protobuf-c.h> not found)"])
-fi
-if test "x$have_protoc_c" = "xyes"
-then
- AC_CHECK_LIB([protobuf-c], [protobuf_c_message_pack],
- [have_protoc_c="yes"],
- [have_protoc_c="no (libprotobuf-c not found)"])
+AC_ARG_VAR([GRPC_CPP_PLUGIN], [path to the grpc_cpp_plugin binary])
+AC_PATH_PROG([GRPC_CPP_PLUGIN], [grpc_cpp_plugin])
+AM_CONDITIONAL(HAVE_GRPC_CPP, test "x$GRPC_CPP_PLUGIN" != "x")
+AC_ARG_VAR([PROTOC_C], [path to the protoc-c binary])
+AC_PATH_PROG([PROTOC_C], [protoc-c])
+if test "x$PROTOC_C" = "x"
+then
+ have_protoc_c="no (protoc-c compiler not found)"
+else
+ have_protoc_c="yes"
fi
-AM_CONDITIONAL(HAVE_PROTOC_C, test "x$have_protoc_c" = "xyes")
AC_MSG_CHECKING([for kernel type ($host_os)])
case $host_os in
AC_DEFINE([KERNEL_OPENBSD], 1, [True if program is to be compiled for an OpenBSD kernel])
ac_system="OpenBSD"
;;
+ *netbsd*)
+ AC_DEFINE([KERNEL_NETBSD], 1, [True if program is to be compiled for a NetBSD kernel])
+ ac_system="NetBSD"
+ ;;
*aix*)
AC_DEFINE([KERNEL_AIX], 1, [True if program is to be compiled for a AIX kernel])
ac_system="AIX"
esac
AC_MSG_RESULT([$ac_system])
-AM_CONDITIONAL([BUILD_LINUX],[test "x$ac_system" = "xLinux"])
-AM_CONDITIONAL([BUILD_SOLARIS],[test "x$ac_system" = "xSolaris"])
-AM_CONDITIONAL([BUILD_DARWIN],[test "x$ac_system" = "xDarwin"])
-AM_CONDITIONAL([BUILD_OPENBSD],[test "x$ac_system" = "xOpenBSD"])
-AM_CONDITIONAL([BUILD_AIX],[test "x$ac_system" = "xAIX"])
-AM_CONDITIONAL([BUILD_FREEBSD],[test "x$ac_system" = "xFreeBSD"])
+AM_CONDITIONAL([BUILD_AIX], [test "x$ac_system" = "xAIX"])
+AM_CONDITIONAL([BUILD_DARWIN], [test "x$ac_system" = "xDarwin"])
+AM_CONDITIONAL([BUILD_FREEBSD], [test "x$ac_system" = "xFreeBSD"])
+AM_CONDITIONAL([BUILD_LINUX], [test "x$ac_system" = "xLinux"])
+AM_CONDITIONAL([BUILD_OPENBSD], [test "x$ac_system" = "xOpenBSD"])
+AM_CONDITIONAL([BUILD_SOLARIS], [test "x$ac_system" = "xSolaris"])
if test "x$ac_system" = "xLinux"
then
AC_CHECK_HEADERS(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 fnmatch.h libgen.h)
+# For entropy plugin on newer NetBSD
+AC_CHECK_HEADERS(sys/rndio.h, [], [],
+[#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+])
+
# For ping library
AC_CHECK_HEADERS(netinet/in_systm.h, [], [],
[#if HAVE_STDINT_H
AC_MSG_CHECKING([for sysctl kern.cp_times])
if test -x /sbin/sysctl
then
- /sbin/sysctl kern.cp_times 2>/dev/null
+ /sbin/sysctl kern.cp_times >/dev/null 2>&1
if test $? -eq 0
then
AC_MSG_RESULT([yes])
AC_MSG_RESULT([no])
fi
+AC_MSG_CHECKING([for sysctl kern.cp_time])
+if test -x /sbin/sysctl
+then
+ /sbin/sysctl kern.cp_time >/dev/null 2>&1
+ if test $? -eq 0
+ then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_SYSCTL_KERN_CP_TIME, 1,
+ [Define if sysctl supports kern.cp_time])
+ else
+ AC_MSG_RESULT([no])
+ fi
+else
+ AC_MSG_RESULT([no])
+fi
+
# For hddtemp module
AC_CHECK_HEADERS(linux/major.h)
have_linux_raid_md_u_h="no"
fi
-# For the swap module
+# For the wireless module
have_linux_wireless_h="no"
if test "x$ac_system" = "xLinux"
then
wordexp.h \
])
-AC_CHECK_HEADERS([xfs/xqm.h], [], [],
-[
-#define _GNU_SOURCE
-])
+# --enable-xfs {{{
+AC_ARG_ENABLE([xfs],
+ [AS_HELP_STRING([--enable-xfs], [xfs support in df plugin @<:@default=yes@:>@])],
+ [],
+ [enable_xfs="auto"]
+)
+
+if test "x$enable_xfs" != "xno"; then
+ AC_CHECK_HEADERS([xfs/xqm.h],
+ [],
+ [
+ if test "x$enable_xfs" = "xyes"; then
+ AC_MSG_ERROR([xfs/xqm.h not found])
+ fi
+ ],
+ [[#define _GNU_SOURCE]]
+ )
+fi
+
+# }}}
# For the dns plugin
AC_CHECK_HEADERS(arpa/nameser.h)
#endif
])
-AC_CHECK_HEADERS(netinet/ip_compat.h)
-
have_net_pfvar_h="no"
AC_CHECK_HEADERS(net/pfvar.h,
[have_net_pfvar_h="yes"],
have_termios_h="no"
AC_CHECK_HEADERS(termios.h, [have_termios_h="yes"])
+# For cpusleep plugin
+AC_CACHE_CHECK([whether clock_boottime and clock_monotonic are supported],
+ [c_cv_have_clock_boottime_monotonic],
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <time.h>
+]],
+[[
+ struct timespec b, m;
+ clock_gettime(CLOCK_BOOTTIME, &b );
+ clock_gettime(CLOCK_MONOTONIC, &m );
+]]
+ )],
+ [c_cv_have_clock_boottime_monotonic="yes"],
+ [c_cv_have_clock_boottime_monotonic="no"]))
+
+
# For the turbostat plugin
have_asm_msrindex_h="no"
AC_CHECK_HEADERS(asm/msr-index.h, [have_asm_msrindex_h="yes"])
have_cpuid_h="no"
AC_CHECK_HEADERS(cpuid.h, [have_cpuid_h="yes"])
-AC_CHECK_HEADERS(sys/capability.h)
+have_capability="yes"
+AC_CHECK_HEADERS(sys/capability.h,
+ [have_capability="yes"],
+ [have_capability="no (<sys/capability.h> not found)"])
+if test "x$have_capability" = "xyes"; then
+AC_CHECK_LIB(cap, cap_get_bound,
+ [have_capability="yes"],
+ [have_capability="no (cap_get_bound() not found)"])
+fi
+if test "x$have_capability" = "xyes"; then
+ AC_DEFINE(HAVE_CAPABILITY, 1, [Define to 1 if you have cap_get_bound() (-lcap).])
+fi
+AM_CONDITIONAL(BUILD_WITH_CAPABILITY, test "x$have_capability" = "xyes")
+
#
# Checks for typedefs, structures, and compiler characteristics.
#
AC_C_CONST
-AC_C_INLINE
-AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
-AC_TYPE_SSIZE_T
AC_TYPE_UID_T
-AC_TYPE_UINT32_T
AC_HEADER_TIME
#
# Checks for library functions.
#
-AC_PROG_GCC_TRADITIONAL
-AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname setlocale)
+AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname setlocale asprintf)
AC_FUNC_STRERROR_R
+test_cxx_flags() {
+ AC_LANG_PUSH([C++])
+ AC_LANG_CONFTEST([
+ AC_LANG_SOURCE([[int main(void){}]])
+ ])
+ $CXX -c conftest.cpp $CXXFLAGS $@ > /dev/null 2> /dev/null
+ ret=$?
+ rm -f conftest.o
+ AC_LANG_POP([C++])
+ return $ret
+}
+
SAVE_CFLAGS="$CFLAGS"
# Emulate behavior of src/Makefile.am
if test "x$GCC" = "xyes"
if test "x$have_clock_gettime" = "xyes"
then
AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if the clock_gettime(2) function is available.])
-else
- AC_MSG_WARN(cannot find clock_gettime)
fi
nanosleep_needs_rt="no"
@@ -1305,6 +1400,20 @@ AC_ARG_WITH(useragent, [AS_HELP_STRING([--with-useragent@<:@=AGENT@:>@], [User a
# }}}
+# --with-data-max-name-len {{{
+AC_ARG_WITH(data-max-name-len, [AS_HELP_STRING([--with-data-max-name-len@<:@=VALUE@:>@], [Maximum length of data buffers])],
+[
+ if test "x$withval" != "x" && test $withval -gt 0
+ then
+ AC_DEFINE_UNQUOTED(DATA_MAX_NAME_LEN, [$withval], [Maximum length of data buffers])
+ else
+ AC_MSG_ERROR([DATA_MAX_NAME_LEN must be a positive integer -- $withval given])
+ fi
+],
+[ AC_DEFINE(DATA_MAX_NAME_LEN, 128, [Maximum length of data buffers])]
+)
+# }}}
+
have_getfsstat="no"
AC_CHECK_FUNCS(getfsstat, [have_getfsstat="yes"])
have_getvfsstat="no"
fi
if test "x$have_getmntent" = "xsun"; then
AC_DEFINE(HAVE_SUN_GETMNTENT, 1,
- [Define if the function getmntent exists. It's the version from libsun.])
+ [Define if the function getmntent exists. It is the version from libsun.])
fi
if test "x$have_getmntent" = "xseq"; then
AC_DEFINE(HAVE_SEQ_GETMNTENT, 1,
- [Define if the function getmntent exists. It's the version from libseq.])
+ [Define if the function getmntent exists. It is the version from libseq.])
fi
if test "x$have_getmntent" = "xgen"; then
AC_DEFINE(HAVE_GEN_GETMNTENT, 1,
- [Define if the function getmntent exists. It's the version from libgen.])
+ [Define if the function getmntent exists. It is the version from libgen.])
fi
# Check for htonll
#include <kvm.h>
])
+
+AC_CHECK_MEMBERS([struct kinfo_proc2.p_pid, struct kinfo_proc2.p_uru_maxrss],
+ [
+ AC_DEFINE(HAVE_STRUCT_KINFO_PROC2_NETBSD, 1,
+ [Define if struct kinfo_proc2 exists in the NetBSD variant.])
+ have_struct_kinfo_proc2_netbsd="yes"
+ ],
+ [
+ have_struct_kinfo_proc2_netbsd="no"
+ ],
+ [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <kvm.h>
+ ])
+
+
+
AC_CHECK_MEMBERS([struct udphdr.uh_dport, struct udphdr.uh_sport], [], [],
[#define _BSD_SOURCE
#define _DEFAULT_SOURCE
AM_CONDITIONAL(BUILD_WITH_LIBRESOLV, test "x$with_libresolv" = "xyes")
dnl Check for HAL (hardware abstraction library)
-with_libhal="yes"
-AC_CHECK_LIB(hal,libhal_device_property_exists,
- [AC_DEFINE(HAVE_LIBHAL, 1, [Define to 1 if you have 'hal' library])],
- [with_libhal="no"])
-if test "x$with_libhal" = "xyes"; then
- if test "x$PKG_CONFIG" != "x"; then
- BUILD_WITH_LIBHAL_CFLAGS="`$PKG_CONFIG --cflags hal`"
- BUILD_WITH_LIBHAL_LIBS="`$PKG_CONFIG --libs hal`"
- AC_SUBST(BUILD_WITH_LIBHAL_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBHAL_LIBS)
- fi
-fi
+with_libhal="no"
+PKG_CHECK_MODULES([HAL], [hal],
+ [
+ SAVE_LIBS="$LIBS"
+ LIBS="$HAL_LIBS $LIBS"
+ AC_CHECK_LIB([hal], [libhal_device_property_exists],
+ [
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$HAL_CFLAGS $CPPFLAGS"
+ AC_CHECK_HEADERS([libhal.h],
+ [
+ with_libhal="yes"
+ BUILD_WITH_LIBHAL_CFLAGS="$HAL_CFLAGS"
+ BUILD_WITH_LIBHAL_LIBS="$HAL_LIBS"
+ ])
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ ],
+ [ : ]
+ )
+ LIBS="$SAVE_LIBS"
+ ],
+ [ : ]
+)
+AC_SUBST(BUILD_WITH_LIBHAL_CFLAGS)
+AC_SUBST(BUILD_WITH_LIBHAL_LIBS)
+
+
+SAVE_LIBS="$LIBS"
+AC_CHECK_LIB([pthread],
+ [pthread_create],
+ [],
+ [AC_MSG_ERROR([Symbol 'pthread_create' not found in libpthread"])],
+ []
+)
+PTHREAD_LIBS="$LIBS"
+LIBS="$SAVE_LIBS"
+
+AC_CHECK_HEADERS([pthread.h],
+ [],
+ [AC_MSG_ERROR([pthread.h not found])]
+)
+AC_SUBST([PTHREAD_LIBS])
m4_divert_once([HELP_WITH], [
collectd additional packages:])
[[#include <curl/curl.h>]])
fi
fi
+if test "x$with_libcurl" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_curl_cflags"
+ LDFLAGS="$LDFLAGS $with_curl_libs"
+ AC_CACHE_CHECK([for CURLINFO_APPCONNECT_TIME],
+ [c_cv_have_curlinfo_appconnect_time],
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <curl/curl.h>
+]],
+[[
+int val = CURLINFO_APPCONNECT_TIME;
+return val;
+]]
+ )],
+ [c_cv_have_curlinfo_appconnect_time="yes"],
+ [c_cv_have_curlinfo_appconnect_time="no"]
+ )
+ )
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
+if test "x$c_cv_have_curlinfo_appconnect_time" = "xyes"
+then
+ AC_DEFINE(HAVE_CURLINFO_APPCONNECT_TIME, 1, [Define if curl.h defines CURLINFO_APPCONNECT_TIME.])
+fi
+
if test "x$with_libcurl" = "xyes"
then
BUILD_WITH_LIBCURL_CFLAGS="$with_curl_cflags"
AC_DEFINE(HAVE_CURLOPT_TIMEOUT_MS, 1, [Define if libcurl supports CURLOPT_TIMEOUT_MS option.])
fi
fi
-AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
# }}}
# --with-libdbi {{{
AC_CHECK_LIB(gcrypt, gcry_md_hash_buffer,
[with_libgcrypt="yes"],
[with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"])
-
- if test "$with_libgcrypt" != "no"; then
- m4_ifdef([AM_PATH_LIBGCRYPT],[AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")])
- GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS"
- GCRYPT_LIBS="$LIBGCRYPT_LIBS"
- fi
fi
CPPFLAGS="$SAVE_CPPFLAGS"
AM_CONDITIONAL(BUILD_WITH_LIBGCRYPT, test "x$with_libgcrypt" = "xyes")
# }}}
+# --with-libgps {{{
+with_libgps_cflags=""
+with_libgps_ldflags=""
+AC_ARG_WITH(libgps, [AS_HELP_STRING([--with-libgps@<:@=PREFIX@:>@], [Path to libgps.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libgps_cflags="-I$withval/include"
+ with_libgps_ldflags="-L$withval/lib"
+ with_libgps="yes"
+ else
+ with_libgps="$withval"
+ fi
+],
+[
+ with_libgps="yes"
+])
+if test "x$with_libgps" = "xyes"
+then
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $with_libgps_cflags"
+
+ AC_CHECK_HEADERS(gps.h, [with_libgps="yes"], [with_libgps="no (gps.h not found)"])
+
+ CFLAGS="$SAVE_CFLAGS"
+fi
+if test "x$with_libgps" = "xyes"
+then
+ SAVE_CFLAGS="$CFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CFLAGS="$CFLAGS $with_libgps_cflags"
+ LDFLAGS="$LDFLAGS $with_libgps_ldflags"
+
+ AC_CHECK_LIB(gps, gps_open, [with_libgps="yes"], [with_libgps="no (symbol gps_open not found)"])
+
+ CFLAGS="$SAVE_CFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libgps" = "xyes"
+then
+ BUILD_WITH_LIBGPS_CFLAGS="$with_libgps_cflags"
+ BUILD_WITH_LIBGPS_LDFLAGS="$with_libgps_ldflags"
+ BUILD_WITH_LIBGPS_LIBS="-lgps"
+ AC_SUBST(BUILD_WITH_LIBGPS_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBGPS_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBGPS_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBGPS, test "x$with_libgps" = "xyes")
+# }}}
+
+# --with-libgrpc++ {{{
+with_libgrpcpp_cppflags=""
+with_libgrpcpp_ldflags=""
+AC_ARG_WITH([libgrpc++], [AS_HELP_STRING([--with-libgrpc++@<:@=PREFIX@:>@], [Path to libgrpc++.])],
+ [
+ with_grpcpp="$withval"
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libgrpcpp_cppflags="-I$withval/include"
+ with_libgrpcpp_ldflags="-L$withval/lib"
+ with_libgrpcpp="yes"
+ fi
+ if test "x$withval" = "xno"
+ then
+ with_libgrpcpp="no (disabled on command line)"
+ fi
+ ],
+ [withval="yes"]
+)
+if test "x$withval" = "xyes"
+then
+PKG_CHECK_MODULES([GRPCPP], [grpc++],
+ [with_libgrpcpp="yes"],
+ [with_libgrpcpp="no (pkg-config could not find libgrpc++)"]
+)
+fi
+
+if test "x$withval" != "xno"
+then
+ AC_MSG_CHECKING([whether $CXX accepts -std=c++11])
+ if test_cxx_flags -std=c++11; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ with_libgrpcpp="no (requires C++11 support)"
+ fi
+fi
+
+if test "x$with_libgrpcpp" = "xyes"
+then
+ AC_LANG_PUSH(C++)
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="-std=c++11 $with_libgrpcpp_cppflags $GRPCPP_CFLAGS $CPPFLAGS"
+ AC_CHECK_HEADERS([grpc++/grpc++.h], [],
+ [with_libgrpcpp="no (<grpc++/grpc++.h> not found)"]
+ )
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ AC_LANG_POP(C++)
+fi
+if test "x$with_libgrpcpp" = "xyes"
+then
+ AC_LANG_PUSH(C++)
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_LIBS="$LIBS"
+ CPPFLAGS="-std=c++11 $with_libgrpcpp_cppflags $GRPCPP_CFLAGS $CPPFLAGS"
+ LDFLAGS="$with_libgrpcpp_ldflags"
+ if test "x$GRPCPP_LIBS" = "x"
+ then
+ LIBS="-lgrpc++"
+ else
+ LIBS="$GRPCPP_LIBS"
+ fi
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <grpc++/grpc++.h>]],
+ [[grpc::ServerBuilder sb;]]
+ )],
+ [
+ with_libgrpcpp="yes"
+ if test "x$GRPCPP_LIBS" = "x"
+ then
+ GRPCPP_LIBS="-lgrpc++"
+ fi
+ ],
+ [with_libgrpcpp="no (libgrpc++ not found)"]
+ )
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+ LIBS="$SAVE_LIBS"
+ AC_LANG_POP(C++)
+fi
+BUILD_WITH_LIBGRPCPP_CPPFLAGS="-std=c++11 $with_libgrpcpp_cppflags $GRPCPP_CFLAGS"
+BUILD_WITH_LIBGRPCPP_LDFLAGS="$with_libgrpcpp_ldflags"
+BUILD_WITH_LIBGRPCPP_LIBS="$GRPCPP_LIBS"
+AC_SUBST([BUILD_WITH_LIBGRPCPP_CPPFLAGS])
+AC_SUBST([BUILD_WITH_LIBGRPCPP_LDFLAGS])
+AC_SUBST([BUILD_WITH_LIBGRPCPP_LIBS])
+# }}}
+
# --with-libiptc {{{
AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
[
@@ -2158,11 +2478,6 @@ AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to l
fi
])
-if test "x$with_libiptc" = "xpkgconfig" && test "x$PKG_CONFIG" = "x"
-then
- with_libiptc="no (Don't have pkg-config)"
-fi
-
if test "x$with_libiptc" = "xpkgconfig"
then
$PKG_CONFIG --exists 'libiptc' 2>/dev/null
then
with_java_home="/usr/lib/jvm"
fi
-with_java_vmtype="client"
-with_java_cflags=""
-with_java_libs=""
JAVAC="$JAVAC"
JAR="$JAR"
AC_ARG_WITH(java, [AS_HELP_STRING([--with-java@<:@=PREFIX@:>@], [Path to Java home.])],
then
AC_MSG_NOTICE([Building with JAVA_LDFLAGS set to: $JAVA_LDFLAGS])
fi
+if test "x$JAVA_LIBS" != "x"
+then
+ AC_MSG_NOTICE([Building with JAVA_LIBS set to: $JAVA_LIBS])
+fi
if test "x$JAVAC" = "x"
then
with_javac_path="$PATH"
SAVE_CPPFLAGS="$CPPFLAGS"
SAVE_CFLAGS="$CFLAGS"
SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
CPPFLAGS="$CPPFLAGS $JAVA_CPPFLAGS"
CFLAGS="$CFLAGS $JAVA_CFLAGS"
LDFLAGS="$LDFLAGS $JAVA_LDFLAGS"
+LIBS="$LIBS $JAVA_LIBS"
if test "x$with_java" = "xyes"
then
then
AC_CHECK_LIB(jvm, JNI_CreateJavaVM,
[with_java="yes"],
- [with_java="no (libjvm not found)"],
- [$JAVA_LIBS])
+ [with_java="no (Symbol 'JNI_CreateJavaVM' not found)"],
+ [$JAVA_LIBS $PTHREAD_LIBS])
fi
if test "x$with_java" = "xyes"
then
CPPFLAGS="$SAVE_CPPFLAGS"
CFLAGS="$SAVE_CFLAGS"
LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
AC_SUBST(JAVA_CPPFLAGS)
AC_SUBST(JAVA_CFLAGS)
AM_CONDITIONAL(BUILD_WITH_LIBLDAP, test "x$with_libldap" = "xyes")
# }}}
+# --with-liblua {{{
+AC_ARG_VAR([LIBLUA_PKG_CONFIG_NAME], [Name of liblua used by pkg-config])
+if test "x$LIBLUA_PKG_CONFIG_NAME" != "x"
+then
+ PKG_CHECK_MODULES([LUA], [$LIBLUA_PKG_CONFIG_NAME],
+ [with_liblua="yes"],
+ [with_liblua="no"]
+ )
+else
+ PKG_CHECK_MODULES([LUA], [lua],
+ [with_liblua="yes"],
+ [
+ PKG_CHECK_MODULES([LUA], [lua-5.3],
+ [with_liblua="yes"],
+ [
+ PKG_CHECK_MODULES([LUA], [lua5.3],
+ [with_liblua="yes"],
+ [
+ PKG_CHECK_MODULES([LUA], [lua-5.2],
+ [with_liblua="yes"],
+ [
+ PKG_CHECK_MODULES([LUA], [lua5.2],
+ [with_liblua="yes"],
+ [
+ PKG_CHECK_MODULES([LUA], [lua-5.1],
+ [with_liblua="yes"],
+ [
+ PKG_CHECK_MODULES([LUA], [lua5.1],
+ [with_liblua="yes"],
+ [with_liblua="no (pkg-config cannot find liblua)"]
+ )
+ ]
+ )
+ ]
+ )
+ ]
+ )
+ ]
+ )
+ ]
+ )
+ ]
+ )
+fi
+
+if test "x$with_liblua" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $LUA_CFLAGS"
+
+ AC_CHECK_HEADERS([lua.h lauxlib.h lualib.h],
+ [with_liblua="yes"],
+ [with_liblua="no (header not found)"]
+ )
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+if test "x$with_liblua" = "xyes"
+then
+ SAVE_LIBS="$LIBS"
+ LIBS="$LIBS $LUA_LIBS"
+
+ AC_CHECK_FUNC([lua_settop],
+ [with_liblua="yes"],
+ [with_liblua="no (symbol 'lua_settop' not found)"]
+ )
+
+ LIBS="$SAVE_LIBS"
+fi
+
+if test "x$with_liblua" = "xyes"
+then
+ BUILD_WITH_LIBLUA_CFLAGS="$LUA_CFLAGS"
+ BUILD_WITH_LIBLUA_LIBS="$LUA_LIBS"
+fi
+AC_SUBST(BUILD_WITH_LIBLUA_CFLAGS)
+AC_SUBST(BUILD_WITH_LIBLUA_LIBS)
+# }}}
+
# --with-liblvm2app {{{
with_liblvm2app_cppflags=""
with_liblvm2app_ldflags=""
AC_ARG_WITH(liblvm2app, [AS_HELP_STRING([--with-liblvm2app@<:@=PREFIX@:>@], [Path to liblvm2app.])],
[
- if test "x$withval" != "xno" && test "x$withval" != "xyes"
- then
- with_liblvm2app_cppflags="-I$withval/include"
- with_liblvm2app_ldflags="-L$withval/lib"
- with_liblvm2app="yes"
- else
- with_liblvm2app="$withval"
+ if test "x$withval" = "xno"
+ then
+ with_liblvm2app="no"
+ else
+ with_liblvm2app="yes"
+ if test "x$withval" != "xyes"
+ then
+ with_liblvm2app_cppflags="-I$withval/include"
+ with_liblvm2app_ldflags="-L$withval/lib"
+ fi
fi
],
[
- with_liblvm2app="yes"
+ if test "x$ac_system" = "xLinux"
+ then
+ with_liblvm2app="yes"
+ else
+ with_liblvm2app="no (Linux only library)"
+ fi
])
if test "x$with_liblvm2app" = "xyes"
then
@@ -2587,13 +2994,6 @@ AC_ARG_WITH(libmodbus, [AS_HELP_STRING([--with-libmodbus@<:@=PREFIX@:>@], [Path
# configure using pkg-config
if test "x$with_libmodbus" = "xuse_pkgconfig"
-then
- if test "x$PKG_CONFIG" = "x"
- then
- with_libmodbus="no (Don't have pkg-config)"
- fi
-fi
-if test "x$with_libmodbus" = "xuse_pkgconfig"
then
AC_MSG_NOTICE([Checking for libmodbus using $PKG_CONFIG])
$PKG_CONFIG --exists 'libmodbus' 2>/dev/null
AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes")
# }}}
-# --with-libmysql {{{
-with_mysql_config="mysql_config"
-with_mysql_cflags=""
-with_mysql_libs=""
-AC_ARG_WITH(libmysql, [AS_HELP_STRING([--with-libmysql@<:@=PREFIX@:>@], [Path to libmysql.])],
+# --with-libmosquitto {{{
+with_libmosquitto_cppflags=""
+with_libmosquitto_ldflags=""
+AC_ARG_WITH(libmosquitto, [AS_HELP_STRING([--with-libmosquitto@<:@=PREFIX@:>@], [Path to libmosquitto.])],
[
- if test "x$withval" = "xno"
- then
- with_libmysql="no"
- else if test "x$withval" = "xyes"
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
then
- with_libmysql="yes"
+ with_libmosquitto_cppflags="-I$withval/include"
+ with_libmosquitto_ldflags="-L$withval/lib"
+ with_libmosquitto="yes"
else
- if test -f "$withval" && test -x "$withval";
- then
- with_mysql_config="$withval"
- else if test -x "$withval/bin/mysql_config"
- then
- with_mysql_config="$withval/bin/mysql_config"
- fi; fi
- with_libmysql="yes"
+ with_libmosquitto="$withval"
+ fi
+],
+[
+ with_libmosquitto="yes"
+])
+if test "x$with_libmosquitto" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libmosquitto_cppflags"
+
+ AC_CHECK_HEADERS(mosquitto.h, [with_libmosquitto="yes"], [with_libmosquitto="no (mosquitto.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmosquitto" = "xyes"
+then
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ LDFLAGS="$LDFLAGS $with_libmosquitto_ldflags"
+ CPPFLAGS="$CPPFLAGS $with_libmosquitto_cppflags"
+
+ AC_CHECK_LIB(mosquitto, mosquitto_connect, [with_libmosquitto="yes"], [with_libmosquitto="no (libmosquitto not found)"])
+
+ LDFLAGS="$SAVE_LDFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmosquitto" = "xyes"
+then
+ BUILD_WITH_LIBMOSQUITTO_CPPFLAGS="$with_libmosquitto_cppflags"
+ BUILD_WITH_LIBMOSQUITTO_LDFLAGS="$with_libmosquitto_ldflags"
+ BUILD_WITH_LIBMOSQUITTO_LIBS="-lmosquitto"
+ AC_SUBST(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBMOSQUITTO_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBMOSQUITTO_LIBS)
+fi
+# }}}
+
+# --with-libmysql {{{
+with_mysql_config="mysql_config"
+with_mysql_cflags=""
+with_mysql_libs=""
+AC_ARG_WITH(libmysql, [AS_HELP_STRING([--with-libmysql@<:@=PREFIX@:>@], [Path to libmysql.])],
+[
+ if test "x$withval" = "xno"
+ then
+ with_libmysql="no"
+ else if test "x$withval" = "xyes"
+ then
+ with_libmysql="yes"
+ else
+ if test -f "$withval" && test -x "$withval";
+ then
+ with_mysql_config="$withval"
+ else if test -x "$withval/bin/mysql_config"
+ then
+ with_mysql_config="$withval/bin/mysql_config"
+ fi; fi
+ with_libmysql="yes"
fi; fi
],
[
@@ -2836,10 +3285,6 @@ AC_ARG_WITH(libmnl, [AS_HELP_STRING([--with-libmnl@<:@=PREFIX@:>@], [Path to lib
with_libmnl="no (Linux only library)"
fi
])
-if test "x$PKG_CONFIG" = "x"
-then
- with_libmnl="no (Don't have pkg-config)"
-fi
if test "x$with_libmnl" = "xyes"
then
if $PKG_CONFIG --exists libmnl 2>/dev/null; then
if test "x$LIBNETAPP_LIBS" = "x"
then
- LIBNETAPP_LIBS="-lpthread -lxml -ladt -lssl -lm -lcrypto -lz"
+ LIBNETAPP_LIBS="$PTHREAD_LIBS -lxml -ladt -lssl -lm -lcrypto -lz"
fi
AC_MSG_NOTICE([netapp LIBS: $LIBNETAPP_LIBS])
# }}}
# --with-libnetsnmp {{{
-with_snmp_config="net-snmp-config"
-with_snmp_cflags=""
-with_snmp_libs=""
AC_ARG_WITH(libnetsnmp, [AS_HELP_STRING([--with-libnetsnmp@<:@=PREFIX@:>@], [Path to the Net-SNMPD library.])],
[
if test "x$withval" = "xno"
@@ -3008,57 +3450,42 @@ AC_ARG_WITH(libnetsnmp, [AS_HELP_STRING([--with-libnetsnmp@<:@=PREFIX@:>@], [Pat
then
with_libnetsnmp="yes"
else
- if test -x "$withval"
- then
- with_snmp_config="$withval"
- with_libnetsnmp="yes"
- else
- with_snmp_config="$withval/bin/net-snmp-config"
- with_libnetsnmp="yes"
- fi
+ with_libnetsnmp_cppflags="-I$withval/include"
+ with_libnetsnmp_ldflags="-I$withval/lib"
+ with_libnetsnmp="yes"
fi; fi
],
[with_libnetsnmp="yes"])
if test "x$with_libnetsnmp" = "xyes"
then
- with_snmp_cflags=`$with_snmp_config --cflags 2>/dev/null`
- snmp_config_status=$?
-
- if test $snmp_config_status -ne 0
- then
- with_libnetsnmp="no ($with_snmp_config failed)"
- else
- SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_snmp_cflags"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libnetsnmp_cppflags"
- AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"])
+ AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"])
- CPPFLAGS="$SAVE_CPPFLAGS"
- fi
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
if test "x$with_libnetsnmp" = "xyes"
then
- with_snmp_libs=`$with_snmp_config --libs 2>/dev/null`
- snmp_config_status=$?
+ SAVE_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $with_libnetsnmp_ldflags"
- if test $snmp_config_status -ne 0
- then
- with_libnetsnmp="no ($with_snmp_config failed)"
- else
- AC_CHECK_LIB(netsnmp, init_snmp,
+ AC_CHECK_LIB(netsnmp, init_snmp,
[with_libnetsnmp="yes"],
[with_libnetsnmp="no (libnetsnmp not found)"],
[$with_snmp_libs])
- fi
+
+ LDFLAGS="$SAVE_LDFLAGS"
fi
if test "x$with_libnetsnmp" = "xyes"
then
- BUILD_WITH_LIBSNMP_CFLAGS="$with_snmp_cflags"
- BUILD_WITH_LIBSNMP_LIBS="$with_snmp_libs"
- AC_SUBST(BUILD_WITH_LIBSNMP_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBSNMP_LIBS)
+ BUILD_WITH_LIBNETSNMP_CPPFLAGS="$with_libnetsnmp_cppflags"
+ BUILD_WITH_LIBNETSNMP_LDFLAGS="$with_libnetsnmp_ldflags"
+ BUILD_WITH_LIBNETSNMP_LIBS="-lnetsnmp"
fi
-AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes")
+AC_SUBST(BUILD_WITH_LIBNETSNMP_CPPFLAGS)
+AC_SUBST(BUILD_WITH_LIBNETSNMP_LDFLAGS)
+AC_SUBST(BUILD_WITH_LIBNETSNMP_LIBS)
# }}}
# --with-liboconfig {{{
save_CPPFLAGS="$CPPFLAGS"
LDFLAGS="$liboconfig_LDFLAGS"
CPPFLAGS="$liboconfig_CPPFLAGS"
-AC_CHECK_LIB(oconfig, oconfig_parse_fh,
+AC_CHECK_LIB(oconfig, oconfig_parse_file,
[
with_liboconfig="yes"
with_own_liboconfig="no"
fi
if test "x$with_oracle" = "xyes"
then
- BUILD_WITH_ORACLE_CFLAGS="$with_oracle_cppflags"
+ BUILD_WITH_ORACLE_CPPFLAGS="$with_oracle_cppflags"
BUILD_WITH_ORACLE_LIBS="$with_oracle_libs"
- AC_SUBST(BUILD_WITH_ORACLE_CFLAGS)
+ AC_SUBST(BUILD_WITH_ORACLE_CPPFLAGS)
AC_SUBST(BUILD_WITH_ORACLE_LIBS)
fi
# }}}
# --with-libowcapi {{{
with_libowcapi_cppflags=""
-with_libowcapi_libs="-lowcapi"
+with_libowcapi_ldflags=""
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_ldflags="-L$withval/lib"
with_libowcapi="yes"
else
with_libowcapi="$withval"
@@ -3256,7 +3683,7 @@ AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path
if test "x$with_libowcapi" = "xyes"
then
SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$with_libowcapi_cppflags"
+ CPPFLAGS="$CPPFLAGS $with_libowcapi_cppflags"
AC_CHECK_HEADERS(owcapi.h, [with_libowcapi="yes"], [with_libowcapi="no (owcapi.h not found)"])
then
SAVE_LDFLAGS="$LDFLAGS"
SAVE_CPPFLAGS="$CPPFLAGS"
- LDFLAGS="$with_libowcapi_libs"
+ LDFLAGS="$LDFLAGS $with_libowcapi_ldflags"
CPPFLAGS="$with_libowcapi_cppflags"
AC_CHECK_LIB(owcapi, OW_get, [with_libowcapi="yes"], [with_libowcapi="no (libowcapi not found)"])
if test "x$with_libowcapi" = "xyes"
then
BUILD_WITH_LIBOWCAPI_CPPFLAGS="$with_libowcapi_cppflags"
- BUILD_WITH_LIBOWCAPI_LIBS="$with_libowcapi_libs"
+ BUILD_WITH_LIBOWCAPI_LDFLAGS="$with_libowcapi_ldflags"
+ BUILD_WITH_LIBOWCAPI_LIBS="-lowcapi"
AC_SUBST(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBOWCAPI_LDFLAGS)
AC_SUBST(BUILD_WITH_LIBOWCAPI_LIBS)
fi
# }}}
SAVE_CFLAGS="$CFLAGS"
SAVE_LIBS="$LIBS"
dnl ARCHFLAGS="" -> disable multi -arch on OSX (see Config_heavy.pl:fetch_string)
- PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ccopts`
+ PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e perl_inc`
PERL_LIBS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts`
CFLAGS="$CFLAGS $PERL_CFLAGS"
LIBS="$LIBS $PERL_LIBS"
AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes")
# }}}
-# --with-libpthread {{{
-AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
-[ if test "x$withval" != "xno" \
- && test "x$withval" != "xyes"
- then
- LDFLAGS="$LDFLAGS -L$withval/lib"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- with_libpthread="yes"
- else
- if test "x$withval" = "xno"
- then
- with_libpthread="no (disabled)"
- fi
- fi
-], [with_libpthread="yes"])
-if test "x$with_libpthread" = "xyes"
+# --with-libprotobuf {{{
+with_libprotobuf_cppflags=""
+with_libprotobuf_ldflags=""
+AC_ARG_WITH([libprotobuf], [AS_HELP_STRING([--with-libprotobuf@<:@=PREFIX@:>@], [Path to libprotobuf.])],
+ [
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libprotobuf_cppflags="-I$withval/include"
+ with_libprotobuf_ldflags="-L$withval/lib"
+ with_libprotobuf="yes"
+ fi
+ if test "x$withval" = "xno"
+ then
+ with_libprotobuf="no (disabled on command line)"
+ fi
+ ],
+ [withval="yes"]
+)
+if test "x$withval" = "xyes"
then
- AC_CHECK_LIB(pthread, pthread_create, [with_libpthread="yes"], [with_libpthread="no (libpthread not found)"], [])
+PKG_CHECK_MODULES([PROTOBUF], [protobuf],
+ [with_libprotobuf="yes"],
+ [with_libprotobuf="no (pkg-config could not find libprotobuf)"]
+)
fi
-if test "x$with_libpthread" = "xyes"
-then
- AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"])
-fi
-if test "x$with_libpthread" = "xyes"
+if test "x$withval" != "xno"
then
- collect_pthread=1
-else
- collect_pthread=0
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_LIBS="$LIBS"
+ LDFLAGS="$with_libprotobuf_ldflags"
+ LIBS="$PROTOBUF_LIBS $LIBS"
+ AC_LANG_PUSH([C++])
+ AC_CHECK_LIB([protobuf], [main],
+ [
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$with_libprotobuf_cppflags $PROTOBUF_CFLAGS"
+ if test "x$PROTOBUF_LIBS" = "x"
+ then
+ PROTOBUF_LIBS="-lprotobuf"
+ fi
+ AC_CHECK_HEADERS([google/protobuf/util/time_util.h],
+ [with_libprotobuf="yes"],
+ [with_libprotobuf="no (<google/protobuf/util/time_util.h> not found)"]
+ )
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ ],
+ [with_libprotobuf="no (libprotobuf not found)"]
+ )
+ AC_LANG_POP([C++])
+ LDFLAGS="$SAVE_LDFLAGS"
+ LIBS="$SAVE_LIBS"
fi
-AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread],
- [Wether or not to use pthread (POSIX threads) library])
-AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
+BUILD_WITH_LIBPROTOBUF_CPPFLAGS="$with_libprotobuf_cppflags $PROTOBUF_CFLAGS"
+BUILD_WITH_LIBPROTOBUF_LDFLAGS="$with_libprotobuf_ldflags"
+BUILD_WITH_LIBPROTOBUF_LIBS="$PROTOBUF_LIBS"
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_CPPFLAGS])
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_LDFLAGS])
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_LIBS])
# }}}
-# --with-python {{{
-with_python_prog=""
-with_python_path="$PATH"
-AC_ARG_WITH(python, [AS_HELP_STRING([--with-python@<:@=PREFIX@:>@], [Path to the python interpreter.])],
-[
- if test "x$withval" = "xyes" || test "x$withval" = "xno"
- then
- with_python="$withval"
- else if test -x "$withval"
- then
- with_python_prog="$withval"
- with_python_path="`dirname \"$withval\"`$PATH_SEPARATOR$with_python_path"
- with_python="yes"
- else if test -d "$withval"
- then
- with_python_path="$withval$PATH_SEPARATOR$with_python_path"
- with_python="yes"
- else
- AC_MSG_WARN([Argument not recognized: $withval])
- fi; fi; fi
-], [with_python="yes"])
-
-SAVE_PATH="$PATH"
-SAVE_CPPFLAGS="$CPPFLAGS"
-SAVE_LDFLAGS="$LDFLAGS"
-SAVE_LIBS="$LIBS"
-
-PATH="$with_python_path"
-
-if test "x$with_python" = "xyes" && test "x$with_python_prog" = "x"
-then
- AC_MSG_CHECKING([for python])
- with_python_prog="`which python 2>/dev/null`"
- if test "x$with_python_prog" = "x"
- then
- AC_MSG_RESULT([not found])
- with_python="no (interpreter not found)"
- else
- AC_MSG_RESULT([$with_python_prog])
- fi
-fi
-
-if test "x$with_python" = "xyes"
-then
- AC_MSG_CHECKING([for Python CPPFLAGS])
- python_include_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_python_inc())" | "$with_python_prog" 2>&1`
- python_config_status=$?
-
- if test "$python_config_status" -ne 0 || test "x$python_include_path" = "x"
- then
- AC_MSG_RESULT([failed with status $python_config_status (output: $python_include_path)])
- with_python="no"
- else
- AC_MSG_RESULT([$python_include_path])
- fi
-fi
-
-if test "x$with_python" = "xyes"
+# --with-libprotobuf-c {{{
+with_libprotobuf_c_cppflags=""
+with_libprotobuf_c_ldflags=""
+AC_ARG_WITH([libprotobuf-c], [AS_HELP_STRING([--with-libprotobuf-c@<:@=PREFIX@:>@], [Path to libprotobuf-c.])],
+ [
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libprotobuf_c_cppflags="-I$withval/include"
+ with_libprotobuf_c_ldflags="-L$withval/lib"
+ with_libprotobuf_c="yes"
+ fi
+ if test "x$withval" = "xno"
+ then
+ with_libprotobuf_c="no (disabled on command line)"
+ fi
+ ],
+ [withval="yes"]
+)
+if test "x$withval" = "xyes"
then
- CPPFLAGS="-I$python_include_path $CPPFLAGS"
- AC_CHECK_HEADERS(Python.h,
- [with_python="yes"],
- [with_python="no ('Python.h' not found)"])
+PKG_CHECK_MODULES([PROTOBUF_C], [libprotobuf-c],
+ [with_libprotobuf_c="yes"],
+ [with_libprotobuf_c="no (pkg-config could not find libprotobuf-c)"]
+)
fi
-if test "x$with_python" = "xyes"
+if test "x$withval" != "xno"
then
- AC_MSG_CHECKING([for Python LDFLAGS])
- python_library_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0))" | "$with_python_prog" 2>&1`
- python_config_status=$?
-
- if test "$python_config_status" -ne 0 || test "x$python_library_path" = "x"
- then
- AC_MSG_RESULT([failed with status $python_config_status (output: $python_library_path)])
- with_python="no"
- else
- AC_MSG_RESULT([$python_library_path])
- fi
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_LIBS="$LIBS"
+ LDFLAGS="$with_libprotobuf_c_ldflags"
+ LIBS="$PROTOBUF_C_LIBS $LIBS"
+ AC_CHECK_LIB([protobuf-c], [protobuf_c_message_pack],
+ [
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$with_libprotobuf_c_cppflags $PROTOBUF_C_CFLAGS"
+ if test "x$PROTOBUF_C_LIBS" = "x"
+ then
+ PROTOBUF_C_LIBS="-lprotobuf-c"
+ fi
+ AC_CHECK_HEADERS([protobuf-c/protobuf-c.h google/protobuf-c/protobuf-c.h],
+ [
+ with_libprotobuf_c="yes"
+ break
+ ],
+ [with_libprotobuf_c="no (<protobuf-c.h> not found)"]
+ )
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ ],
+ [with_libprotobuf_c="no (libprotobuf-c not found)"]
+ )
+ LDFLAGS="$SAVE_LDFLAGS"
+ LIBS="$SAVE_LIBS"
fi
+BUILD_WITH_LIBPROTOBUF_C_CPPFLAGS="$with_libprotobuf_c_cppflags $PROTOBUF_C_CFLAGS"
+BUILD_WITH_LIBPROTOBUF_C_LDFLAGS="$with_libprotobuf_c_ldflags"
+BUILD_WITH_LIBPROTOBUF_C_LIBS="$PROTOBUF_C_LIBS"
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_C_CPPFLAGS])
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_C_LDFLAGS])
+AC_SUBST([BUILD_WITH_LIBPROTOBUF_C_LIBS])
+# }}}
-if test "x$with_python" = "xyes"
-then
- AC_MSG_CHECKING([for Python LIBS])
- python_library_flags=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0))" | "$with_python_prog" 2>&1`
- python_config_status=$?
+# --with-libpython {{{
+AC_ARG_VAR([LIBPYTHON_CPPFLAGS], [Preprocessor flags for libpython])
+AC_ARG_VAR([LIBPYTHON_LDFLAGS], [Linker flags for libpython])
+AC_ARG_VAR([LIBPYTHON_LIBS], [Libraries for libpython])
- if test "$python_config_status" -ne 0 || test "x$python_library_flags" = "x"
- then
- AC_MSG_RESULT([failed with status $python_config_status (output: $python_library_flags)])
- with_python="no"
- else
- AC_MSG_RESULT([$python_library_flags])
- fi
+AC_ARG_WITH([libpython],
+ [AS_HELP_STRING([--with-libpython],
+ [if we should build with libpython @<:@default=yes@:>@])
+ ],
+ [with_libpython="$withval"],
+ [with_libpython="check"]
+)
+if test "$with_libpython" != "no"; then
+ if test "$LIBPYTHON_CPPFLAGS" = "" && test "$LIBPYTHON_LDFLAGS" = ""; then
+ AC_ARG_VAR([PYTHON_CONFIG], [path to python-config])
+ AC_PATH_PROGS([PYTHON_CONFIG],
+ [python3-config python2-config python-config]
+ )
+ if test "$PYTHON_CONFIG" = ""; then
+ if test "$with_libpython" = "yes"; then
+ AC_MSG_ERROR([Unable to find python-config])
+ fi
+ with_libpython="no"
+ fi
+ fi
fi
-if test "x$with_python" = "xyes"
-then
- LDFLAGS="-L$python_library_path $LDFLAGS"
- LIBS="$python_library_flags $LIBS"
-
- AC_CHECK_FUNC(PyObject_CallFunction,
- [with_python="yes"],
- [with_python="no (Symbol 'PyObject_CallFunction' not found)"])
+if test "$PYTHON_CONFIG" != ""; then
+ LIBPYTHON_CPPFLAGS="`${PYTHON_CONFIG} --includes`"
+ if test $? -ne 0; then
+ with_libpython="no"
+ fi
+ LIBPYTHON_LDFLAGS="`${PYTHON_CONFIG} --ldflags`"
+ if test $? -ne 0; then
+ with_libpython="no"
+ fi
+ LIBPYTHON_LIBS="`${PYTHON_CONFIG} --libs`"
+ if test $? -ne 0; then
+ with_libpython="no"
+ fi
fi
-PATH="$SAVE_PATH"
-CPPFLAGS="$SAVE_CPPFLAGS"
-LDFLAGS="$SAVE_LDFLAGS"
-LIBS="$SAVE_LIBS"
-
-if test "x$with_python" = "xyes"
-then
- BUILD_WITH_PYTHON_CPPFLAGS="-I$python_include_path"
- BUILD_WITH_PYTHON_LDFLAGS="-L$python_library_path"
- BUILD_WITH_PYTHON_LIBS="$python_library_flags"
- AC_SUBST(BUILD_WITH_PYTHON_CPPFLAGS)
- AC_SUBST(BUILD_WITH_PYTHON_LDFLAGS)
- AC_SUBST(BUILD_WITH_PYTHON_LIBS)
+if test "$with_libpython" != "xno"; then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_LIBS="$LIBS"
+ CPPFLAGS="$LIBPYTHON_CPPFLAGS $CPPFLAGS"
+ LDFLAGS="$LIBPYTHON_LDFLAGS $LDFLAGS"
+ LIBS="$LIBPYTHON_LIBS $LIBS"
+ AC_CHECK_HEADERS([Python.h],
+ [
+ AC_MSG_CHECKING([for libpython])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+ [[#include <Python.h>]],
+ [[Py_Initialize();]])
+ ],
+ [with_libpython="yes"],
+ [with_libpython="no"]
+ )
+ AC_MSG_RESULT([$with_libpython])
+ ],
+ [with_libpython="no"]
+ )
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+ LIBS="$SAVE_LIBS"
fi
-# }}} --with-python
+# }}} --with-libpython
# --with-librabbitmq {{{
with_librabbitmq_cppflags=""
SAVE_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
-# AC_CHECK_HEADERS(sensors/sensors.h,
-# [
-# AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the <sensors/sensors.h> header file.])
-# ],
-# [with_libsensors="no (sensors/sensors.h not found)"])
AC_CHECK_HEADERS(sensors/sensors.h, [], [with_libsensors="no (sensors/sensors.h not found)"])
CPPFLAGS="$SAVE_CPPFLAGS"
AM_CONDITIONAL(BUILD_WITH_LM_SENSORS, test "x$with_libsensors" = "xyes")
# }}}
-# --with-libsigrok {{{
-with_libsigrok_cflags=""
-with_libsigrok_ldflags=""
-AC_ARG_WITH(libsigrok, [AS_HELP_STRING([--with-libsigrok@<:@=PREFIX@:>@], [Path to libsigrok.])],
-[
- if test "x$withval" = "xno"
- then
- with_libsigrok="no"
- else
- with_libsigrok="yes"
- if test "x$withval" != "xyes"
- then
- with_libsigrok_cflags="-I$withval/include"
- with_libsigrok_ldflags="-L$withval/lib"
- fi
- fi
-],[with_libsigrok="yes"])
-
-# libsigrok has a glib dependency
-if test "x$with_libsigrok" = "xyes"
-then
-m4_ifdef([AM_PATH_GLIB_2_0],
- [
- AM_PATH_GLIB_2_0([2.28.0],
- [with_libsigrok_cflags="$with_libsigrok_cflags $GLIB_CFLAGS"; with_libsigrok_ldflags="$with_libsigrok_ldflags $GLIB_LIBS"])
- ],
- [
- with_libsigrok="no (glib not available)"
- ]
+# libsigrok {{{
+AC_SUBST([LIBSIGROK_CFLAGS])
+AC_SUBST([LIBSIGROK_LIBS])
+PKG_CHECK_MODULES([LIBSIGROK], [libsigrok < 0.4],
+ [with_libsigrok="yes"],
+ [with_libsigrok="no (pkg-config could not find libsigrok)"]
)
-fi
-
-# libsigrok headers
-if test "x$with_libsigrok" = "xyes"
-then
- SAVE_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $with_libsigrok_cflags"
-
- AC_CHECK_HEADERS(libsigrok/libsigrok.h, [], [with_libsigrok="no (libsigrok/libsigrok.h not found)"])
-
- CPPFLAGS="$SAVE_CPPFLAGS"
-fi
-
-# libsigrok library
-if test "x$with_libsigrok" = "xyes"
-then
- SAVE_CPPFLAGS="$CPPFLAGS"
- SAVE_LDFLAGS="$LDFLAGS"
- CPPFLAGS="$CPPFLAGS $with_libsigrok_cflags"
- LDFLAGS="$LDFLAGS $with_libsigrok_ldflags"
-
- AC_CHECK_LIB(sigrok, sr_init,
- [
- AC_DEFINE(HAVE_LIBSIGROK, 1, [Define to 1 if you have the sigrok library (-lsigrok).])
- ],
- [with_libsigrok="no (libsigrok not found)"])
-
- CPPFLAGS="$SAVE_CPPFLAGS"
- LDFLAGS="$SAVE_LDFLAGS"
-fi
-if test "x$with_libsigrok" = "xyes"
-then
- BUILD_WITH_LIBSIGROK_CFLAGS="$with_libsigrok_cflags"
- BUILD_WITH_LIBSIGROK_LDFLAGS="$with_libsigrok_ldflags"
- AC_SUBST(BUILD_WITH_LIBSIGROK_CFLAGS)
- AC_SUBST(BUILD_WITH_LIBSIGROK_LDFLAGS)
-fi
-AM_CONDITIONAL(BUILD_WITH_LIBSIGROK, test "x$with_libsigrok" = "xyes")
# }}}
# --with-libstatgrab {{{
@@ -4243,23 +4642,16 @@ AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [P
if test "x$with_libstatgrab" = "xyes" \
&& test "x$with_libstatgrab_pkg_config" = "xyes"
then
- if test "x$PKG_CONFIG" != "x"
+ AC_MSG_CHECKING([pkg-config for libstatgrab])
+ temp_result="found"
+ $PKG_CONFIG --exists libstatgrab 2>/dev/null
+ if test "$?" != "0"
then
- AC_MSG_CHECKING([pkg-config for libstatgrab])
- temp_result="found"
- $PKG_CONFIG --exists libstatgrab 2>/dev/null
- if test "$?" != "0"
- then
- with_libstatgrab_pkg_config="no"
- with_libstatgrab="no (pkg-config doesn't know libstatgrab)"
- temp_result="not found"
- fi
- AC_MSG_RESULT([$temp_result])
- else
- AC_MSG_NOTICE([pkg-config not available, trying to guess flags for the statgrab library.])
with_libstatgrab_pkg_config="no"
- with_libstatgrab_ldflags="$with_libstatgrab_ldflags -lstatgrab"
+ with_libstatgrab="no (pkg-config doesn't know libstatgrab)"
+ temp_result="not found"
fi
+ AC_MSG_RESULT([$temp_result])
fi
if test "x$with_libstatgrab" = "xyes" \
if test "x$with_libstatgrab" = "xyes"
then
SAVE_CFLAGS="$CFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
SAVE_LIBS="$LIBS"
CFLAGS="$CFLAGS $with_libstatgrab_cflags"
# configure using pkg-config
if test "x$with_libupsclient" = "xuse_pkgconfig"
-then
- if test "x$PKG_CONFIG" = "x"
- then
- with_libupsclient="no (Don't have pkg-config)"
- fi
-fi
-if test "x$with_libupsclient" = "xuse_pkgconfig"
then
AC_MSG_NOTICE([Checking for libupsclient using $PKG_CONFIG])
$PKG_CONFIG --exists 'libupsclient' 2>/dev/null
fi
# }}}
+# --with-libxenctrl {{{
+with_libxenctrl_cppflags=""
+with_libxenctrl_ldflags=""
+AC_ARG_WITH(libxenctrl, [AS_HELP_STRING([--with-libxenctrl@<:@=PREFIX@:>@], [Path to libxenctrl.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libxenctrl_cppflags="-I$withval/include"
+ with_libxenctrl_ldflags="-L$withval/lib"
+ with_libxenctrl="yes"
+ else
+ with_libxenctrl="$withval"
+ fi
+],
+[
+ with_libxenctrl="yes"
+])
+if test "x$with_libxenctrl" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libxenctrl_cppflags"
+
+ AC_CHECK_HEADERS(xenctrl.h, [with_libxenctrl="yes"], [with_libxenctrl="no (xenctrl.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libxenctrl" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libxenctrl_cppflags"
+ LDFLAGS="$LDFLAGS $with_libxenctrl_ldflags"
+
+ #Xen versions older than 3.4 has no xc_getcpuinfo()
+ AC_CHECK_LIB(xenctrl, xc_getcpuinfo, [with_libxenctrl="yes"], [with_libxenctrl="no (symbol 'xc_getcpuinfo' not found)"], [])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+ LIBXENCTL_CPPFLAGS="$with_libxenctl_cppflags"
+ LIBXENCTL_LDFLAGS="$with_libxenctl_ldflags"
+ AC_SUBST(LIBXENCTL_CPPFLAGS)
+ AC_SUBST(LIBXENCTL_LDFLAGS)
+fi
+# }}}
+
# --with-libxmms {{{
with_xmms_config="xmms-config"
with_xmms_cflags=""
@@ -4775,7 +5206,7 @@ AC_ARG_WITH(mic,[AS_HELP_STRING([--with-mic@<:@=PREFIX@:>@], [Path to Intel MIC
AC_MSG_NOTICE([Not checking for Intel Mic: Manually configured])
with_mic_cflags="-I$withval/include"
with_mic_ldpath="-L$withval/lib/Linux"
- with_mic_libs="-lMicAccessSDK -lscif -lpthread"
+ with_mic_libs="$PTHREAD_LIBS -lMicAccessSDK -lscif"
with_mic="yes"
fi; fi; fi
],
AC_CHECK_LIB(MicAccessSDK, MicInitAPI,
[with_mic_ldpath="$with_mic_ldpath"
- with_mic_libs="-lMicAccessSDK -lscif -lpthread"],
- [with_mic="no (symbol MicInitAPI not found)"],[-lscif -lpthread])
+ with_mic_libs="$PTHREAD_LIBS -lMicAccessSDK -lscif"],
+ [with_mic="no (symbol MicInitAPI not found)"],[$PTHREAD_LIBS -lscif])
CPPFLAGS="$SAVE_CPPFLAGS"
LDFLAGS="$SAVE_LDFLAGS"
@@ -4839,13 +5270,6 @@ AC_ARG_WITH(libvarnish, [AS_HELP_STRING([--with-libvarnish@<:@=PREFIX@:>@], [Pat
# configure using pkg-config
if test "x$with_libvarnish" = "xuse_pkgconfig"
-then
- if test "x$PKG_CONFIG" = "x"
- then
- with_libvarnish="no (Don't have pkg-config)"
- fi
-fi
-if test "x$with_libvarnish" = "xuse_pkgconfig"
then
AC_MSG_NOTICE([Checking for varnishapi using $PKG_CONFIG])
$PKG_CONFIG --exists 'varnishapi' 2>/dev/null
with_libvirt="no (pkg-config isn't available)"
with_libvirt_cflags=""
with_libvirt_ldflags=""
-if test "x$PKG_CONFIG" != "x"
+$PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
+if test "$?" = "0"
then
- $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
- if test "$?" = "0"
- then
- with_libxml2="yes"
- else
- with_libxml2="no (pkg-config doesn't know libxml-2.0)"
- fi
+ with_libxml2="yes"
+else
+ with_libxml2="no (pkg-config doesn't know libxml-2.0)"
+fi
- $PKG_CONFIG --exists libvirt 2>/dev/null
- if test "$?" = "0"
- then
- with_libvirt="yes"
- else
- with_libvirt="no (pkg-config doesn't know libvirt)"
- fi
+$PKG_CONFIG --exists libvirt 2>/dev/null
+if test "$?" = "0"
+then
+ with_libvirt="yes"
+else
+ with_libvirt="no (pkg-config doesn't know libvirt)"
fi
if test "x$with_libxml2" = "xyes"
then
with_libopenipmipthread_cflags=""
with_libopenipmipthread_libs=""
-AC_MSG_CHECKING([for pkg-config])
-temp_result="no"
-if test "x$PKG_CONFIG" = "x"
-then
- with_libopenipmipthread="no"
- temp_result="no"
-else
- temp_result="$PKG_CONFIG"
-fi
-AC_MSG_RESULT([$temp_result])
-
if test "x$with_libopenipmipthread" = "xyes"
then
AC_MSG_CHECKING([for libOpenIPMIpthread])
PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
[with_libnotify="yes"],
- [if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
- with_libnotify="no"
- else
- with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"
- fi])
+ [with_libnotify="no (pkg-config doesn't know libnotify)"]
+)
+
+PKG_CHECK_MODULES([LIBRIEMANN_CLIENT], [riemann-client >= 1.6.0],
+ [with_libriemann_client="yes"],
+ [with_libriemann_client="no (pkg-config doesn't know libriemann-client)"])
# Check for enabled/disabled features
#
then
enable_plugin="yes"
else
- enable_plugin="no"
+ enable_plugin="$2"
fi
else
enable_plugin="$enable_all_plugins"
fi
else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
dependency_error="yes"
- enable_plugin="no (dependency error)"
+ enable_plugin="$2 (dependency error)"
fi
fi
AM_CONDITIONAL([BUILD_PLUGIN_]my_toupper([$1]), test "x$enable_plugin" = "xyes")
AC_COLLECTD([debug], [enable], [feature], [debugging])
AC_COLLECTD([daemon], [disable], [feature], [daemon mode])
AC_COLLECTD([getifaddrs],[enable], [feature], [getifaddrs under Linux])
+AC_COLLECTD([werror], [disable], [feature], [building with -Werror])
dependency_warning="no"
dependency_error="no"
plugin_contextswitch="no"
plugin_cpu="no"
plugin_cpufreq="no"
+plugin_cpusleep="no"
plugin_curl_json="no"
plugin_curl_xml="no"
plugin_df="no"
plugin_ethstat="no"
plugin_fhcount="no"
plugin_fscache="no"
+plugin_gps="no"
+plugin_grpc="no"
plugin_interface="no"
plugin_ipmi="no"
plugin_ipvs="no"
plugin_nfs="no"
plugin_numa="no"
plugin_perl="no"
+plugin_pinba="no"
plugin_processes="no"
plugin_protocols="no"
+plugin_python="no"
plugin_serial="no"
plugin_smart="no"
plugin_swap="no"
plugin_vmem="no"
plugin_vserver="no"
plugin_wireless="no"
+plugin_xencpu="no"
plugin_zfs_arc="no"
+plugin_zone="no"
plugin_zookeeper="no"
# Linux
if test "x$ac_system" = "xLinux"
then
plugin_battery="yes"
+ plugin_cgroups="yes"
plugin_conntrack="yes"
plugin_contextswitch="yes"
- plugin_cgroups="yes"
plugin_cpu="yes"
plugin_cpufreq="yes"
plugin_disk="yes"
then
plugin_turbostat="yes"
fi
+
+ if test "x$c_cv_have_clock_boottime_monotonic" = "xyes"
+ then
+ plugin_cpusleep="yes"
+ fi
fi
if test "x$ac_system" = "xOpenBSD"
plugin_tcpconns="yes"
fi
+if test "x$ac_system" = "xNetBSD"
+then
+ plugin_disk="yes"
+ plugin_entropy="yes"
+ plugin_irq="yes"
+ plugin_processes="yes"
+fi
+
# Mac OS X devices
if test "x$with_libiokit" = "xyes"
then
if test "x$ac_system" = "xAIX"
then
- plugin_tcpconns="yes"
plugin_ipc="yes"
+ plugin_tcpconns="yes"
fi
# FreeBSD
if test "x$ac_system" = "xFreeBSD"
then
+ plugin_disk="yes"
plugin_zfs_arc="yes"
fi
if test "x$with_perfstat" = "xyes"
then
- plugin_cpu="yes"
plugin_contextswitch="yes"
+ plugin_cpu="yes"
plugin_disk="yes"
- plugin_memory="yes"
- plugin_swap="yes"
plugin_interface="yes"
plugin_load="yes"
+ plugin_memory="yes"
+ plugin_swap="yes"
plugin_uptime="yes"
fi
plugin_processes="yes"
plugin_uptime="yes"
plugin_zfs_arc="yes"
+ plugin_zone="yes"
fi
if test "x$with_devinfo$with_kstat" = "xyesyes"
fi
# libi2c-dev
-with_libi2c="no"
if test "x$ac_system" = "xLinux"
then
AC_CHECK_DECL(i2c_smbus_read_i2c_block_data,
[with_libi2c="no (symbol i2c_smbus_read_i2c_block_data not found - have you installed libi2c-dev ?)"],
[[#include <stdlib.h>
#include <linux/i2c-dev.h>]])
+else
+ with_libi2c="no (Linux only)"
fi
if test "x$with_libi2c" = "xyes"
plugin_ethstat="yes"
fi
+if test "x$with_libgrpcpp" = "xyes" && test "x$with_libprotobuf" = "xyes" && test "x$have_protoc3" = "xyes" && test "x$GRPC_CPP_PLUGIN" != "x"
+then
+ plugin_grpc="yes"
+fi
+
if test "x$have_getifaddrs" = "xyes"
then
plugin_interface="yes"
fi
+if test "x$with_libgps" = "xyes"
+then
+ plugin_gps="yes"
+fi
+
if test "x$have_getloadavg" = "xyes"
then
plugin_load="yes"
plugin_perl="yes"
fi
+if test "x$have_protoc_c" = "xyes" && test "x$with_libprotobuf_c" = "xyes"
+then
+ plugin_pinba="yes"
+fi
+
# Mac OS X memory interface
if test "x$have_host_statistics" = "xyes"
then
plugin_processes="yes"
fi
+if test "x$with_libpython" != "xno"
+then
+ plugin_python="yes"
+fi
+
if test "x$with_libatasmart" = "xyes" && test "x$with_libudev" = "xyes"
then
plugin_smart="yes"
plugin_swap="yes"
fi
+if test "x$have_swapctl" = "xyes" && test "x$c_cv_have_swapctl_three_args" = "xyes"
+then
+ plugin_swap="yes"
+fi
+
if test "x$with_kvm_openfiles$with_kvm_nlist" = "xyesyes"
then
plugin_tcpconns="yes"
plugin_virt="yes"
fi
+if test "x$with_libxenctrl" = "xyes"
+then
+ plugin_xencpu="yes"
+fi
m4_divert_once([HELP_ENABLE], [
collectd plugins:])
m4_divert_once([HELP_ENABLE], [])
-AC_PLUGIN([aggregation], [yes], [Aggregation plugin])
-AC_PLUGIN([amqp], [$with_librabbitmq], [AMQP output plugin])
-AC_PLUGIN([apache], [$with_libcurl], [Apache httpd statistics])
-AC_PLUGIN([apcups], [yes], [Statistics of UPSes by APC])
-AC_PLUGIN([apple_sensors], [$with_libiokit], [Apple's hardware sensors])
-AC_PLUGIN([aquaero], [$with_libaquaero5], [Aquaero's hardware sensors])
-AC_PLUGIN([ascent], [$plugin_ascent], [AscentEmu player statistics])
-AC_PLUGIN([barometer], [$plugin_barometer], [Barometer sensor on I2C])
-AC_PLUGIN([battery], [$plugin_battery], [Battery statistics])
-AC_PLUGIN([bind], [$plugin_bind], [ISC Bind nameserver statistics])
-AC_PLUGIN([ceph], [$plugin_ceph], [Ceph daemon statistics])
-AC_PLUGIN([conntrack], [$plugin_conntrack], [nf_conntrack statistics])
-AC_PLUGIN([contextswitch], [$plugin_contextswitch], [context switch statistics])
-AC_PLUGIN([cpufreq], [$plugin_cpufreq], [CPU frequency statistics])
-AC_PLUGIN([cpu], [$plugin_cpu], [CPU usage statistics])
-AC_PLUGIN([csv], [yes], [CSV output plugin])
-AC_PLUGIN([curl], [$with_libcurl], [CURL generic web statistics])
-AC_PLUGIN([curl_json], [$plugin_curl_json], [CouchDB statistics])
-AC_PLUGIN([curl_xml], [$plugin_curl_xml], [CURL generic xml statistics])
-AC_PLUGIN([cgroups], [$plugin_cgroups], [CGroups CPU usage accounting])
-AC_PLUGIN([dbi], [$with_libdbi], [General database statistics])
-AC_PLUGIN([df], [$plugin_df], [Filesystem usage statistics])
-AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics])
-AC_PLUGIN([drbd], [$plugin_drbd], [DRBD statistics])
-AC_PLUGIN([dns], [$with_libpcap], [DNS traffic analysis])
-AC_PLUGIN([email], [yes], [EMail statistics])
-AC_PLUGIN([entropy], [$plugin_entropy], [Entropy statistics])
-AC_PLUGIN([ethstat], [$plugin_ethstat], [Stats from NIC driver])
-AC_PLUGIN([exec], [yes], [Execution of external programs])
-AC_PLUGIN([fhcount], [$plugin_fhcount], [File handles statistics])
-AC_PLUGIN([filecount], [yes], [Count files in directories])
-AC_PLUGIN([fscache], [$plugin_fscache], [fscache statistics])
-AC_PLUGIN([gmond], [$with_libganglia], [Ganglia plugin])
-AC_PLUGIN([hddtemp], [yes], [Query hddtempd])
-AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics])
-AC_PLUGIN([ipc], [$plugin_ipc], [IPC statistics])
-AC_PLUGIN([ipmi], [$plugin_ipmi], [IPMI sensor statistics])
-AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters])
-AC_PLUGIN([ipvs], [$plugin_ipvs], [IPVS connection statistics])
-AC_PLUGIN([irq], [$plugin_irq], [IRQ statistics])
-AC_PLUGIN([java], [$with_java], [Embed the Java Virtual Machine])
-AC_PLUGIN([load], [$plugin_load], [System load])
-AC_PLUGIN([logfile], [yes], [File logging plugin])
-AC_PLUGIN([log_logstash], [$plugin_log_logstash], [Logstash json_event compatible logging])
-AC_PLUGIN([lpar], [$with_perfstat], [AIX logical partitions statistics])
-AC_PLUGIN([lvm], [$with_liblvm2app], [LVM statistics])
-AC_PLUGIN([madwifi], [$have_linux_wireless_h], [Madwifi wireless statistics])
-AC_PLUGIN([match_empty_counter], [yes], [The empty counter match])
-AC_PLUGIN([match_hashed], [yes], [The hashed match])
-AC_PLUGIN([match_regex], [yes], [The regex match])
-AC_PLUGIN([match_timediff], [yes], [The timediff match])
-AC_PLUGIN([match_value], [yes], [The value match])
-AC_PLUGIN([mbmon], [yes], [Query mbmond])
-AC_PLUGIN([md], [$have_linux_raid_md_u_h], [md (Linux software RAID) devices])
-AC_PLUGIN([memcachec], [$with_libmemcached], [memcachec statistics])
-AC_PLUGIN([memcached], [yes], [memcached statistics])
-AC_PLUGIN([memory], [$plugin_memory], [Memory usage])
-AC_PLUGIN([mic], [$with_mic], [Intel Many Integrated Core stats])
-AC_PLUGIN([modbus], [$with_libmodbus], [Modbus plugin])
-AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values])
-AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics])
-AC_PLUGIN([netapp], [$with_libnetapp], [NetApp plugin])
-AC_PLUGIN([netlink], [$with_libmnl], [Enhanced Linux network statistics])
-AC_PLUGIN([network], [yes], [Network communication plugin])
-AC_PLUGIN([nfs], [$plugin_nfs], [NFS statistics])
-AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics])
-AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
-AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier])
-AC_PLUGIN([ntpd], [yes], [NTPd statistics])
-AC_PLUGIN([numa], [$plugin_numa], [NUMA virtual memory statistics])
-AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
-AC_PLUGIN([olsrd], [yes], [olsrd statistics])
-AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics])
-AC_PLUGIN([openldap], [$with_libldap], [OpenLDAP statistics])
-AC_PLUGIN([openvpn], [yes], [OpenVPN client statistics])
-AC_PLUGIN([oracle], [$with_oracle], [Oracle plugin])
-AC_PLUGIN([perl], [$plugin_perl], [Embed a Perl interpreter])
-AC_PLUGIN([pf], [$have_net_pfvar_h], [BSD packet filter (PF) statistics])
+AC_PLUGIN([aggregation], [yes], [Aggregation plugin])
+AC_PLUGIN([amqp], [$with_librabbitmq], [AMQP output plugin])
+AC_PLUGIN([apache], [$with_libcurl], [Apache httpd statistics])
+AC_PLUGIN([apcups], [yes], [Statistics of UPSes by APC])
+AC_PLUGIN([apple_sensors], [$with_libiokit], [Apple hardware sensors])
+AC_PLUGIN([aquaero], [$with_libaquaero5], [Aquaero hardware sensors])
+AC_PLUGIN([ascent], [$plugin_ascent], [AscentEmu player statistics])
+AC_PLUGIN([barometer], [$plugin_barometer], [Barometer sensor on I2C])
+AC_PLUGIN([battery], [$plugin_battery], [Battery statistics])
+AC_PLUGIN([bind], [$plugin_bind], [ISC Bind nameserver statistics])
+AC_PLUGIN([ceph], [$plugin_ceph], [Ceph daemon statistics])
+AC_PLUGIN([cgroups], [$plugin_cgroups], [CGroups CPU usage accounting])
+AC_PLUGIN([chrony], [yes], [Chrony statistics])
+AC_PLUGIN([conntrack], [$plugin_conntrack], [nf_conntrack statistics])
+AC_PLUGIN([contextswitch], [$plugin_contextswitch], [context switch statistics])
+AC_PLUGIN([cpu], [$plugin_cpu], [CPU usage statistics])
+AC_PLUGIN([cpufreq], [$plugin_cpufreq], [CPU frequency statistics])
+AC_PLUGIN([cpusleep], [$plugin_cpusleep], [CPU sleep statistics])
+AC_PLUGIN([csv], [yes], [CSV output plugin])
+AC_PLUGIN([curl], [$with_libcurl], [CURL generic web statistics])
+AC_PLUGIN([curl_json], [$plugin_curl_json], [CouchDB statistics])
+AC_PLUGIN([curl_xml], [$plugin_curl_xml], [CURL generic xml statistics])
+AC_PLUGIN([dbi], [$with_libdbi], [General database statistics])
+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([drbd], [$plugin_drbd], [DRBD statistics])
+AC_PLUGIN([email], [yes], [EMail statistics])
+AC_PLUGIN([entropy], [$plugin_entropy], [Entropy statistics])
+AC_PLUGIN([ethstat], [$plugin_ethstat], [Stats from NIC driver])
+AC_PLUGIN([exec], [yes], [Execution of external programs])
+AC_PLUGIN([fhcount], [$plugin_fhcount], [File handles statistics])
+AC_PLUGIN([filecount], [yes], [Count files in directories])
+AC_PLUGIN([fscache], [$plugin_fscache], [fscache statistics])
+AC_PLUGIN([gmond], [$with_libganglia], [Ganglia plugin])
+AC_PLUGIN([gps], [$plugin_gps], [GPS plugin])
+AC_PLUGIN([grpc], [$plugin_grpc], [gRPC plugin])
+AC_PLUGIN([hddtemp], [yes], [Query hddtempd])
+AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics])
+AC_PLUGIN([ipc], [$plugin_ipc], [IPC statistics])
+AC_PLUGIN([ipmi], [$plugin_ipmi], [IPMI sensor statistics])
+AC_PLUGIN([iptables], [$with_libiptc], [IPTables rule counters])
+AC_PLUGIN([ipvs], [$plugin_ipvs], [IPVS connection statistics])
+AC_PLUGIN([irq], [$plugin_irq], [IRQ statistics])
+AC_PLUGIN([java], [$with_java], [Embed the Java Virtual Machine])
+AC_PLUGIN([load], [$plugin_load], [System load])
+AC_PLUGIN([log_logstash], [$plugin_log_logstash], [Logstash json_event compatible logging])
+AC_PLUGIN([logfile], [yes], [File logging plugin])
+AC_PLUGIN([lpar], [$with_perfstat], [AIX logical partitions statistics])
+AC_PLUGIN([lua], [$with_liblua], [Lua plugin])
+AC_PLUGIN([lvm], [$with_liblvm2app], [LVM statistics])
+AC_PLUGIN([madwifi], [$have_linux_wireless_h], [Madwifi wireless statistics])
+AC_PLUGIN([match_empty_counter], [yes], [The empty counter match])
+AC_PLUGIN([match_hashed], [yes], [The hashed match])
+AC_PLUGIN([match_regex], [yes], [The regex match])
+AC_PLUGIN([match_timediff], [yes], [The timediff match])
+AC_PLUGIN([match_value], [yes], [The value match])
+AC_PLUGIN([mbmon], [yes], [Query mbmond])
+AC_PLUGIN([md], [$have_linux_raid_md_u_h], [md (Linux software RAID) devices])
+AC_PLUGIN([memcachec], [$with_libmemcached], [memcachec statistics])
+AC_PLUGIN([memcached], [yes], [memcached statistics])
+AC_PLUGIN([memory], [$plugin_memory], [Memory usage])
+AC_PLUGIN([mic], [$with_mic], [Intel Many Integrated Core stats])
+AC_PLUGIN([modbus], [$with_libmodbus], [Modbus plugin])
+AC_PLUGIN([mqtt], [$with_libmosquitto], [MQTT output plugin])
+AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values])
+AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics])
+AC_PLUGIN([netapp], [$with_libnetapp], [NetApp plugin])
+AC_PLUGIN([netlink], [$with_libmnl], [Enhanced Linux network statistics])
+AC_PLUGIN([network], [yes], [Network communication plugin])
+AC_PLUGIN([nfs], [$plugin_nfs], [NFS statistics])
+AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics])
+AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
+AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier])
+AC_PLUGIN([notify_nagios], [yes], [Nagios notification plugin])
+AC_PLUGIN([ntpd], [yes], [NTPd statistics])
+AC_PLUGIN([numa], [$plugin_numa], [NUMA virtual memory statistics])
+AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
+AC_PLUGIN([olsrd], [yes], [olsrd statistics])
+AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics])
+AC_PLUGIN([openldap], [$with_libldap], [OpenLDAP statistics])
+AC_PLUGIN([openvpn], [yes], [OpenVPN client statistics])
+AC_PLUGIN([oracle], [$with_oracle], [Oracle plugin])
+AC_PLUGIN([perl], [$plugin_perl], [Embed a Perl interpreter])
+AC_PLUGIN([pf], [$have_net_pfvar_h], [BSD packet filter (PF) statistics])
# FIXME: Check for libevent, too.
-AC_PLUGIN([pinba], [$have_protoc_c], [Pinba statistics])
-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([protocols], [$plugin_protocols], [Protocol (IP, TCP, ...) statistics])
-AC_PLUGIN([python], [$with_python], [Embed a Python interpreter])
-AC_PLUGIN([redis], [$with_libhiredis], [Redis plugin])
-AC_PLUGIN([routeros], [$with_librouteros], [RouterOS plugin])
-AC_PLUGIN([rrdcached], [$librrd_rrdc_update], [RRDTool output plugin])
-AC_PLUGIN([rrdtool], [$with_librrd], [RRDTool output plugin])
-AC_PLUGIN([sensors], [$with_libsensors], [lm_sensors statistics])
-AC_PLUGIN([serial], [$plugin_serial], [serial port traffic])
-AC_PLUGIN([sigrok], [$with_libsigrok], [sigrok acquisition sources])
-AC_PLUGIN([smart], [$plugin_smart], [SMART statistics])
-AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin])
-AC_PLUGIN([statsd], [yes], [StatsD plugin])
-AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics])
-AC_PLUGIN([syslog], [$have_syslog], [Syslog logging plugin])
-AC_PLUGIN([table], [yes], [Parsing of tabular data])
-AC_PLUGIN([tail], [yes], [Parsing of logfiles])
-AC_PLUGIN([tail_csv], [yes], [Parsing of CSV files])
-AC_PLUGIN([tape], [$plugin_tape], [Tape drive statistics])
-AC_PLUGIN([target_notification], [yes], [The notification target])
-AC_PLUGIN([target_replace], [yes], [The replace target])
-AC_PLUGIN([target_scale],[yes], [The scale target])
-AC_PLUGIN([target_set], [yes], [The set target])
-AC_PLUGIN([target_v5upgrade], [yes], [The v5upgrade target])
-AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics])
-AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics])
-AC_PLUGIN([ted], [$plugin_ted], [Read The Energy Detective values])
-AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI thermal zone statistics])
-AC_PLUGIN([threshold], [yes], [Threshold checking plugin])
-AC_PLUGIN([tokyotyrant], [$with_libtokyotyrant], [TokyoTyrant database statistics])
-AC_PLUGIN([turbostat], [$plugin_turbostat], [Advanced statistic on Intel cpu states])
-AC_PLUGIN([unixsock], [yes], [Unixsock communication plugin])
-AC_PLUGIN([uptime], [$plugin_uptime], [Uptime statistics])
-AC_PLUGIN([users], [$plugin_users], [User statistics])
-AC_PLUGIN([uuid], [yes], [UUID as hostname plugin])
-AC_PLUGIN([varnish], [$with_libvarnish], [Varnish cache statistics])
-AC_PLUGIN([virt], [$plugin_virt], [Virtual machine statistics])
-AC_PLUGIN([vmem], [$plugin_vmem], [Virtual memory statistics])
-AC_PLUGIN([vserver], [$plugin_vserver], [Linux VServer statistics])
-AC_PLUGIN([wireless], [$plugin_wireless], [Wireless statistics])
-AC_PLUGIN([write_graphite], [yes], [Graphite / Carbon output plugin])
-AC_PLUGIN([write_http], [$with_libcurl], [HTTP output plugin])
-AC_PLUGIN([write_kafka], [$with_librdkafka], [Kafka output plugin])
-AC_PLUGIN([write_log], [yes], [Log output plugin])
-AC_PLUGIN([write_mongodb], [$with_libmongoc], [MongoDB output plugin])
-AC_PLUGIN([write_redis], [$with_libhiredis], [Redis output plugin])
-AC_PLUGIN([write_riemann], [$have_protoc_c], [Riemann output plugin])
-AC_PLUGIN([write_sensu], [yes], [Sensu output plugin])
-AC_PLUGIN([write_tsdb], [yes], [TSDB output plugin])
-AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics])
-AC_PLUGIN([zfs_arc], [$plugin_zfs_arc], [ZFS ARC statistics])
-AC_PLUGIN([zookeeper], [yes], [Zookeeper statistics])
+AC_PLUGIN([pinba], [$plugin_pinba], [Pinba statistics])
+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([protocols], [$plugin_protocols], [Protocol (IP, TCP, ...) statistics])
+AC_PLUGIN([python], [$plugin_python], [Embed a Python interpreter])
+AC_PLUGIN([redis], [$with_libhiredis], [Redis plugin])
+AC_PLUGIN([routeros], [$with_librouteros], [RouterOS plugin])
+AC_PLUGIN([rrdcached], [$librrd_rrdc_update], [RRDTool output plugin])
+AC_PLUGIN([rrdtool], [$with_librrd], [RRDTool output plugin])
+AC_PLUGIN([sensors], [$with_libsensors], [lm_sensors statistics])
+AC_PLUGIN([serial], [$plugin_serial], [serial port traffic])
+AC_PLUGIN([sigrok], [$with_libsigrok], [sigrok acquisition sources])
+AC_PLUGIN([smart], [$plugin_smart], [SMART statistics])
+AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin])
+AC_PLUGIN([statsd], [yes], [StatsD plugin])
+AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics])
+AC_PLUGIN([syslog], [$have_syslog], [Syslog logging plugin])
+AC_PLUGIN([table], [yes], [Parsing of tabular data])
+AC_PLUGIN([tail], [yes], [Parsing of logfiles])
+AC_PLUGIN([tail_csv], [yes], [Parsing of CSV files])
+AC_PLUGIN([tape], [$plugin_tape], [Tape drive statistics])
+AC_PLUGIN([target_notification], [yes], [The notification target])
+AC_PLUGIN([target_replace], [yes], [The replace target])
+AC_PLUGIN([target_scale], [yes], [The scale target])
+AC_PLUGIN([target_set], [yes], [The set target])
+AC_PLUGIN([target_v5upgrade], [yes], [The v5upgrade target])
+AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics])
+AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics])
+AC_PLUGIN([ted], [$plugin_ted], [Read The Energy Detective values])
+AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI thermal zone statistics])
+AC_PLUGIN([threshold], [yes], [Threshold checking plugin])
+AC_PLUGIN([tokyotyrant], [$with_libtokyotyrant], [TokyoTyrant database statistics])
+AC_PLUGIN([turbostat], [$plugin_turbostat], [Advanced statistic on Intel cpu states])
+AC_PLUGIN([unixsock], [yes], [Unixsock communication plugin])
+AC_PLUGIN([uptime], [$plugin_uptime], [Uptime statistics])
+AC_PLUGIN([users], [$plugin_users], [User statistics])
+AC_PLUGIN([uuid], [yes], [UUID as hostname plugin])
+AC_PLUGIN([varnish], [$with_libvarnish], [Varnish cache statistics])
+AC_PLUGIN([virt], [$plugin_virt], [Virtual machine statistics])
+AC_PLUGIN([vmem], [$plugin_vmem], [Virtual memory statistics])
+AC_PLUGIN([vserver], [$plugin_vserver], [Linux VServer statistics])
+AC_PLUGIN([wireless], [$plugin_wireless], [Wireless statistics])
+AC_PLUGIN([write_graphite], [yes], [Graphite / Carbon output plugin])
+AC_PLUGIN([write_http], [$with_libcurl], [HTTP output plugin])
+AC_PLUGIN([write_kafka], [$with_librdkafka], [Kafka output plugin])
+AC_PLUGIN([write_log], [yes], [Log output plugin])
+AC_PLUGIN([write_mongodb], [$with_libmongoc], [MongoDB output plugin])
+AC_PLUGIN([write_redis], [$with_libhiredis], [Redis output plugin])
+AC_PLUGIN([write_riemann], [$with_libriemann_client], [Riemann output plugin])
+AC_PLUGIN([write_sensu], [yes], [Sensu output plugin])
+AC_PLUGIN([write_tsdb], [yes], [TSDB output plugin])
+AC_PLUGIN([xencpu], [$plugin_xencpu], [Xen Host CPU usage])
+AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics])
+AC_PLUGIN([zfs_arc], [$plugin_zfs_arc], [ZFS ARC statistics])
+AC_PLUGIN([zone], [$plugin_zone], [Solaris container statistics])
+AC_PLUGIN([zookeeper], [yes], [Zookeeper statistics])
dnl Default configuration file
# Load either syslog or logfile
@@ -5932,6 +6405,18 @@ AC_ARG_WITH(perl-bindings, [AS_HELP_STRING([--with-perl-bindings@<:@=OPTIONS@:>@
with_perl_bindings="no (no perl interpreter found)"
fi
])
+
+if test "x$with_perl_bindings" = "xyes"
+then
+ AC_MSG_CHECKING([for the ExtUtils::MakeMaker module])
+ if $PERL -MExtUtils::MakeMaker -e '' 2>/dev/null; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ with_perl_bindings="no (ExtUtils::MakeMaker not found)"
+ fi
+fi
+
if test "x$with_perl_bindings" = "xyes"
then
PERL_BINDINGS="perl"
AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
-AC_CONFIG_FILES([Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
+AM_CFLAGS="-Wall"
+AM_CXXFLAGS="-Wall"
+if test "x$enable_werror" != "xno"
+then
+ AM_CFLAGS="$AM_CFLAGS -Werror"
+ AM_CXXFLAGS="$AM_CXXFLAGS -Werror"
+fi
+AC_SUBST([AM_CFLAGS])
+AC_SUBST([AM_CXXFLAGS])
+
+AC_CONFIG_FILES([Makefile proto/Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
AC_OUTPUT
if test "x$with_librrd" = "xyes" \
with_perl_bindings="yes ($PERL_BINDINGS_OPTIONS)"
fi
-cat <<EOF;
-
-Configuration:
- Libraries:
- intel mic . . . . . . $with_mic
- libaquaero5 . . . . . $with_libaquaero5
- libatasmart . . . . . $with_libatasmart
- libcurl . . . . . . . $with_libcurl
- libdbi . . . . . . . $with_libdbi
- libesmtp . . . . . . $with_libesmtp
- libganglia . . . . . $with_libganglia
- libgcrypt . . . . . . $with_libgcrypt
- libhal . . . . . . . $with_libhal
- libhiredis . . . . . $with_libhiredis
- libi2c-dev . . . . . $with_libi2c
- libiokit . . . . . . $with_libiokit
- libiptc . . . . . . . $with_libiptc
- libjvm . . . . . . . $with_java
- libkstat . . . . . . $with_kstat
- libkvm . . . . . . . $with_libkvm
- libldap . . . . . . . $with_libldap
- liblvm2app . . . . . $with_liblvm2app
- libmemcached . . . . $with_libmemcached
- libmnl . . . . . . . $with_libmnl
- libmodbus . . . . . . $with_libmodbus
- libmongoc . . . . . . $with_libmongoc
- libmysql . . . . . . $with_libmysql
- libnetapp . . . . . . $with_libnetapp
- libnetsnmp . . . . . $with_libnetsnmp
- libnotify . . . . . . $with_libnotify
- liboconfig . . . . . $with_liboconfig
- libopenipmi . . . . . $with_libopenipmipthread
- liboping . . . . . . $with_liboping
- libowcapi . . . . . . $with_libowcapi
- libpcap . . . . . . . $with_libpcap
- libperfstat . . . . . $with_perfstat
- libperl . . . . . . . $with_libperl
- libpq . . . . . . . . $with_libpq
- libpthread . . . . . $with_libpthread
- librabbitmq . . . . . $with_librabbitmq
- librdkafka . . . . . $with_librdkafka
- librouteros . . . . . $with_librouteros
- librrd . . . . . . . $with_librrd
- libsensors . . . . . $with_libsensors
- libsigrok . . . . . $with_libsigrok
- libstatgrab . . . . . $with_libstatgrab
- libtokyotyrant . . . $with_libtokyotyrant
- libudev . . . . . . . $with_libudev
- libupsclient . . . . $with_libupsclient
- libvarnish . . . . . $with_libvarnish
- libvirt . . . . . . . $with_libvirt
- libxml2 . . . . . . . $with_libxml2
- libxmms . . . . . . . $with_libxmms
- libyajl . . . . . . . $with_libyajl
- oracle . . . . . . . $with_oracle
- protobuf-c . . . . . $have_protoc_c
- python . . . . . . . $with_python
-
- Features:
- daemon mode . . . . . $enable_daemon
- debug . . . . . . . . $enable_debug
-
- Bindings:
- perl . . . . . . . . $with_perl_bindings
-
- Modules:
- aggregation . . . . . $enable_aggregation
- amqp . . . . . . . $enable_amqp
- apache . . . . . . . $enable_apache
- apcups . . . . . . . $enable_apcups
- apple_sensors . . . . $enable_apple_sensors
- aquaero . . . . . . . $enable_aquaero
- ascent . . . . . . . $enable_ascent
- barometer . . . . . . $enable_barometer
- battery . . . . . . . $enable_battery
- bind . . . . . . . . $enable_bind
- ceph . . . . . . . . $enable_ceph
- cgroups . . . . . . . $enable_cgroups
- conntrack . . . . . . $enable_conntrack
- contextswitch . . . . $enable_contextswitch
- cpu . . . . . . . . . $enable_cpu
- cpufreq . . . . . . . $enable_cpufreq
- csv . . . . . . . . . $enable_csv
- curl . . . . . . . . $enable_curl
- curl_json . . . . . . $enable_curl_json
- curl_xml . . . . . . $enable_curl_xml
- dbi . . . . . . . . . $enable_dbi
- df . . . . . . . . . $enable_df
- disk . . . . . . . . $enable_disk
- dns . . . . . . . . . $enable_dns
- drbd . . . . . . . . $enable_drbd
- email . . . . . . . . $enable_email
- entropy . . . . . . . $enable_entropy
- ethstat . . . . . . . $enable_ethstat
- exec . . . . . . . . $enable_exec
- fhcount . . . . . . . $enable_fhcount
- filecount . . . . . . $enable_filecount
- fscache . . . . . . . $enable_fscache
- gmond . . . . . . . . $enable_gmond
- hddtemp . . . . . . . $enable_hddtemp
- interface . . . . . . $enable_interface
- ipc . . . . . . . . . $enable_ipc
- ipmi . . . . . . . . $enable_ipmi
- iptables . . . . . . $enable_iptables
- ipvs . . . . . . . . $enable_ipvs
- irq . . . . . . . . . $enable_irq
- java . . . . . . . . $enable_java
- load . . . . . . . . $enable_load
- logfile . . . . . . . $enable_logfile
- log_logstash . . . . $enable_log_logstash
- lpar . . . . . . . . $enable_lpar
- lvm . . . . . . . . . $enable_lvm
- madwifi . . . . . . . $enable_madwifi
- match_empty_counter . $enable_match_empty_counter
- match_hashed . . . . $enable_match_hashed
- match_regex . . . . . $enable_match_regex
- match_timediff . . . $enable_match_timediff
- match_value . . . . . $enable_match_value
- mbmon . . . . . . . . $enable_mbmon
- md . . . . . . . . . $enable_md
- memcachec . . . . . . $enable_memcachec
- memcached . . . . . . $enable_memcached
- memory . . . . . . . $enable_memory
- mic . . . . . . . . . $enable_mic
- modbus . . . . . . . $enable_modbus
- multimeter . . . . . $enable_multimeter
- mysql . . . . . . . . $enable_mysql
- netapp . . . . . . . $enable_netapp
- 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
- numa . . . . . . . . $enable_numa
- nut . . . . . . . . . $enable_nut
- olsrd . . . . . . . . $enable_olsrd
- onewire . . . . . . . $enable_onewire
- openldap . . . . . . $enable_openldap
- openvpn . . . . . . . $enable_openvpn
- oracle . . . . . . . $enable_oracle
- perl . . . . . . . . $enable_perl
- pf . . . . . . . . . $enable_pf
- pinba . . . . . . . . $enable_pinba
- ping . . . . . . . . $enable_ping
- postgresql . . . . . $enable_postgresql
- powerdns . . . . . . $enable_powerdns
- processes . . . . . . $enable_processes
- protocols . . . . . . $enable_protocols
- python . . . . . . . $enable_python
- redis . . . . . . . . $enable_redis
- routeros . . . . . . $enable_routeros
- rrdcached . . . . . . $enable_rrdcached
- rrdtool . . . . . . . $enable_rrdtool
- sensors . . . . . . . $enable_sensors
- serial . . . . . . . $enable_serial
- sigrok . . . . . . . $enable_sigrok
- smart . . . . . . . . $enable_smart
- snmp . . . . . . . . $enable_snmp
- statsd . . . . . . . $enable_statsd
- swap . . . . . . . . $enable_swap
- syslog . . . . . . . $enable_syslog
- table . . . . . . . . $enable_table
- tail_csv . . . . . . $enable_tail_csv
- tail . . . . . . . . $enable_tail
- tape . . . . . . . . $enable_tape
- target_notification . $enable_target_notification
- target_replace . . . $enable_target_replace
- target_scale . . . . $enable_target_scale
- target_set . . . . . $enable_target_set
- target_v5upgrade . . $enable_target_v5upgrade
- tcpconns . . . . . . $enable_tcpconns
- teamspeak2 . . . . . $enable_teamspeak2
- ted . . . . . . . . . $enable_ted
- thermal . . . . . . . $enable_thermal
- threshold . . . . . . $enable_threshold
- tokyotyrant . . . . . $enable_tokyotyrant
- turbostat . . . . . . $enable_turbostat
- unixsock . . . . . . $enable_unixsock
- uptime . . . . . . . $enable_uptime
- users . . . . . . . . $enable_users
- uuid . . . . . . . . $enable_uuid
- varnish . . . . . . . $enable_varnish
- virt . . . . . . . . $enable_virt
- vmem . . . . . . . . $enable_vmem
- vserver . . . . . . . $enable_vserver
- wireless . . . . . . $enable_wireless
- write_graphite . . . $enable_write_graphite
- write_http . . . . . $enable_write_http
- write_kafka . . . . . $enable_write_kafka
- write_log . . . . . . $enable_write_log
- write_mongodb . . . . $enable_write_mongodb
- write_redis . . . . . $enable_write_redis
- write_riemann . . . . $enable_write_riemann
- write_sensu . . . . . $enable_write_sensu
- write_tsdb . . . . . $enable_write_tsdb
- xmms . . . . . . . . $enable_xmms
- zfs_arc . . . . . . . $enable_zfs_arc
- zookeeper . . . . . . $enable_zookeeper
-
-EOF
+AC_MSG_RESULT()
+AC_MSG_RESULT([Configuration:])
+AC_MSG_RESULT([ Build:])
+AC_MSG_RESULT([ Platform . . . . . . $ac_system])
+AC_MSG_RESULT([ CC . . . . . . . . . $CC])
+AC_MSG_RESULT([ CFLAGS . . . . . . . $AM_CFLAGS $CFLAGS])
+AC_MSG_RESULT([ CXXFLAGS . . . . . . $AM_CXXFLAGS $CXXFLAGS])
+AC_MSG_RESULT([ CPP . . . . . . . . . $CPP])
+AC_MSG_RESULT([ CPPFLAGS . . . . . . $CPPFLAGS])
+AC_MSG_RESULT([ GRPC_CPP_PLUGIN . . . $GRPC_CPP_PLUGIN])
+AC_MSG_RESULT([ LD . . . . . . . . . $LD])
+AC_MSG_RESULT([ LDFLAGS . . . . . . . $LDFLAGS])
+AC_MSG_RESULT([ PROTOC . . . . . . . $PROTOC])
+AC_MSG_RESULT([ YACC . . . . . . . . $YACC])
+AC_MSG_RESULT([ YFLAGS . . . . . . . $YFLAGS])
+AC_MSG_RESULT()
+AC_MSG_RESULT([ Libraries:])
+AC_MSG_RESULT([ intel mic . . . . . . $with_mic])
+AC_MSG_RESULT([ libaquaero5 . . . . . $with_libaquaero5])
+AC_MSG_RESULT([ libatasmart . . . . . $with_libatasmart])
+AC_MSG_RESULT([ libcurl . . . . . . . $with_libcurl])
+AC_MSG_RESULT([ libdbi . . . . . . . $with_libdbi])
+AC_MSG_RESULT([ libesmtp . . . . . . $with_libesmtp])
+AC_MSG_RESULT([ libganglia . . . . . $with_libganglia])
+AC_MSG_RESULT([ libgcrypt . . . . . . $with_libgcrypt])
+AC_MSG_RESULT([ libgps . . . . . . . $with_libgps])
+AC_MSG_RESULT([ libgrpc++ . . . . . . $with_libgrpcpp])
+AC_MSG_RESULT([ libhal . . . . . . . $with_libhal])
+AC_MSG_RESULT([ libhiredis . . . . . $with_libhiredis])
+AC_MSG_RESULT([ libi2c-dev . . . . . $with_libi2c])
+AC_MSG_RESULT([ libiokit . . . . . . $with_libiokit])
+AC_MSG_RESULT([ libiptc . . . . . . . $with_libiptc])
+AC_MSG_RESULT([ libjvm . . . . . . . $with_java])
+AC_MSG_RESULT([ libkstat . . . . . . $with_kstat])
+AC_MSG_RESULT([ libkvm . . . . . . . $with_libkvm])
+AC_MSG_RESULT([ libldap . . . . . . . $with_libldap])
+AC_MSG_RESULT([ liblua . . . . . . . $with_liblua])
+AC_MSG_RESULT([ liblvm2app . . . . . $with_liblvm2app])
+AC_MSG_RESULT([ libmemcached . . . . $with_libmemcached])
+AC_MSG_RESULT([ libmnl . . . . . . . $with_libmnl])
+AC_MSG_RESULT([ libmodbus . . . . . . $with_libmodbus])
+AC_MSG_RESULT([ libmongoc . . . . . . $with_libmongoc])
+AC_MSG_RESULT([ libmosquitto . . . . $with_libmosquitto])
+AC_MSG_RESULT([ libmysql . . . . . . $with_libmysql])
+AC_MSG_RESULT([ libnetapp . . . . . . $with_libnetapp])
+AC_MSG_RESULT([ libnetsnmp . . . . . $with_libnetsnmp])
+AC_MSG_RESULT([ libnotify . . . . . . $with_libnotify])
+AC_MSG_RESULT([ liboconfig . . . . . $with_liboconfig])
+AC_MSG_RESULT([ libopenipmi . . . . . $with_libopenipmipthread])
+AC_MSG_RESULT([ liboping . . . . . . $with_liboping])
+AC_MSG_RESULT([ libowcapi . . . . . . $with_libowcapi])
+AC_MSG_RESULT([ libpcap . . . . . . . $with_libpcap])
+AC_MSG_RESULT([ libperfstat . . . . . $with_perfstat])
+AC_MSG_RESULT([ libperl . . . . . . . $with_libperl])
+AC_MSG_RESULT([ libpq . . . . . . . . $with_libpq])
+AC_MSG_RESULT([ libprotobuf . . . . . $with_libprotobuf])
+AC_MSG_RESULT([ libprotobuf-c . . . . $with_libprotobuf_c])
+AC_MSG_RESULT([ libpython . . . . . . $with_libpython])
+AC_MSG_RESULT([ librabbitmq . . . . . $with_librabbitmq])
+AC_MSG_RESULT([ libriemann-client . . $with_libriemann_client])
+AC_MSG_RESULT([ librdkafka . . . . . $with_librdkafka])
+AC_MSG_RESULT([ librouteros . . . . . $with_librouteros])
+AC_MSG_RESULT([ librrd . . . . . . . $with_librrd])
+AC_MSG_RESULT([ libsensors . . . . . $with_libsensors])
+AC_MSG_RESULT([ libsigrok . . . . . $with_libsigrok])
+AC_MSG_RESULT([ libstatgrab . . . . . $with_libstatgrab])
+AC_MSG_RESULT([ libtokyotyrant . . . $with_libtokyotyrant])
+AC_MSG_RESULT([ libudev . . . . . . . $with_libudev])
+AC_MSG_RESULT([ libupsclient . . . . $with_libupsclient])
+AC_MSG_RESULT([ libvarnish . . . . . $with_libvarnish])
+AC_MSG_RESULT([ libvirt . . . . . . . $with_libvirt])
+AC_MSG_RESULT([ libxenctrl . . . . . $with_libxenctrl])
+AC_MSG_RESULT([ libxml2 . . . . . . . $with_libxml2])
+AC_MSG_RESULT([ libxmms . . . . . . . $with_libxmms])
+AC_MSG_RESULT([ libyajl . . . . . . . $with_libyajl])
+AC_MSG_RESULT([ oracle . . . . . . . $with_oracle])
+AC_MSG_RESULT([ protobuf-c . . . . . $have_protoc_c])
+AC_MSG_RESULT([ protoc 3 . . . . . . $have_protoc3])
+AC_MSG_RESULT()
+AC_MSG_RESULT([ Features:])
+AC_MSG_RESULT([ daemon mode . . . . . $enable_daemon])
+AC_MSG_RESULT([ debug . . . . . . . . $enable_debug])
+AC_MSG_RESULT()
+AC_MSG_RESULT([ Bindings:])
+AC_MSG_RESULT([ perl . . . . . . . . $with_perl_bindings])
+AC_MSG_RESULT()
+AC_MSG_RESULT([ Modules:])
+AC_MSG_RESULT([ aggregation . . . . . $enable_aggregation])
+AC_MSG_RESULT([ amqp . . . . . . . $enable_amqp])
+AC_MSG_RESULT([ apache . . . . . . . $enable_apache])
+AC_MSG_RESULT([ apcups . . . . . . . $enable_apcups])
+AC_MSG_RESULT([ apple_sensors . . . . $enable_apple_sensors])
+AC_MSG_RESULT([ aquaero . . . . . . . $enable_aquaero])
+AC_MSG_RESULT([ ascent . . . . . . . $enable_ascent])
+AC_MSG_RESULT([ barometer . . . . . . $enable_barometer])
+AC_MSG_RESULT([ battery . . . . . . . $enable_battery])
+AC_MSG_RESULT([ bind . . . . . . . . $enable_bind])
+AC_MSG_RESULT([ ceph . . . . . . . . $enable_ceph])
+AC_MSG_RESULT([ cgroups . . . . . . . $enable_cgroups])
+AC_MSG_RESULT([ chrony. . . . . . . . $enable_chrony])
+AC_MSG_RESULT([ conntrack . . . . . . $enable_conntrack])
+AC_MSG_RESULT([ contextswitch . . . . $enable_contextswitch])
+AC_MSG_RESULT([ cpu . . . . . . . . . $enable_cpu])
+AC_MSG_RESULT([ cpufreq . . . . . . . $enable_cpufreq])
+AC_MSG_RESULT([ cpusleep . . . . . . $enable_cpusleep])
+AC_MSG_RESULT([ csv . . . . . . . . . $enable_csv])
+AC_MSG_RESULT([ curl . . . . . . . . $enable_curl])
+AC_MSG_RESULT([ curl_json . . . . . . $enable_curl_json])
+AC_MSG_RESULT([ curl_xml . . . . . . $enable_curl_xml])
+AC_MSG_RESULT([ dbi . . . . . . . . . $enable_dbi])
+AC_MSG_RESULT([ df . . . . . . . . . $enable_df])
+AC_MSG_RESULT([ disk . . . . . . . . $enable_disk])
+AC_MSG_RESULT([ dns . . . . . . . . . $enable_dns])
+AC_MSG_RESULT([ drbd . . . . . . . . $enable_drbd])
+AC_MSG_RESULT([ email . . . . . . . . $enable_email])
+AC_MSG_RESULT([ entropy . . . . . . . $enable_entropy])
+AC_MSG_RESULT([ ethstat . . . . . . . $enable_ethstat])
+AC_MSG_RESULT([ exec . . . . . . . . $enable_exec])
+AC_MSG_RESULT([ fhcount . . . . . . . $enable_fhcount])
+AC_MSG_RESULT([ filecount . . . . . . $enable_filecount])
+AC_MSG_RESULT([ fscache . . . . . . . $enable_fscache])
+AC_MSG_RESULT([ gmond . . . . . . . . $enable_gmond])
+AC_MSG_RESULT([ gps . . . . . . . . . $enable_gps])
+AC_MSG_RESULT([ grpc . . . . . . . . $enable_grpc])
+AC_MSG_RESULT([ hddtemp . . . . . . . $enable_hddtemp])
+AC_MSG_RESULT([ interface . . . . . . $enable_interface])
+AC_MSG_RESULT([ ipc . . . . . . . . . $enable_ipc])
+AC_MSG_RESULT([ ipmi . . . . . . . . $enable_ipmi])
+AC_MSG_RESULT([ iptables . . . . . . $enable_iptables])
+AC_MSG_RESULT([ ipvs . . . . . . . . $enable_ipvs])
+AC_MSG_RESULT([ irq . . . . . . . . . $enable_irq])
+AC_MSG_RESULT([ java . . . . . . . . $enable_java])
+AC_MSG_RESULT([ load . . . . . . . . $enable_load])
+AC_MSG_RESULT([ logfile . . . . . . . $enable_logfile])
+AC_MSG_RESULT([ log_logstash . . . . $enable_log_logstash])
+AC_MSG_RESULT([ lpar . . . . . . . . $enable_lpar])
+AC_MSG_RESULT([ lua . . . . . . . . . $enable_lua])
+AC_MSG_RESULT([ lvm . . . . . . . . . $enable_lvm])
+AC_MSG_RESULT([ madwifi . . . . . . . $enable_madwifi])
+AC_MSG_RESULT([ match_empty_counter . $enable_match_empty_counter])
+AC_MSG_RESULT([ match_hashed . . . . $enable_match_hashed])
+AC_MSG_RESULT([ match_regex . . . . . $enable_match_regex])
+AC_MSG_RESULT([ match_timediff . . . $enable_match_timediff])
+AC_MSG_RESULT([ match_value . . . . . $enable_match_value])
+AC_MSG_RESULT([ mbmon . . . . . . . . $enable_mbmon])
+AC_MSG_RESULT([ md . . . . . . . . . $enable_md])
+AC_MSG_RESULT([ memcachec . . . . . . $enable_memcachec])
+AC_MSG_RESULT([ memcached . . . . . . $enable_memcached])
+AC_MSG_RESULT([ memory . . . . . . . $enable_memory])
+AC_MSG_RESULT([ mic . . . . . . . . . $enable_mic])
+AC_MSG_RESULT([ modbus . . . . . . . $enable_modbus])
+AC_MSG_RESULT([ mqtt . . . . . . . . $enable_mqtt])
+AC_MSG_RESULT([ multimeter . . . . . $enable_multimeter])
+AC_MSG_RESULT([ mysql . . . . . . . . $enable_mysql])
+AC_MSG_RESULT([ netapp . . . . . . . $enable_netapp])
+AC_MSG_RESULT([ netlink . . . . . . . $enable_netlink])
+AC_MSG_RESULT([ network . . . . . . . $enable_network])
+AC_MSG_RESULT([ nfs . . . . . . . . . $enable_nfs])
+AC_MSG_RESULT([ nginx . . . . . . . . $enable_nginx])
+AC_MSG_RESULT([ notify_desktop . . . $enable_notify_desktop])
+AC_MSG_RESULT([ notify_email . . . . $enable_notify_email])
+AC_MSG_RESULT([ notify_nagios . . . . $enable_notify_nagios])
+AC_MSG_RESULT([ ntpd . . . . . . . . $enable_ntpd])
+AC_MSG_RESULT([ numa . . . . . . . . $enable_numa])
+AC_MSG_RESULT([ nut . . . . . . . . . $enable_nut])
+AC_MSG_RESULT([ olsrd . . . . . . . . $enable_olsrd])
+AC_MSG_RESULT([ onewire . . . . . . . $enable_onewire])
+AC_MSG_RESULT([ openldap . . . . . . $enable_openldap])
+AC_MSG_RESULT([ openvpn . . . . . . . $enable_openvpn])
+AC_MSG_RESULT([ oracle . . . . . . . $enable_oracle])
+AC_MSG_RESULT([ perl . . . . . . . . $enable_perl])
+AC_MSG_RESULT([ pf . . . . . . . . . $enable_pf])
+AC_MSG_RESULT([ pinba . . . . . . . . $enable_pinba])
+AC_MSG_RESULT([ ping . . . . . . . . $enable_ping])
+AC_MSG_RESULT([ postgresql . . . . . $enable_postgresql])
+AC_MSG_RESULT([ powerdns . . . . . . $enable_powerdns])
+AC_MSG_RESULT([ processes . . . . . . $enable_processes])
+AC_MSG_RESULT([ protocols . . . . . . $enable_protocols])
+AC_MSG_RESULT([ python . . . . . . . $enable_python])
+AC_MSG_RESULT([ redis . . . . . . . . $enable_redis])
+AC_MSG_RESULT([ routeros . . . . . . $enable_routeros])
+AC_MSG_RESULT([ rrdcached . . . . . . $enable_rrdcached])
+AC_MSG_RESULT([ rrdtool . . . . . . . $enable_rrdtool])
+AC_MSG_RESULT([ sensors . . . . . . . $enable_sensors])
+AC_MSG_RESULT([ serial . . . . . . . $enable_serial])
+AC_MSG_RESULT([ sigrok . . . . . . . $enable_sigrok])
+AC_MSG_RESULT([ smart . . . . . . . . $enable_smart])
+AC_MSG_RESULT([ snmp . . . . . . . . $enable_snmp])
+AC_MSG_RESULT([ statsd . . . . . . . $enable_statsd])
+AC_MSG_RESULT([ swap . . . . . . . . $enable_swap])
+AC_MSG_RESULT([ syslog . . . . . . . $enable_syslog])
+AC_MSG_RESULT([ table . . . . . . . . $enable_table])
+AC_MSG_RESULT([ tail_csv . . . . . . $enable_tail_csv])
+AC_MSG_RESULT([ tail . . . . . . . . $enable_tail])
+AC_MSG_RESULT([ tape . . . . . . . . $enable_tape])
+AC_MSG_RESULT([ target_notification . $enable_target_notification])
+AC_MSG_RESULT([ target_replace . . . $enable_target_replace])
+AC_MSG_RESULT([ target_scale . . . . $enable_target_scale])
+AC_MSG_RESULT([ target_set . . . . . $enable_target_set])
+AC_MSG_RESULT([ target_v5upgrade . . $enable_target_v5upgrade])
+AC_MSG_RESULT([ tcpconns . . . . . . $enable_tcpconns])
+AC_MSG_RESULT([ teamspeak2 . . . . . $enable_teamspeak2])
+AC_MSG_RESULT([ ted . . . . . . . . . $enable_ted])
+AC_MSG_RESULT([ thermal . . . . . . . $enable_thermal])
+AC_MSG_RESULT([ threshold . . . . . . $enable_threshold])
+AC_MSG_RESULT([ tokyotyrant . . . . . $enable_tokyotyrant])
+AC_MSG_RESULT([ turbostat . . . . . . $enable_turbostat])
+AC_MSG_RESULT([ unixsock . . . . . . $enable_unixsock])
+AC_MSG_RESULT([ uptime . . . . . . . $enable_uptime])
+AC_MSG_RESULT([ users . . . . . . . . $enable_users])
+AC_MSG_RESULT([ uuid . . . . . . . . $enable_uuid])
+AC_MSG_RESULT([ varnish . . . . . . . $enable_varnish])
+AC_MSG_RESULT([ virt . . . . . . . . $enable_virt])
+AC_MSG_RESULT([ vmem . . . . . . . . $enable_vmem])
+AC_MSG_RESULT([ vserver . . . . . . . $enable_vserver])
+AC_MSG_RESULT([ wireless . . . . . . $enable_wireless])
+AC_MSG_RESULT([ write_graphite . . . $enable_write_graphite])
+AC_MSG_RESULT([ write_http . . . . . $enable_write_http])
+AC_MSG_RESULT([ write_kafka . . . . . $enable_write_kafka])
+AC_MSG_RESULT([ write_log . . . . . . $enable_write_log])
+AC_MSG_RESULT([ write_mongodb . . . . $enable_write_mongodb])
+AC_MSG_RESULT([ write_redis . . . . . $enable_write_redis])
+AC_MSG_RESULT([ write_riemann . . . . $enable_write_riemann])
+AC_MSG_RESULT([ write_sensu . . . . . $enable_write_sensu])
+AC_MSG_RESULT([ write_tsdb . . . . . $enable_write_tsdb])
+AC_MSG_RESULT([ xencpu . . . . . . . $enable_xencpu])
+AC_MSG_RESULT([ xmms . . . . . . . . $enable_xmms])
+AC_MSG_RESULT([ zfs_arc . . . . . . . $enable_zfs_arc])
+AC_MSG_RESULT([ zone . . . . . . . . $enable_zone])
+AC_MSG_RESULT([ zookeeper . . . . . . $enable_zookeeper])
+AC_MSG_RESULT()
if test "x$dependency_error" = "xyes"; then
AC_MSG_ERROR("Some plugins are missing dependencies - see the summary above for details")
diff --git a/contrib/README b/contrib/README
index 3ca9386fab022c356603833a72ac659581019af0..5f401f0938e90cf55e90b528502c757327d6df43 100644 (file)
--- a/contrib/README
+++ b/contrib/README
RRD-file that should have been in multiple RRD-files instead. Is is used by
`migrate-3-4.px' to split up the cpu-, nfs-, swap-files and possibly others.
-fedora/
--------
- Init-script and Spec-file that can be used when creating RPM-packages for
-Fedora.
-
GenericJMX.conf
---------------
Example configuration file for the ‘GenericJMX’ Java plugin. Please read the
diff --git a/contrib/collectd.service b/contrib/collectd.service
--- a/contrib/collectd.service
+++ /dev/null
@@ -1,15 +0,0 @@
-[Unit]
-Description=statistics collection daemon
-Documentation=man:collectd(1)
-After=local-fs.target network.target
-Requires=local-fs.target network.target
-
-[Service]
-ExecStart=/usr/sbin/collectd -C /etc/collectd/collectd.conf -f
-Restart=always
-RestartSec=10
-StandardOutput=syslog
-StandardError=syslog
-
-[Install]
-WantedBy=multi-user.target
diff --git a/contrib/collection3/lib/Collectd/Graph/Common.pm b/contrib/collection3/lib/Collectd/Graph/Common.pm
index cc7e141f8828380fb8978c796faf4df46f4c6653..31c530f466987f403b76db500a117a9cb1b5a085 100644 (file)
my $ident = shift;
my $all_files;
my @ret = ();
+ my $temp;
+ my $hosts;
my $cache_key = ident_to_string ($ident);
if (defined ($Cache->{'get_files_by_ident'}{$cache_key}))
return ($ret)
}
- $all_files = _get_all_files ();
+ if ($ident->{'hostname'})
+ {
+ $all_files = [];
+ $hosts = $ident->{'hostname'};
+ foreach (@$hosts)
+ {
+ $temp = get_files_for_host ($_);
+ push (@$all_files, @$temp);
+ }
+ }
+ else
+ {
+ $all_files = _get_all_files ();
+ }
@ret = grep { _filter_ident ($ident, $_) == 0 } (@$all_files);
index d836a7932a4ae12961117948ab24b69a3d8f10e7..ab3ec2fd383df59a5f4c6624ee1d79a554c09fc5 100644 (file)
#endif /* ! HAVE_CONFIG */
#include <collectd/collectd.h>
+
#include <collectd/common.h>
#include <collectd/plugin.h>
diff --git a/contrib/fedora/collectd.spec b/contrib/fedora/collectd.spec
+++ /dev/null
@@ -1,376 +0,0 @@
-Summary: Statistics collection daemon for filling RRD files.
-Name: collectd
-Version: 4.2.0
-Release: 1.fc6
-Source: http://collectd.org/files/%{name}-%{version}.tar.gz
-License: GPL
-Group: System Environment/Daemons
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-BuildPrereq: lm_sensors-devel
-BuildPrereq: mysql-devel
-BuildPrereq: rrdtool-devel
-BuildPrereq: net-snmp-devel
-Requires: rrdtool
-Requires: perl-Regexp-Common
-Packager: Florian octo Forster <octo@verplant.org>
-Vendor: Florian octo Forster <octo@verplant.org>
-
-%description
-collectd is a small daemon written in C for performance. It reads various
-system statistics and updates RRD files, creating them if neccessary.
-Since the daemon doesn't need to startup every time it wants to update the
-files it's very fast and easy on the system. Also, the statistics are very
-fine grained since the files are updated every 10 seconds.
-
-%package apache
-Summary: apache-plugin for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, curl
-%description apache
-This plugin collectd data provided by Apache's `mod_status'.
-
-%package email
-Summary: email-plugin for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, spamassassin
-%description email
-This plugin collectd data provided by spamassassin.
-
-%package mysql
-Summary: mysql-module for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, mysql
-%description mysql
-MySQL querying plugin. This plugins provides data of issued commands,
-called handlers and database traffic.
-
-%package sensors
-Summary: libsensors-module for collectd.
-Group: System Environment/Daemons
-Requires: collectd = %{version}, lm_sensors
-%description sensors
-This plugin for collectd provides querying of sensors supported by
-lm_sensors.
-
-%prep
-rm -rf $RPM_BUILD_ROOT
-%setup
-
-%build
-./configure --prefix=%{_prefix} --sbindir=%{_sbindir} --mandir=%{_mandir} --libdir=%{_libdir} --sysconfdir=%{_sysconfdir}
-make
-
-%install
-make install DESTDIR=$RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
-mkdir -p $RPM_BUILD_ROOT/var/www/cgi-bin
-cp src/collectd.conf $RPM_BUILD_ROOT/etc/collectd.conf
-cp contrib/fedora/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd
-cp contrib/collection.cgi $RPM_BUILD_ROOT/var/www/cgi-bin
-cp contrib/collection.conf $RPM_BUILD_ROOT/etc/collection.conf
-mkdir -p $RPM_BUILD_ROOT/var/lib/collectd
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%post
-/sbin/chkconfig --add collectd
-/sbin/chkconfig collectd on
-
-%preun
-if [ "$1" = 0 ]; then
- /sbin/chkconfig collectd off
- /etc/init.d/collectd stop
- /sbin/chkconfig --del collectd
-fi
-exit 0
-
-%postun
-if [ "$1" -ge 1 ]; then
- /etc/init.d/collectd restart
-fi
-exit 0
-
-%files
-%defattr(-,root,root)
-%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
-%attr(0644,root,root) %config(noreplace) /etc/collectd.conf
-%attr(0644,root,root) %config(noreplace) /etc/collection.conf
-%attr(0755,root,root) /etc/rc.d/init.d/collectd
-%attr(0755,root,root) /var/www/cgi-bin/collection.cgi
-%attr(0755,root,root) %{_sbindir}/collectd
-%attr(0755,root,root) %{_bindir}/collectd-nagios
-%attr(0644,root,root) %{_mandir}/man1/*
-%attr(0644,root,root) %{_mandir}/man5/*
-
-%attr(0644,root,root) /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd.pm
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd/Unixsock.pm
-%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Collectd/.packlist
-%attr(0644,root,root) %{_mandir}/man3/Collectd::Unixsock.3pm.gz
-
-%attr(0644,root,root) %{_libdir}/%{name}/apcups.so*
-%attr(0644,root,root) %{_libdir}/%{name}/apcups.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/battery.so*
-%attr(0644,root,root) %{_libdir}/%{name}/battery.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/conntrack.so*
-%attr(0644,root,root) %{_libdir}/%{name}/conntrack.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.so*
-%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/cpu.so*
-%attr(0644,root,root) %{_libdir}/%{name}/cpu.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/csv.so*
-%attr(0644,root,root) %{_libdir}/%{name}/csv.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/df.so*
-%attr(0644,root,root) %{_libdir}/%{name}/df.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/disk.so*
-%attr(0644,root,root) %{_libdir}/%{name}/disk.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/dns.so*
-%attr(0644,root,root) %{_libdir}/%{name}/dns.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/entropy.so*
-%attr(0644,root,root) %{_libdir}/%{name}/entropy.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/exec.so*
-%attr(0644,root,root) %{_libdir}/%{name}/exec.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.so*
-%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/interface.so*
-%attr(0644,root,root) %{_libdir}/%{name}/interface.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/iptables.so*
-%attr(0644,root,root) %{_libdir}/%{name}/iptables.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/irq.so*
-%attr(0644,root,root) %{_libdir}/%{name}/irq.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/load.so*
-%attr(0644,root,root) %{_libdir}/%{name}/load.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/logfile.so*
-%attr(0644,root,root) %{_libdir}/%{name}/logfile.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/mbmon.so*
-%attr(0644,root,root) %{_libdir}/%{name}/mbmon.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/memcached.so*
-%attr(0644,root,root) %{_libdir}/%{name}/memcached.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/memory.so*
-%attr(0644,root,root) %{_libdir}/%{name}/memory.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/multimeter.so*
-%attr(0644,root,root) %{_libdir}/%{name}/multimeter.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/network.so*
-%attr(0644,root,root) %{_libdir}/%{name}/network.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/nfs.so*
-%attr(0644,root,root) %{_libdir}/%{name}/nfs.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/nginx.so*
-%attr(0644,root,root) %{_libdir}/%{name}/nginx.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/ntpd.so*
-%attr(0644,root,root) %{_libdir}/%{name}/ntpd.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/nut.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/nut.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/perl.so*
-%attr(0644,root,root) %{_libdir}/%{name}/perl.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/ping.so*
-%attr(0644,root,root) %{_libdir}/%{name}/ping.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/processes.so*
-%attr(0644,root,root) %{_libdir}/%{name}/processes.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.so*
-%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/serial.so*
-%attr(0644,root,root) %{_libdir}/%{name}/serial.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/swap.so*
-%attr(0644,root,root) %{_libdir}/%{name}/swap.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/snmp.so*
-%attr(0644,root,root) %{_libdir}/%{name}/snmp.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/syslog.so*
-%attr(0644,root,root) %{_libdir}/%{name}/syslog.la
-
-# FIXME!!!
-#%attr(0644,root,root) %{_libdir}/%{name}/tape.so*
-#%attr(0644,root,root) %{_libdir}/%{name}/tape.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.so*
-%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/unixsock.so*
-%attr(0644,root,root) %{_libdir}/%{name}/unixsock.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/users.so*
-%attr(0644,root,root) %{_libdir}/%{name}/users.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/vserver.so*
-%attr(0644,root,root) %{_libdir}/%{name}/vserver.la
-
-%attr(0644,root,root) %{_libdir}/%{name}/wireless.so*
-%attr(0644,root,root) %{_libdir}/%{name}/wireless.la
-
-%attr(0644,root,root) %{_datadir}/%{name}/types.db
-
-%dir /var/lib/collectd
-
-%files apache
-%attr(0644,root,root) %{_libdir}/%{name}/apache.so*
-%attr(0644,root,root) %{_libdir}/%{name}/apache.la
-
-%files email
-%attr(0644,root,root) %{_libdir}/%{name}/email.so*
-%attr(0644,root,root) %{_libdir}/%{name}/email.la
-
-%files mysql
-%attr(0644,root,root) %{_libdir}/%{name}/mysql.so*
-%attr(0644,root,root) %{_libdir}/%{name}/mysql.la
-
-%files sensors
-%attr(0644,root,root) %{_libdir}/%{name}/sensors.so*
-%attr(0644,root,root) %{_libdir}/%{name}/sensors.la
-
-%changelog
-* Wed Oct 31 2007 Iain Lea <iain@bricbrac.de> 4.2.0
-- New major release
-- Changes to support 4.2.0 (ie. contrib/collection.conf)
-
-* Mon Aug 06 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.6
-- New upstream version
-
-* Wed Jul 25 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.5
-- New major release
-- Changes to support 4.0.5
-
-* Wed Jan 11 2007 Iain Lea <iain@bricbrac.de> 3.11.0-0
-- fixed spec file to build correctly on fedora core
-- added improved init.d script to work with chkconfig
-- added %post and %postun to call chkconfig automatically
-
-* Sun Jul 09 2006 Florian octo Forster <octo@verplant.org> 3.10.0-1
-- New upstream version
-
-* Tue Jun 25 2006 Florian octo Forster <octo@verplant.org> 3.9.4-1
-- New upstream version
-
-* Tue Jun 01 2006 Florian octo Forster <octo@verplant.org> 3.9.3-1
-- New upstream version
-
-* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.9.2-1
-- New upstream version
-
-* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.8.5-1
-- New upstream version
-
-* Fri Apr 21 2006 Florian octo Forster <octo@verplant.org> 3.9.1-1
-- New upstream version
-
-* Fri Apr 14 2006 Florian octo Forster <octo@verplant.org> 3.9.0-1
-- New upstream version
-- Added the `apache' package.
-
-* Thu Mar 14 2006 Florian octo Forster <octo@verplant.org> 3.8.2-1
-- New upstream version
-
-* Thu Mar 13 2006 Florian octo Forster <octo@verplant.org> 3.8.1-1
-- New upstream version
-
-* Thu Mar 09 2006 Florian octo Forster <octo@verplant.org> 3.8.0-1
-- New upstream version
-
-* Sat Feb 18 2006 Florian octo Forster <octo@verplant.org> 3.7.2-1
-- Include `tape.so' so the build doesn't terminate because of missing files..
-- New upstream version
-
-* Sat Feb 04 2006 Florian octo Forster <octo@verplant.org> 3.7.1-1
-- New upstream version
-
-* Mon Jan 30 2006 Florian octo Forster <octo@verplant.org> 3.7.0-1
-- New upstream version
-- Removed the extra `hddtemp' package
-
-* Tue Jan 24 2006 Florian octo Forster <octo@verplant.org> 3.6.2-1
-- New upstream version
-
-* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.1-1
-- New upstream version
-
-* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.0-1
-- New upstream version
-- Added config file, `collectd.conf(5)', `df.so'
-- Added package `collectd-mysql', dependency on `mysqlclient10 | mysql'
-
-* Wed Dec 07 2005 Florian octo Forster <octo@verplant.org> 3.5.0-1
-- New upstream version
-
-* Sat Nov 26 2005 Florian octo Forster <octo@verplant.org> 3.4.0-1
-- New upstream version
-
-* Sat Nov 05 2005 Florian octo Forster <octo@verplant.org> 3.3.0-1
-- New upstream version
-
-* Tue Oct 26 2005 Florian octo Forster <octo@verplant.org> 3.2.0-1
-- New upstream version
-- Added statement to remove the `*.la' files. This fixes a problem when
- `Unpackaged files terminate build' is in effect.
-- Added `processes.so*' to the main package
-
-* Fri Oct 14 2005 Florian octo Forster <octo@verplant.org> 3.1.0-1
-- New upstream version
-- Added package `collectd-hddtemp'
-
-* Fri Sep 30 2005 Florian octo Forster <octo@verplant.org> 3.0.0-1
-- New upstream version
-- Split the package into `collectd' and `collectd-sensors'
-
-* Fri Sep 16 2005 Florian octo Forster <octo@verplant.org> 2.1.0-1
-- New upstream version
-
-* Mon Sep 10 2005 Florian octo Forster <octo@verplant.org> 2.0.0-1
-- New upstream version
-
-* Mon Aug 29 2005 Florian octo Forster <octo@verplant.org> 1.8.0-1
-- New upstream version
-
-* Sun Aug 25 2005 Florian octo Forster <octo@verplant.org> 1.7.0-1
-- New upstream version
-
-* Sun Aug 21 2005 Florian octo Forster <octo@verplant.org> 1.6.0-1
-- New upstream version
-
-* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5.1-1
-- New upstream version
-
-* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5-1
-- New upstream version
-
-* Mon Jul 11 2005 Florian octo Forster <octo@verplant.org> 1.4.2-1
-- New upstream version
-
-* Sat Jul 09 2005 Florian octo Forster <octo@verplant.org> 1.4-1
-- Built on RedHat 7.3
diff --git a/contrib/fedora/init.d-collectd b/contrib/fedora/init.d-collectd
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-#
-# collectd Startup script for the Collectd statistics gathering daemon
-# chkconfig: - 86 15
-# description: Collectd is a statistics gathering daemon used to collect \
-# system information ie. cpu, memory, disk, network
-# processname: collectd
-# config: /etc/collectd.conf
-# config: /etc/sysconfig/collectd
-# pidfile: /var/run/collectd.pid
-
-# Source function library.
-. /etc/init.d/functions
-
-RETVAL=0
-ARGS=""
-prog="collectd"
-CONFIG=/etc/collectd.conf
-
-if [ -r /etc/default/$prog ]; then
- . /etc/default/$prog
-fi
-
-start () {
- echo -n $"Starting $prog: "
- if [ -r "$CONFIG" ]
- then
- daemon /usr/sbin/collectd -C "$CONFIG"
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
- fi
-}
-stop () {
- echo -n $"Stopping $prog: "
- killproc $prog
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
-}
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status $prog
- ;;
- restart|reload)
- stop
- start
- ;;
- condrestart)
- [ -f /var/lock/subsys/$prog ] && stop && start || :
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
- exit 1
-esac
-
-exit $?
-
-# vim:syntax=sh
index 4f6306be78828eb7fdb97617b612bd621dbab1a8..4c136d65b162a8a998e0098839d9fc57cc85e2af 100644 (file)
%global _hardened_build 1
%{?perl_default_filter}
-# plugins only buildable on RHEL6
-# (NB: %{elN} macro is not available on RHEL < 6)
-%{?el6:%global _has_libyajl 1}
-%{?el6:%global _has_recent_libpcap 1}
-%{?el6:%global _has_recent_sockios_h 1}
-%{?el6:%global _has_recent_libganglia 1}
-%{?el6:%global _has_working_libiptc 1}
-%{?el6:%global _has_ip_vs_h 1}
-%{?el6:%global _has_lvm2app_h 1}
-%{?el6:%global _has_libmodbus 1}
-%{?el6:%global _has_libudev 1}
-%{?el6:%global _has_iproute 1}
-%{?el6:%global _has_atasmart 1}
-%{?el6:%global _has_hiredis 1}
-%{?el6:%global _has_asm_msr_index 1}
-
-%{?el7:%global _has_libyajl 1}
-%{?el7:%global _has_recent_libpcap 1}
-%{?el7:%global _has_recent_sockios_h 1}
-%{?el7:%global _has_working_libiptc 1}
-%{?el7:%global _has_ip_vs_h 1}
-%{?el7:%global _has_lvm2app_h 1}
-%{?el7:%global _has_libudev 1}
-%{?el7:%global _has_recent_librrd 1}
-%{?el7:%global _has_iproute 1}
-%{?el7:%global _has_atasmart 1}
-%{?el7:%global _has_hiredis 1}
-%{?el7:%global _has_asm_msr_index 1}
-%{?el7:%global _has_libmodbus 1}
-%{?el7:%global _has_xmms 1}
-
# plugins enabled by default
%define with_aggregation 0%{!?_without_aggregation:1}
%define with_amqp 0%{!?_without_amqp:1}
%define with_ascent 0%{!?_without_ascent:1}
%define with_battery 0%{!?_without_battery:1}
%define with_bind 0%{!?_without_bind:1}
-%define with_ceph 0%{!?_without_ceph:0%{?_has_libyajl}}
+%define with_ceph 0%{!?_without_ceph:1}
%define with_cgroups 0%{!?_without_cgroups:1}
+%define with_chrony 0%{!?_without_chrony:1}
%define with_conntrack 0%{!?_without_conntrack:1}
%define with_contextswitch 0%{!?_without_contextswitch:1}
%define with_cpu 0%{!?_without_cpu:1}
%define with_cpufreq 0%{!?_without_cpufreq:1}
+%define with_cpusleep 0%{!?_without_cpusleep:1}
%define with_csv 0%{!?_without_csv:1}
%define with_curl 0%{!?_without_curl:1}
-%define with_curl_json 0%{!?_without_curl_json:0%{?_has_libyajl}}
+%define with_curl_json 0%{!?_without_curl_json:1}
%define with_curl_xml 0%{!?_without_curl_xml:1}
%define with_dbi 0%{!?_without_dbi:1}
%define with_df 0%{!?_without_df:1}
%define with_disk 0%{!?_without_disk:1}
-%define with_dns 0%{!?_without_dns:0%{?_has_recent_libpcap}}
+%define with_dns 0%{!?_without_dns:1}
%define with_drbd 0%{!?_without_drbd:1}
%define with_email 0%{!?_without_email:1}
%define with_entropy 0%{!?_without_entropy:1}
-%define with_ethstat 0%{!?_without_ethstat:0%{?_has_recent_sockios_h}}
+%define with_ethstat 0%{!?_without_ethstat:1}
%define with_exec 0%{!?_without_exec:1}
%define with_fhcount 0%{!?_without_fhcount:1}
%define with_filecount 0%{!?_without_filecount:1}
%define with_fscache 0%{!?_without_fscache:1}
-%define with_gmond 0%{!?_without_gmond:0%{?_has_recent_libganglia}}
+%define with_gmond 0%{!?_without_gmond:1}
+%define with_gps 0%{!?_without_gps:1}
%define with_hddtemp 0%{!?_without_hddtemp:1}
%define with_interface 0%{!?_without_interface:1}
%define with_ipc 0%{!?_without_ipc:1}
%define with_ipmi 0%{!?_without_ipmi:1}
-%define with_iptables 0%{!?_without_iptables:0%{?_has_working_libiptc}}
-%define with_ipvs 0%{!?_without_ipvs:0%{?_has_ip_vs_h}}
+%define with_iptables 0%{!?_without_iptables:1}
+%define with_ipvs 0%{!?_without_ipvs:1}
%define with_irq 0%{!?_without_irq:1}
%define with_java 0%{!?_without_java:1}
-%define with_virt 0%{!?_without_virt:1}
%define with_load 0%{!?_without_load:1}
+%define with_log_logstash 0%{!?_without_log_logstash:1}
%define with_logfile 0%{!?_without_logfile:1}
-%define with_log_logstash 0%{!?_without_log_logstash:0%{?_has_libyajl}}
-%define with_lvm 0%{!?_without_lvm:0%{?_has_lvm2app_h}}
+%define with_lua 0%{!?_without_lua:1}
+%define with_lvm 0%{!?_without_lvm:1}
%define with_madwifi 0%{!?_without_madwifi:1}
%define with_mbmon 0%{!?_without_mbmon:1}
%define with_md 0%{!?_without_md:1}
%define with_memcachec 0%{!?_without_memcachec:1}
%define with_memcached 0%{!?_without_memcached:1}
%define with_memory 0%{!?_without_memory:1}
+%define with_modbus 0%{!?_without_modbus:1}
+%define with_mqtt 0%{!?_without_mqtt:1}
%define with_multimeter 0%{!?_without_multimeter:1}
-%define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}}
%define with_mysql 0%{!?_without_mysql:1}
-%define with_netlink 0%{!?_without_netlink:0%{?_has_iproute}}
+%define with_netlink 0%{!?_without_netlink:1}
%define with_network 0%{!?_without_network:1}
%define with_nfs 0%{!?_without_nfs:1}
%define with_nginx 0%{!?_without_nginx:1}
%define with_notify_desktop 0%{!?_without_notify_desktop:1}
%define with_notify_email 0%{!?_without_notify_email:1}
+%define with_notify_nagios 0%{!?_without_notify_nagios:1}
%define with_ntpd 0%{!?_without_ntpd:1}
%define with_numa 0%{!?_without_numa:1}
%define with_nut 0%{!?_without_nut:1}
%define with_processes 0%{!?_without_processes:1}
%define with_protocols 0%{!?_without_protocols:1}
%define with_python 0%{!?_without_python:1}
-%define with_redis 0%{!?_without_redis:0%{?_has_hiredis}}
-%define with_rrdcached 0%{!?_without_rrdcached:0%{?_has_recent_librrd}}
+%define with_redis 0%{!?_without_redis:1}
+%define with_rrdcached 0%{!?_without_rrdcached:1}
%define with_rrdtool 0%{!?_without_rrdtool:1}
%define with_sensors 0%{!?_without_sensors:1}
%define with_serial 0%{!?_without_serial:1}
-%define with_smart 0%{!?_without_smart:0%{?_has_atasmart}}
+%define with_smart 0%{!?_without_smart:1}
%define with_snmp 0%{!?_without_snmp:1}
%define with_statsd 0%{!?_without_statsd:1}
%define with_swap 0%{!?_without_swap:1}
%define with_ted 0%{!?_without_ted:1}
%define with_thermal 0%{!?_without_thermal:1}
%define with_threshold 0%{!?_without_threshold:1}
-%define with_turbostat 0%{!?_without_turbostat:0%{?_has_asm_msr_index}}
+%define with_turbostat 0%{!?_without_turbostat:1}
%define with_unixsock 0%{!?_without_unixsock:1}
%define with_uptime 0%{!?_without_uptime:1}
%define with_users 0%{!?_without_users:1}
%define with_uuid 0%{!?_without_uuid:1}
%define with_varnish 0%{!?_without_varnish:1}
+%define with_virt 0%{!?_without_virt:1}
%define with_vmem 0%{!?_without_vmem:1}
%define with_vserver 0%{!?_without_vserver:1}
%define with_wireless 0%{!?_without_wireless:1}
%define with_write_graphite 0%{!?_without_write_graphite:1}
%define with_write_http 0%{!?_without_write_http:1}
%define with_write_log 0%{!?_without_write_log:1}
-%define with_write_redis 0%{!?_without_write_redis:0%{?_has_hiredis}}
-%define with_write_riemann 0%{!?_without_write_riemann:1}
+%define with_write_redis 0%{!?_without_write_redis:1}
%define with_write_sensu 0%{!?_without_write_sensu:1}
%define with_write_tsdb 0%{!?_without_write_tsdb:1}
%define with_xmms 0%{!?_without_xmms:0%{?_has_xmms}}
%define with_aquaero 0%{!?_without_aquaero:0}
# plugin barometer disabled, requires a libi2c
%define with_barometer 0%{!?_without_barometer:0}
+# plugin grpc disabled, requires protobuf-compiler >= 3.0
+%define with_grpc 0%{!?_without_grpc:0}
# plugin lpar disabled, requires AIX
%define with_lpar 0%{!?_without_lpar:0}
# plugin mic disabled, requires Mic
%define with_write_kafka 0%{!?_without_write_kafka:0}
# plugin write_mongodb disabled, requires libmongoc
%define with_write_mongodb 0%{!?_without_write_mongodb:0}
-
-Summary: statistics collection and monitoring daemon
+# plugin write_riemann disabled, requires a new enough riemann_c_client
+%define with_write_riemann 0%{!?_without_write_riemann:0}
+# plugin xencpu disabled, requires xen-devel from non-default repo
+%define with_xencpu 0%{!?_without_xencpu:0}
+# plugin zone disabled, requires Solaris
+%define with_zone 0%{!?_without_zone:0}
+
+# Plugins not buildable on RHEL < 6
+%if 0%{?rhel} && 0%{?rhel} < 6
+%define with_ceph 0
+%define with_curl_json 0
+%define with_log_logstash 0
+%define with_dns 0
+%define with_ethstat 0
+%define with_gmond 0
+%define with_iptables 0
+%define with_ipvs 0
+%define with_lvm 0
+%define with_modbus 0
+%define with_netlink 0
+%define with_redis 0
+%define with_smart 0
+%define with_turbostat 0
+%define with_write_redis 0
+%endif
+
+# Plugins not buildable on RHEL < 7
+%if 0%{?rhel} && 0%{?rhel} < 7
+%define with_cpusleep 0
+%define with_gps 0
+%define with_mqtt 0
+%define with_rrdcached 0
+%define with_xmms 0
+%endif
+
+Summary: Statistics collection and monitoring daemon
Name: collectd
-Version: 5.5.2
+Version: 5.6.1
Release: 1%{?dist}
URL: https://collectd.org
Source: https://collectd.org/files/%{name}-%{version}.tar.bz2
License: GPLv2
Group: System Environment/Daemons
BuildRoot: %{_tmppath}/%{name}-%{version}-root
-BuildRequires: libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel
+BuildRequires: libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel, which
Vendor: collectd development team <collectd@verplant.org>
-%if 0%{?el7:1}
-Requires(pre): initscripts
-Requires(post): systemd
-Requires(preun): systemd
-Requires(postun): systemd
+%if 0%{?fedora} || 0%{?rhel} >= 7
+%{?systemd_requires}
+BuildRequires: systemd
%else
Requires(post): chkconfig
Requires(preun): chkconfig, initscripts
Ceph plugin for collectd
%endif
+%if %{with_chrony}
+%package chrony
+Summary: Chrony plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+%description chrony
+Chrony plugin for collectd
+%endif
+
%if %{with_curl}
%package curl
Summary: Curl plugin for collectd
the client daemon of the Ganglia project.
%endif
+%if %{with_gps}
+%package gps
+Summary: GPS plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: gpsd-devel
+%description gps
+This plugin monitor gps related data through gpsd.
+%endif
+
+%if %{with_grpc}
+%package grpc
+Summary: GRPC plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: protobuf-compiler
+%description grpc
+This plugin embeds a gRPC server into Collectd.
+%endif
+
%if %{with_hddtemp}
%package hddtemp
Summary: Hddtemp plugin for collectd
This plugin logs in logstash JSON format
%endif
+%if %{with_lua}
+%package lua
+Summary: Lua plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: lua-devel
+%description lua
+The Lua plugin embeds a Lua interpreter into collectd and exposes the
+application programming interface (API) to Lua scripts.
+%endif
+
%if %{with_lvm}
%package lvm
Summary: LVM plugin for collectd
handlers and database traffic.
%endif
+%if %{with_mqtt}
+%package mqtt
+Summary: mqtt plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: mosquitto-devel
+%description mqtt
+The MQTT plugin publishes and subscribes to MQTT topics.
+%endif
+
%if %{with_netlink}
%package netlink
Summary: netlink plugin for collectd
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
- %if 0%{?rhel} >= 6
-BuildRequires: perl-ExtUtils-Embed
- %else
+ %if 0%{?rhel} && 0%{?rhel} < 6
BuildRequires: perl
+ %else
+BuildRequires: perl-ExtUtils-Embed
%endif
%description perl
The Perl plugin embeds a Perl interpreter into collectd and exposes the
Summary: Python plugin for collectd
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
- %if 0%{?rhel} >= 6
-BuildRequires: python-devel
- %else
+ %if 0%{?rhel} && 0%{?rhel} < 6
BuildRequires: python26-devel
+ %else
+BuildRequires: python-devel
%endif
%description python
The Python plugin embeds a Python interpreter into collectd and exposes the
Summary: Write-kafka plugin for collectd
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
-BuildRequires: rdkafka-devel
+BuildRequires: librdkafka-devel
%description write_kafka
The write_kafka plugin sends values to kafka, a distributed messaging system.
%endif
The riemann plugin submits values to Riemann, an event stream processor.
%endif
+%if %{with_xencpu}
+%package xencpu
+Summary: xencpu plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: xen-devel
+%description xencpu
+The xencpu plugin collects CPU statistics from Xen.
+%endif
+
%if %{with_xmms}
%package xmms
Summary: XMMS plugin for collectd
%define _with_cgroups --disable-cgroups
%endif
+%if %{with_chrony}
+%define _with_chrony --enable-chrony
+%else
+%define _with_chrony --disable-chrony
+%endif
+
%if %{with_conntrack}
%define _with_conntrack --enable-conntrack
%else
%define _with_cpufreq --disable-cpufreq
%endif
+%if %{with_cpusleep}
+%define _with_cpusleep --enable-cpusleep
+%else
+%define _with_cpusleep --disable-cpusleep
+%endif
+
%if %{with_csv}
%define _with_csv --enable-csv
%else
%define _with_gmond --disable-gmond
%endif
+%if %{with_gps}
+%define _with_gps --enable-gps
+%else
+%define _with_gps --disable-gps
+%endif
+
+%if %{with_grpc}
+%define _with_grpc --enable-grpc
+%else
+%define _with_grpc --disable-grpc
+%endif
+
%if %{with_hddtemp}
%define _with_hddtemp --enable-hddtemp
%else
%define _with_lpar --disable-lpar
%endif
+%if %{with_lua}
+%define _with_lua --enable-lua
+%else
+%define _with_lua --disable-lua
+%endif
+
%if %{with_lvm}
%define _with_lvm --enable-lvm
%else
%define _with_multimeter --disable-multimeter
%endif
+%if %{with_mqtt}
+%define _with_mqtt --enable-mqtt
+%else
+%define _with_mqtt --disable-mqtt
+%endif
+
%if %{with_mysql}
%define _with_mysql --enable-mysql
%else
%define _with_notify_email --disable-notify_email
%endif
+%if %{with_notify_nagios}
+%define _with_notify_nagios --enable-notify_nagios
+%else
+%define _with_notify_nagios --disable-notify_nagios
+%endif
+
%if %{with_ntpd}
%define _with_ntpd --enable-ntpd
%else
%endif
%if %{with_python}
- %if 0%{?rhel} >= 6
-%define _with_python --enable-python
- %else
+ %if 0%{?rhel} && 0%{?rhel} < 6
%define _with_python --enable-python --with-python=%{_bindir}/python2.6
+%define _python_config PYTHON_CONFIG="%{_bindir}/python2.6-config"
+ %else
+%define _with_python --enable-python
%endif
%else
%define _with_python --disable-python
%define _with_write_tsdb --disable-write_tsdb
%endif
+%if %{with_xencpu}
+%define _with_xencpu --enable-xencpu
+%else
+%define _with_xencpu --disable-xencpu
+%endif
+
%if %{with_xmms}
%define _with_xmms --enable-xmms
%else
%define _with_zfs_arc --disable-zfs_arc
%endif
+%if %{with_zone}
+%define _with_zone --enable-zone
+%else
+%define _with_zone --disable-zone
+%endif
+
%if %{with_zookeeper}
%define _with_zookeeper --enable-zookeeper
%else
%endif
%configure CFLAGS="%{optflags} -DLT_LAZY_OR_NOW=\"RTLD_LAZY|RTLD_GLOBAL\"" \
+ %{?_python_config} \
--disable-static \
--without-included-ltdl \
--enable-all-plugins=yes \
%{?_with_bind} \
%{?_with_ceph} \
%{?_with_cgroups} \
+ %{?_with_chrony} \
%{?_with_conntrack} \
%{?_with_contextswitch} \
- %{?_with_cpu} \
%{?_with_cpufreq} \
+ %{?_with_cpusleep} \
+ %{?_with_cpu} \
%{?_with_csv} \
- %{?_with_curl} \
%{?_with_curl_json} \
%{?_with_curl_xml} \
+ %{?_with_curl} \
%{?_with_dbi} \
%{?_with_df} \
%{?_with_disk} \
%{?_with_filecount} \
%{?_with_fscache} \
%{?_with_gmond} \
+ %{?_with_gps} \
+ %{?_with_grpc} \
%{?_with_hddtemp} \
%{?_with_interface} \
%{?_with_ipc} \
%{?_with_ipmi} \
%{?_with_iptables} \
%{?_with_ipvs} \
+ %{?_with_irq} \
%{?_with_java} \
- %{?_with_virt} \
+ %{?_with_load} \
%{?_with_log_logstash} \
+ %{?_with_logfile} \
%{?_with_lpar} \
+ %{?_with_lua} \
%{?_with_lvm} \
+ %{?_with_madwifi} \
+ %{?_with_mbmon} \
+ %{?_with_md} \
%{?_with_memcachec} \
+ %{?_with_memcached} \
+ %{?_with_memory} \
%{?_with_mic} \
%{?_with_modbus} \
+ %{?_with_mqtt} \
%{?_with_multimeter} \
%{?_with_mysql} \
%{?_with_netapp} \
%{?_with_netlink} \
+ %{?_with_network} \
+ %{?_with_nfs} \
%{?_with_nginx} \
%{?_with_notify_desktop} \
%{?_with_notify_email} \
+ %{?_with_notify_nagios} \
+ %{?_with_ntpd} \
+ %{?_with_numa} \
%{?_with_nut} \
+ %{?_with_olsrd} \
%{?_with_onewire} \
%{?_with_openldap} \
+ %{?_with_openvpn} \
%{?_with_oracle} \
%{?_with_perl} \
%{?_with_pf} \
%{?_with_pinba} \
%{?_with_ping} \
%{?_with_postgresql} \
+ %{?_with_powerdns} \
+ %{?_with_processes} \
+ %{?_with_protocols} \
%{?_with_python} \
%{?_with_redis} \
%{?_with_routeros} \
%{?_with_rrdcached} \
%{?_with_rrdtool} \
%{?_with_sensors} \
+ %{?_with_serial} \
%{?_with_sigrok} \
%{?_with_smart} \
%{?_with_snmp} \
- %{?_with_tape} \
- %{?_with_tokyotyrant} \
- %{?_with_varnish} \
- %{?_with_write_http} \
- %{?_with_write_kafka} \
- %{?_with_write_mongodb} \
- %{?_with_write_redis} \
- %{?_with_xmms} \
- %{?_with_zfs_arc} \
- %{?_with_zookeeper} \
- %{?_with_irq} \
- %{?_with_load} \
- %{?_with_logfile} \
- %{?_with_madwifi} \
- %{?_with_mbmon} \
- %{?_with_md} \
- %{?_with_memcached} \
- %{?_with_memory} \
- %{?_with_network} \
- %{?_with_nfs} \
- %{?_with_ntpd} \
- %{?_with_numa} \
- %{?_with_olsrd} \
- %{?_with_openvpn} \
- %{?_with_powerdns} \
- %{?_with_processes} \
- %{?_with_protocols} \
- %{?_with_serial} \
%{?_with_statsd} \
%{?_with_swap} \
%{?_with_syslog} \
%{?_with_table} \
- %{?_with_tail} \
%{?_with_tail_csv} \
+ %{?_with_tail} \
+ %{?_with_tape} \
%{?_with_tcpconns} \
%{?_with_teamspeak2} \
%{?_with_ted} \
%{?_with_thermal} \
%{?_with_threshold} \
+ %{?_with_tokyotyrant} \
%{?_with_turbostat} \
%{?_with_unixsock} \
%{?_with_uptime} \
%{?_with_users} \
%{?_with_uuid} \
+ %{?_with_varnish} \
+ %{?_with_virt} \
%{?_with_vmem} \
%{?_with_vserver} \
%{?_with_wireless}\
%{?_with_write_graphite} \
%{?_with_write_http} \
+ %{?_with_write_http} \
+ %{?_with_write_kafka} \
%{?_with_write_log} \
+ %{?_with_write_mongodb} \
+ %{?_with_write_redis} \
%{?_with_write_riemann} \
%{?_with_write_sensu} \
- %{?_with_write_tsdb}
+ %{?_with_write_tsdb} \
+ %{?_with_xencpu} \
+ %{?_with_xmms} \
+ %{?_with_zfs_arc} \
+ %{?_with_zone} \
+ %{?_with_zookeeper}
%{__make} %{?_smp_mflags}
%install
rm -rf %{buildroot}
%{__make} install DESTDIR=%{buildroot}
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
%{__install} -Dp -m0644 contrib/systemd.collectd.service %{buildroot}%{_unitdir}/collectd.service
%else
%{__install} -Dp -m0755 contrib/redhat/init.d-collectd %{buildroot}%{_initrddir}/collectd
rm -f %{buildroot}%{_mandir}/man5/collectd-java.5*
%endif
+%if ! %{with_lua}
+rm -f %{buildroot}%{_mandir}/man5/collectd-lua.5*
+%endif
+
%if ! %{with_perl}
rm -f %{buildroot}%{_mandir}/man5/collectd-perl.5*
rm -f %{buildroot}%{_mandir}/man3/Collectd::Unixsock.3pm*
%clean
rm -rf %{buildroot}
-%pre
-%if 0%{?el7:1}
-# stop sysv-based instance before upgrading to systemd
-if [ $1 -eq 2 ] && [ -f /var/lock/subsys/collectd ]; then
- SYSTEMCTL_SKIP_REDIRECT=1 %{_initddir}/collectd stop >/dev/null 2>&1 || :
-fi
-%endif
-
%post
-%if 0%{?el7:1}
-if [ $1 -eq 2 ]; then
- /usr/bin/systemctl daemon-reload >/dev/null 2>&1 || :
-fi
+%if 0%{?fedora} || 0%{?rhel} >= 7
%systemd_post collectd.service
%else
/sbin/chkconfig --add collectd || :
%endif
%preun
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
%systemd_preun collectd.service
%else
# stop collectd only when uninstalling
%endif
%postun
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
%systemd_postun_with_restart collectd.service
%else
# restart collectd only when upgrading
%files
%doc AUTHORS COPYING ChangeLog README
%config(noreplace) %{_sysconfdir}/collectd.conf
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
%{_unitdir}/collectd.service
%else
%{_initrddir}/collectd
%if %{with_cpufreq}
%{_libdir}/%{name}/cpufreq.so
%endif
+%if %{with_cpusleep}
+%{_libdir}/%{name}/cpusleep.so
+%endif
%if %{with_csv}
%{_libdir}/%{name}/csv.so
%endif
%if %{with_nfs}
%{_libdir}/%{name}/nfs.so
%endif
+%if %{with_notify_nagios}
+%{_libdir}/%{name}/notify_nagios.so
+%endif
%if %{with_ntpd}
%{_libdir}/%{name}/ntpd.so
%endif
%{_libdir}/%{name}/ceph.so
%endif
+%if %{with_chrony}
+%files chrony
+%{_libdir}/%{name}/chrony.so
+%endif
+
%if %{with_curl}
%files curl
%{_libdir}/%{name}/curl.so
%{_libdir}/%{name}/gmond.so
%endif
+%if %{with_gps}
+%files gps
+%{_libdir}/%{name}/gps.so
+%endif
+
+%if %{with_grpc}
+%files grpc
+%{_libdir}/%{name}/grpc.so
+%endif
+
%if %{with_hddtemp}
%files hddtemp
%{_libdir}/%{name}/hddtemp.so
%{_libdir}/%{name}/log_logstash.so
%endif
+%if %{with_lua}
+%files lua
+%{_mandir}/man5/collectd-lua*
+%{_libdir}/%{name}/lua.so
+%endif
+
%if %{with_lvm}
%files lvm
%{_libdir}/%{name}/lvm.so
%{_libdir}/%{name}/modbus.so
%endif
+%if %{with_mqtt}
+%files mqtt
+%{_libdir}/%{name}/mqtt.so
+%endif
+
%if %{with_mysql}
%files mysql
%{_libdir}/%{name}/mysql.so
%{_libdir}/%{name}/write_riemann.so
%endif
+%if %{with_xencpu}
+%files xencpu
+%{_libdir}/%{name}/xencpu.so
+%endif
+
%if %{with_xmms}
%files xmms
%{_libdir}/%{name}/xmms.so
%doc contrib/
%changelog
+* Mon Oct 10 2016 Victor Demonchy <v.demonchy@criteo.com> - 5.6.1-1
+- New upstream version
+
+* Sun Aug 14 2016 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.6.0-1
+- New upstream version
+- New plugins enabled by default: chrony, cpusleep, gps, lua, mqtt, notify_nagios
+- New plugins disabled by default: grpc, xencpu, zone
+
* Tue Jul 26 2016 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.5.2-1
- New upstream version
- Contains fix for CVE-2016-6254
index c7806feddd905e1bc18de179e81cadf7ca057fcb..d0f1bdea9c049a757a2ce2ae06a8f96146994815 100644 (file)
[Unit]
-Description=Collectd
-After=local-fs.target network.target
-Requires=local-fs.target network.target
+Description=Collectd statistics daemon
+Documentation=man:collectd(1) man:collectd.conf(5)
+After=local-fs.target network-online.target
+Requires=local-fs.target network-online.target
[Service]
ExecStart=/usr/sbin/collectd
# socket once the daemon is ready. See systemd.service(5) for more details.
Type=notify
-# Restart the collectd daemon after a 10 seconds delay, in case it crashes.
+# Restart the collectd daemon when it fails.
Restart=on-failure
[Install]
diff --git a/proto/Makefile.am b/proto/Makefile.am
--- /dev/null
+++ b/proto/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST = collectd.proto types.proto
diff --git a/proto/collectd.proto b/proto/collectd.proto
--- /dev/null
+++ b/proto/collectd.proto
@@ -0,0 +1,62 @@
+// collectd - proto/collectd.proto
+// Copyright (C) 2015-2016 Sebastian Harl
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// Authors:
+// Sebastian Harl <sh at tokkee.org>
+
+syntax = "proto3";
+
+package collectd;
+option go_package = "collectd.org/rpc/proto";
+
+import "types.proto";
+
+service Collectd {
+ // DispatchValues reads the value lists from the DispatchValuesRequest stream.
+ // The gRPC server embedded into collectd will inject them into the system
+ // just like the network plugin.
+ rpc DispatchValues(stream DispatchValuesRequest)
+ returns (DispatchValuesResponse);
+
+ // QueryValues returns a stream of matching value lists from collectd's
+ // internal cache.
+ rpc QueryValues(QueryValuesRequest) returns (stream QueryValuesResponse);
+}
+
+// The arguments to DispatchValues.
+message DispatchValuesRequest {
+ // value_list is the metric to be sent to the server.
+ collectd.types.ValueList value_list = 1;
+}
+
+// The response from DispatchValues.
+message DispatchValuesResponse {}
+
+// The arguments to QueryValues.
+message QueryValuesRequest {
+ // Query by the fields of the identifier. Only return values matching the
+ // specified shell wildcard patterns (see fnmatch(3)). Use '*' to match
+ // any value.
+ collectd.types.Identifier identifier = 1;
+}
+
+// The response from QueryValues.
+message QueryValuesResponse { collectd.types.ValueList value_list = 1; }
diff --git a/proto/types.proto b/proto/types.proto
--- /dev/null
+++ b/proto/types.proto
@@ -0,0 +1,59 @@
+// collectd - proto/types.proto
+// Copyright (C) 2015-2016 Sebastian Harl
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// Authors:
+// Sebastian Harl <sh at tokkee.org>
+
+syntax = "proto3";
+
+package collectd.types;
+option go_package = "collectd.org/rpc/proto/types";
+
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+
+message Identifier {
+ string host = 1;
+ string plugin = 2;
+ string plugin_instance = 3;
+ string type = 4;
+ string type_instance = 5;
+}
+
+message Value {
+ oneof value {
+ uint64 counter = 1;
+ double gauge = 2;
+ int64 derive = 3;
+ uint64 absolute = 4;
+ };
+}
+
+message ValueList {
+ repeated Value values = 1;
+
+ google.protobuf.Timestamp time = 2;
+ google.protobuf.Duration interval = 3;
+
+ Identifier identifier = 4;
+
+ repeated string ds_names = 5;
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index dc07cb7401cdf091a61d823de047b14a61b0c05a..37160c108013b7a1091988b72abad282c53db6e4 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\<module_register\>'
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
AM_CPPFLAGS = -I$(srcdir)/daemon
AM_CPPFLAGS += -DPREFIX='"${prefix}"'
AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
-AUTOMAKE_OPTIONS = subdir-objects
-
-noinst_LTLIBRARIES = libmount.la liblookup.la
+LOG_COMPILER = env VALGRIND="@VALGRIND@" $(abs_top_srcdir)/testwrapper.sh
+
+V_PROTOC = $(v_protoc_@AM_V@)
+v_protoc_ = $(v_protoc_@AM_DEFAULT_V@)
+v_protoc_0 = @echo " PROTOC " $@;
+
+noinst_LTLIBRARIES =
+check_PROGRAMS =
+TESTS =
+
+noinst_LTLIBRARIES += libformat_json.la
+libformat_json_la_SOURCES = utils_format_json.c utils_format_json.h
+libformat_json_la_CPPFLAGS = $(AM_CPPFLAGS)
+libformat_json_la_LDFLAGS = $(AM_LDFLAGS)
+libformat_json_la_LIBADD =
+if BUILD_WITH_LIBYAJL
+libformat_json_la_CPPFLAGS += $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+libformat_json_la_LDFLAGS += $(BUILD_WITH_LIBYAJL_LDFLAGS)
+libformat_json_la_LIBADD += $(BUILD_WITH_LIBYAJL_LIBS)
+check_PROGRAMS += test_format_json
+TESTS += test_format_json
+test_format_json_SOURCES = utils_format_json_test.c testing.h
+test_format_json_LDADD = libformat_json.la daemon/libmetadata.la daemon/libplugin_mock.la -lm
+endif
+
+noinst_LTLIBRARIES += liblatency.la
+liblatency_la_SOURCES = utils_latency.c utils_latency.h
+check_PROGRAMS += test_utils_latency
+TESTS += test_utils_latency
+test_utils_latency_SOURCES = utils_latency_test.c testing.h
+test_utils_latency_LDADD = liblatency.la daemon/libplugin_mock.la -lm
+
+noinst_LTLIBRARIES += liblookup.la
+liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
+liblookup_la_LIBADD = daemon/libavltree.la
+check_PROGRAMS += test_utils_vl_lookup
+TESTS += test_utils_vl_lookup
+test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
+test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
+if BUILD_WITH_LIBKSTAT
+test_utils_vl_lookup_LDADD += -lkstat
+endif
+noinst_LTLIBRARIES += libmount.la
libmount_la_SOURCES = utils_mount.c utils_mount.h
-libmount_la_LIBADD = daemon/libcommon.la
-
-liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
-liblookup_la_LIBADD = daemon/libavltree.la daemon/libcommon.la
+check_PROGRAMS += test_utils_mount
+TESTS += test_utils_mount
+test_utils_mount_SOURCES = utils_mount_test.c testing.h
+test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
+if BUILD_WITH_LIBKSTAT
+test_utils_mount_LDADD += -lkstat
+endif
sbin_PROGRAMS = collectdmon
bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
collectdmon_SOURCES = collectdmon.c
-collectdmon_CPPFLAGS = $(AM_CPPFLAGS)
collectd_nagios_SOURCES = collectd-nagios.c
-collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectd_nagios_LDADD =
+collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/src/libcollectdclient/collectd \
+ -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_nagios_LDADD = libcollectdclient/libcollectdclient.la
if BUILD_WITH_LIBSOCKET
collectd_nagios_LDADD += -lsocket
endif
collectd_nagios_LDADD += -lm
endif
-collectd_nagios_LDADD += libcollectdclient/libcollectdclient.la
-collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la
-
collectdctl_SOURCES = collectdctl.c
-collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectdctl_LDADD =
+collectdctl_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/src/libcollectdclient/collectd \
+ -I$(top_builddir)/src/libcollectdclient/collectd
+collectdctl_LDADD = libcollectdclient/libcollectdclient.la
if BUILD_WITH_LIBSOCKET
collectdctl_LDADD += -lsocket
endif
if BUILD_AIX
collectdctl_LDADD += -lm
endif
-collectdctl_LDADD += libcollectdclient/libcollectdclient.la
-collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+
collectd_tg_SOURCES = collectd-tg.c
collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) \
- -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectd_tg_LDADD = daemon/libheap.la
+ -I$(top_srcdir)/src/libcollectdclient/collectd \
+ -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_LDADD = \
+ $(PTHREAD_LIBS) \
+ daemon/libheap.la \
+ libcollectdclient/libcollectdclient.la
if BUILD_WITH_LIBSOCKET
collectd_tg_LDADD += -lsocket
endif
if BUILD_AIX
collectd_tg_LDADD += -lm
endif
-if BUILD_WITH_LIBPTHREAD
-collectd_tg_LDADD += -lpthread
-endif
-collectd_tg_LDADD += libcollectdclient/libcollectdclient.la
-collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la
pkglib_LTLIBRARIES =
BUILT_SOURCES =
CLEANFILES =
+if HAVE_PROTOC3
+if HAVE_GRPC_CPP
+BUILT_SOURCES += collectd.grpc.pb.cc collectd.pb.cc types.pb.cc
+CLEANFILES += collectd.grpc.pb.cc collectd.pb.cc types.pb.cc \
+ collectd.grpc.pb.h collectd.pb.h types.pb.h
+
+collectd.grpc.pb.cc: $(top_srcdir)/proto/collectd.proto $(top_srcdir)/proto/types.proto
+ $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto \
+ --grpc_out=$(builddir) --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN) $<
+
+collectd.pb.cc: $(top_srcdir)/proto/collectd.proto $(top_srcdir)/proto/types.proto
+ $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto --cpp_out=$(builddir) $<
+
+types.pb.cc: $(top_srcdir)/proto/types.proto
+ $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto --cpp_out=$(builddir) $<
+endif
+endif
+
if BUILD_PLUGIN_AGGREGATION
pkglib_LTLIBRARIES += aggregation.la
aggregation_la_SOURCES = aggregation.c \
pkglib_LTLIBRARIES += amqp.la
amqp_la_SOURCES = amqp.c \
utils_cmd_putval.c utils_cmd_putval.h \
- utils_parse_option.c utils_parse_option.h \
- utils_format_graphite.c utils_format_graphite.h \
- utils_format_json.c utils_format_json.h
+ utils_parse_option.c utils_parse_option.h \
+ utils_format_graphite.c utils_format_graphite.h
amqp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
-amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS)
+amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS) libformat_json.la
endif
if BUILD_PLUGIN_APACHE
pkglib_LTLIBRARIES += apache.la
apache_la_SOURCES = apache.c
apache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-apache_la_CFLAGS = $(AM_CFLAGS)
-apache_la_LIBADD =
-if BUILD_WITH_LIBCURL
-apache_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-apache_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+apache_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
+apache_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
endif
+
if BUILD_PLUGIN_APCUPS
pkglib_LTLIBRARIES += apcups.la
apcups_la_SOURCES = apcups.c
if BUILD_PLUGIN_APPLE_SENSORS
pkglib_LTLIBRARIES += apple_sensors.la
apple_sensors_la_SOURCES = apple_sensors.c
-apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-apple_sensors_la_LDFLAGS += -framework IOKit
+apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) -framework IOKit
endif
if BUILD_PLUGIN_AQUAERO
pkglib_LTLIBRARIES += aquaero.la
aquaero_la_SOURCES = aquaero.c
-aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS)
aquaero_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBAQUAERO5_CFLAGS)
-aquaero_la_LIBADD = $(BUILD_WITH_LIBAQUAERO5_LDFLAGS) -laquaero5
+aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBAQUAERO5_LDFLAGS)
+aquaero_la_LIBADD = -laquaero5
endif
if BUILD_PLUGIN_ASCENT
pkglib_LTLIBRARIES += battery.la
battery_la_SOURCES = battery.c
battery_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-battery_la_LIBADD =
if BUILD_WITH_LIBIOKIT
battery_la_LDFLAGS += -framework IOKit
endif
cgroups_la_LIBADD = libmount.la
endif
+if BUILD_PLUGIN_CHRONY
+pkglib_LTLIBRARIES += chrony.la
+chrony_la_SOURCES = chrony.c
+chrony_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
if BUILD_PLUGIN_CONNTRACK
pkglib_LTLIBRARIES += conntrack.la
conntrack_la_SOURCES = conntrack.c
cpufreq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
+if BUILD_PLUGIN_CPUSLEEP
+pkglib_LTLIBRARIES += cpusleep.la
+cpusleep_la_SOURCES = cpusleep.c
+cpusleep_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
if BUILD_PLUGIN_CSV
pkglib_LTLIBRARIES += csv.la
csv_la_SOURCES = csv.c
if BUILD_PLUGIN_CURL
pkglib_LTLIBRARIES += curl.la
-curl_la_SOURCES = curl.c
+curl_la_SOURCES = curl.c \
+ utils_curl_stats.c utils_curl_stats.h
curl_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-curl_la_CFLAGS = $(AM_CFLAGS)
-curl_la_LIBADD =
-if BUILD_WITH_LIBCURL
-curl_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-curl_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+curl_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
+curl_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
endif
if BUILD_PLUGIN_CURL_JSON
pkglib_LTLIBRARIES += curl_json.la
-curl_json_la_SOURCES = curl_json.c
-curl_json_la_CFLAGS = $(AM_CFLAGS)
-curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+curl_json_la_SOURCES = curl_json.c \
+ utils_curl_stats.c utils_curl_stats.h
+curl_json_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
curl_json_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
-curl_json_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
-if BUILD_WITH_LIBCURL
-curl_json_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-curl_json_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+curl_json_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBYAJL_LIBS)
endif
if BUILD_PLUGIN_CURL_XML
pkglib_LTLIBRARIES += curl_xml.la
-curl_xml_la_SOURCES = curl_xml.c
+curl_xml_la_SOURCES = curl_xml.c \
+ utils_curl_stats.c utils_curl_stats.h
curl_xml_la_LDFLAGS = $(PLUGIN_LDFLAGS)
curl_xml_la_CFLAGS = $(AM_CFLAGS) \
$(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
disk_la_LDFLAGS += $(BUILD_WITH_LIBUDEV_LDFLAGS)
disk_la_LIBADD += $(BUILD_WITH_LIBUDEV_LIBS)
endif
+if BUILD_FREEBSD
+disk_la_LIBADD += -ldevstat -lgeom
+endif
if BUILD_WITH_PERFSTAT
disk_la_LIBADD += -lperfstat
endif
pkglib_LTLIBRARIES += dns.la
dns_la_SOURCES = dns.c utils_dns.c utils_dns.h
dns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-dns_la_LIBADD = -lpcap -lpthread
+dns_la_LIBADD = -lpcap
endif
if BUILD_PLUGIN_DRBD
pkglib_LTLIBRARIES += drbd.la
drbd_la_SOURCES = drbd.c
drbd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-drbd_la_LIBADD = -lpthread
endif
if BUILD_PLUGIN_EMAIL
pkglib_LTLIBRARIES += email.la
email_la_SOURCES = email.c
email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-email_la_LIBADD = -lpthread
endif
if BUILD_PLUGIN_ENTROPY
utils_cmd_putval.c utils_cmd_putval.h \
utils_parse_option.h utils_parse_option.c
exec_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-exec_la_LIBADD = -lpthread
endif
if BUILD_PLUGIN_ETHSTAT
gmond_la_LIBADD = $(GANGLIA_LIBS)
endif
+if BUILD_PLUGIN_GPS
+pkglib_LTLIBRARIES += gps.la
+gps_la_SOURCES = gps.c
+gps_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBGPS_CFLAGS)
+gps_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBGPS_LDFLAGS)
+gps_la_LIBADD = -lpthread $(BUILD_WITH_LIBGPS_LIBS)
+endif
+
+if BUILD_PLUGIN_GRPC
+pkglib_LTLIBRARIES += grpc.la
+grpc_la_SOURCES = grpc.cc
+nodist_grpc_la_SOURCES = collectd.grpc.pb.cc collectd.pb.cc types.pb.cc
+grpc_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBGRPCPP_CPPFLAGS) $(BUILD_WITH_LIBPROTOBUF_CPPFLAGS)
+grpc_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBGRPCPP_LDFLAGS) $(BUILD_WITH_LIBPROTOBUF_LDFLAGS)
+grpc_la_LIBADD = $(BUILD_WITH_LIBGRPCPP_LIBS) $(BUILD_WITH_LIBPROTOBUF_LIBS)
+endif
+
if BUILD_PLUGIN_HDDTEMP
pkglib_LTLIBRARIES += hddtemp.la
hddtemp_la_SOURCES = hddtemp.c
if BUILD_PLUGIN_IPC
pkglib_LTLIBRARIES += ipc.la
ipc_la_SOURCES = ipc.c
-ipc_la_CFLAGS = $(AM_CFLAGS)
ipc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_IPVS
pkglib_LTLIBRARIES += ipvs.la
ipvs_la_SOURCES = ipvs.c
+ipvs_la_CFLAGS = $(AM_CFLAGS)
if IP_VS_H_NEEDS_KERNEL_CFLAGS
-ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
+ipvs_la_CFLAGS += $(KERNEL_CFLAGS)
endif
ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_LOG_LOGSTASH
pkglib_LTLIBRARIES += log_logstash.la
log_logstash_la_SOURCES = log_logstash.c
-log_logstash_la_CFLAGS = $(AM_CFLAGS)
log_logstash_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
log_logstash_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
log_logstash_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
lpar_la_LIBADD = -lperfstat
endif
+if BUILD_PLUGIN_LUA
+pkglib_LTLIBRARIES += lua.la
+lua_la_SOURCES = lua.c \
+ utils_lua.c utils_lua.h
+lua_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLUA_CFLAGS)
+lua_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+lua_la_LIBADD = $(BUILD_WITH_LIBLUA_LIBS)
+endif
+
if BUILD_PLUGIN_LVM
pkglib_LTLIBRARIES += lvm.la
lvm_la_SOURCES = lvm.c
-lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+lvm_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBLVM2APP_CPPFLAGS)
+lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBLVM2APP_LDFLAGS)
lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS)
endif
modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS)
endif
+if BUILD_PLUGIN_MQTT
+pkglib_LTLIBRARIES += mqtt.la
+mqtt_la_SOURCES = mqtt.c
+mqtt_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMOSQUITTO_CPPFLAGS)
+mqtt_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMOSQUITTO_LDFLAGS)
+mqtt_la_LIBADD = $(BUILD_WITH_LIBMOSQUITTO_LIBS)
+endif
+
if BUILD_PLUGIN_MULTIMETER
pkglib_LTLIBRARIES += multimeter.la
multimeter_la_SOURCES = multimeter.c
if BUILD_PLUGIN_MYSQL
pkglib_LTLIBRARIES += mysql.la
mysql_la_SOURCES = mysql.c
+mysql_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMYSQL_CFLAGS)
mysql_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-mysql_la_CFLAGS = $(AM_CFLAGS)
-mysql_la_LIBADD =
-if BUILD_WITH_LIBMYSQL
-mysql_la_CFLAGS += $(BUILD_WITH_LIBMYSQL_CFLAGS)
-mysql_la_LIBADD += $(BUILD_WITH_LIBMYSQL_LIBS)
-endif
+mysql_la_LIBADD = $(BUILD_WITH_LIBMYSQL_LIBS)
endif
if BUILD_PLUGIN_NETAPP
utils_fbhash.c utils_fbhash.h
network_la_CPPFLAGS = $(AM_CPPFLAGS)
network_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-network_la_LIBADD = -lpthread
+network_la_LIBADD =
if BUILD_WITH_LIBSOCKET
network_la_LIBADD += -lsocket
endif
if BUILD_PLUGIN_NGINX
pkglib_LTLIBRARIES += nginx.la
nginx_la_SOURCES = nginx.c
-nginx_la_CFLAGS = $(AM_CFLAGS)
-nginx_la_LIBADD =
+nginx_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
nginx_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-if BUILD_WITH_LIBCURL
-nginx_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-nginx_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+nginx_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
endif
if BUILD_PLUGIN_NOTIFY_DESKTOP
pkglib_LTLIBRARIES += notify_email.la
notify_email_la_SOURCES = notify_email.c
notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-notify_email_la_LIBADD = -lesmtp -lssl -lcrypto -lpthread
+notify_email_la_LIBADD = -lesmtp -lssl -lcrypto
+endif
+
+if BUILD_PLUGIN_NOTIFY_NAGIOS
+pkglib_LTLIBRARIES += notify_nagios.la
+notify_nagios_la_SOURCES = notify_nagios.c
+notify_nagios_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_NTPD
nut_la_SOURCES = nut.c
nut_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
nut_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-nut_la_LIBADD = -lpthread $(BUILD_WITH_LIBUPSCLIENT_LIBS)
+nut_la_LIBADD = $(BUILD_WITH_LIBUPSCLIENT_LIBS)
endif
if BUILD_PLUGIN_OLSRD
if BUILD_PLUGIN_ONEWIRE
pkglib_LTLIBRARIES += onewire.la
onewire_la_SOURCES = onewire.c
-onewire_la_CFLAGS = $(AM_CFLAGS)
onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
-onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOWCAPI_LDFLAGS)
endif
if BUILD_PLUGIN_OPENLDAP
pkglib_LTLIBRARIES += openldap.la
openldap_la_SOURCES = openldap.c
-openldap_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLDAP_LDFLAGS)
-openldap_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBLDAP_LDFLAGS)
openldap_la_LIBADD = -lldap
endif
if BUILD_PLUGIN_OPENVPN
pkglib_LTLIBRARIES += openvpn.la
openvpn_la_SOURCES = openvpn.c
-openvpn_la_CFLAGS = $(AM_CFLAGS)
openvpn_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
pkglib_LTLIBRARIES += oracle.la
oracle_la_SOURCES = oracle.c \
utils_db_query.c utils_db_query.h
-oracle_la_CFLAGS = $(AM_CFLAGS)
-oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CFLAGS)
+oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CPPFLAGS)
oracle_la_LIBADD = $(BUILD_WITH_ORACLE_LIBS)
oracle_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
# 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
+# Despite off_t being 64 bit wide on 64 bit platforms, Perl insist on using
+# off64_t which is only exposed when _LARGEFILE64_SOURCE is defined... *sigh*
+# On older platforms we also need _REENTRANT. _GNU_SOURCE sets both of these.
+perl_la_CPPFLAGS += -D_GNU_SOURCE
perl_la_CFLAGS = $(AM_CFLAGS) \
$(PERL_CFLAGS) \
-DXS_VERSION=\"$(VERSION)\" -DVERSION=\"$(VERSION)\"
pkglib_LTLIBRARIES += pinba.la
pinba_la_SOURCES = pinba.c
nodist_pinba_la_SOURCES = pinba.pb-c.c pinba.pb-c.h
-pinba_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-pinba_la_LIBADD = -lprotobuf-c
+pinba_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBPROTOBUF_C_CPPFLAGS)
+pinba_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBPROTOBUF_C_LDFLAGS)
+pinba_la_LIBADD = $(BUILD_WITH_LIBPROTOBUF_C_LIBS)
endif
if BUILD_PLUGIN_PING
if BUILD_PLUGIN_PYTHON
pkglib_LTLIBRARIES += python.la
python_la_SOURCES = python.c pyconfig.c pyvalues.c cpython.h
-python_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_PYTHON_CPPFLAGS)
-python_la_CFLAGS = $(AM_CFLAGS)
+python_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBPYTHON_CPPFLAGS)
if COMPILER_IS_GCC
-python_la_CFLAGS += -fno-strict-aliasing -Wno-strict-aliasing
+python_la_CPPFLAGS += -fno-strict-aliasing -Wno-strict-aliasing
endif
-python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_PYTHON_LDFLAGS)
-python_la_LIBADD = $(BUILD_WITH_PYTHON_LIBS)
+python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBPYTHON_LDFLAGS)
endif
if BUILD_PLUGIN_PROCESSES
if BUILD_PLUGIN_SIGROK
pkglib_LTLIBRARIES += sigrok.la
sigrok_la_SOURCES = sigrok.c
-sigrok_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSIGROK_CFLAGS)
-sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSIGROK_LDFLAGS)
-sigrok_la_LIBADD = -lsigrok
+sigrok_la_CFLAGS = $(AM_CFLAGS) $(LIBSIGROK_CFLAGS)
+sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+sigrok_la_LIBADD = $(LIBSIGROK_LIBS)
endif
if BUILD_PLUGIN_SMART
if BUILD_PLUGIN_SNMP
pkglib_LTLIBRARIES += snmp.la
snmp_la_SOURCES = snmp.c
-snmp_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-snmp_la_CFLAGS = $(AM_CFLAGS)
-snmp_la_LIBADD =
-if BUILD_WITH_LIBNETSNMP
-snmp_la_CFLAGS += $(BUILD_WITH_LIBSNMP_CFLAGS)
-snmp_la_LIBADD += $(BUILD_WITH_LIBSNMP_LIBS)
-endif
-if BUILD_WITH_LIBPTHREAD
-snmp_la_LIBADD += -lpthread
-endif
+snmp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBNETSNMP_CPPFLAGS)
+snmp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBNETSNMP_LDFLAGS)
+snmp_la_LIBADD = $(BUILD_WITH_LIBNETSNMP_LIBS)
endif
if BUILD_PLUGIN_STATSD
pkglib_LTLIBRARIES += statsd.la
-statsd_la_SOURCES = statsd.c \
- utils_latency.h utils_latency.c
+statsd_la_SOURCES = statsd.c
statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-statsd_la_LIBADD = -lpthread -lm
+statsd_la_LIBADD = liblatency.la -lm
endif
if BUILD_PLUGIN_SWAP
utils_cmd_putnotif.h utils_cmd_putnotif.c \
utils_parse_option.h utils_parse_option.c
unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-unixsock_la_LIBADD = -lpthread
endif
if BUILD_PLUGIN_UPTIME
if BUILD_PLUGIN_WRITE_GRAPHITE
pkglib_LTLIBRARIES += write_graphite.la
write_graphite_la_SOURCES = write_graphite.c \
- utils_format_graphite.c utils_format_graphite.h \
- utils_format_json.c utils_format_json.h
+ utils_format_graphite.c utils_format_graphite.h
write_graphite_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_WRITE_HTTP
pkglib_LTLIBRARIES += write_http.la
write_http_la_SOURCES = write_http.c \
- utils_format_json.c utils_format_json.h
+ utils_format_kairosdb.c utils_format_kairosdb.h
write_http_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-write_http_la_CFLAGS = $(AM_CFLAGS)
-write_http_la_LIBADD =
-if BUILD_WITH_LIBCURL
-write_http_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-write_http_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+write_http_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
+write_http_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) libformat_json.la
endif
if BUILD_PLUGIN_WRITE_KAFKA
pkglib_LTLIBRARIES += write_kafka.la
write_kafka_la_SOURCES = write_kafka.c \
utils_format_graphite.c utils_format_graphite.h \
- utils_format_json.c utils_format_json.h \
utils_cmd_putval.c utils_cmd_putval.h \
utils_crc32.c utils_crc32.h
write_kafka_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRDKAFKA_CPPFLAGS)
write_kafka_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRDKAFKA_LDFLAGS)
-write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS)
+write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS) libformat_json.la
endif
if BUILD_PLUGIN_WRITE_LOG
pkglib_LTLIBRARIES += write_redis.la
write_redis_la_SOURCES = write_redis.c
write_redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
-write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+write_redis_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
write_redis_la_LIBADD = -lhiredis
endif
if BUILD_PLUGIN_WRITE_RIEMANN
pkglib_LTLIBRARIES += write_riemann.la
write_riemann_la_SOURCES = write_riemann.c write_riemann_threshold.c write_riemann_threshold.h
-nodist_write_riemann_la_SOURCES = riemann.pb-c.c riemann.pb-c.h
-write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-write_riemann_la_LIBADD = -lprotobuf-c
+write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBRIEMANN_CLIENT_LIBS)
+write_riemann_la_CFLAGS = $(AM_CFLAGS) $(LIBRIEMANN_CLIENT_CFLAGS)
endif
if BUILD_PLUGIN_WRITE_SENSU
write_tsdb_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
+if BUILD_PLUGIN_XENCPU
+pkglib_LTLIBRARIES += xencpu.la
+xencpu_la_SOURCES = xencpu.c
+xencpu_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBXENCTL_CPPFLAGS)
+xencpu_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBXENCTL_LDFLAGS)
+xencpu_la_LIBADD = -lxenctrl
+endif
+
if BUILD_PLUGIN_XMMS
pkglib_LTLIBRARIES += xmms.la
xmms_la_SOURCES = xmms.c
if BUILD_PLUGIN_ZFS_ARC
pkglib_LTLIBRARIES += zfs_arc.la
zfs_arc_la_SOURCES = zfs_arc.c
-zfs_arc_la_CFLAGS = $(AM_CFLAGS)
zfs_arc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
if BUILD_FREEBSD
zfs_arc_la_LIBADD = -lm
-else
-if BUILD_LINUX
-# zfs_arc requires no library on linux
-else
-# solaris
-zfs_arc_la_LIBADD = -lkstat
endif
+if BUILD_SOLARIS
+zfs_arc_la_LIBADD = -lkstat
endif
endif
BUILT_SOURCES += $(dist_man_MANS)
+if BUILD_PLUGIN_ZONE
+pkglib_LTLIBRARIES += zone.la
+zone_la_SOURCES = zone.c
+zone_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
dist_man_MANS = collectd.1 \
collectd.conf.5 \
collectd-email.5 \
collectd-exec.5 \
collectdctl.1 \
collectd-java.5 \
+ collectd-lua.5 \
collectdmon.1 \
collectd-nagios.1 \
collectd-perl.5 \
collectd-unixsock.5 \
types.db.5
-#collectd_1_SOURCES = collectd.pod
-
-EXTRA_DIST = types.db
-
-EXTRA_DIST += collectd.conf.pod \
+EXTRA_DIST = collectd.conf.pod \
collectd-email.pod \
collectd-exec.pod \
collectdctl.pod \
collectd-java.pod \
+ collectd-lua.pod \
collectdmon.pod \
collectd-nagios.pod \
collectd-perl.pod \
collectd-threshold.pod \
collectd-unixsock.pod \
postgresql_default.conf \
- types.db.pod
+ types.db \
+ types.db.pod \
+ valgrind.FreeBSD.suppress
+
+AM_V_POD2MAN_C = $(am__v_POD2MAN_C_@AM_V@)
+am__v_POD2MAN_C_ = $(am__v_POD2MAN_C_@AM_DEFAULT_V@)
+am__v_POD2MAN_C_0 = @echo " POD2MAN " $@;
+am__v_POD2MAN_C_1 =
.pod.1:
- pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
+ $(AM_V_POD2MAN_C)pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
>.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
@if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
then \
fi
.pod.5:
- pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< \
+ $(AM_V_POD2MAN_C)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 \
AM_V_PROTOC_C = $(am__v_PROTOC_C_@AM_V@)
am__v_PROTOC_C_ = $(am__v_PROTOC_C_@AM_DEFAULT_V@)
-am__v_PROTOC_C_0 = @echo " PROTOC-C " $@;
+am__v_PROTOC_C_0 = @echo " PROTOC-C" $@;
am__v_PROTOC_C_1 =
# Protocol buffer for the "pinba" plugin.
BUILT_SOURCES += pinba.pb-c.c pinba.pb-c.h
pinba.pb-c.c pinba.pb-c.h: pinba.proto
- $(AM_V_PROTOC_C)protoc-c -I$(srcdir) --c_out . $(srcdir)/pinba.proto
-endif
-
-# Protocol buffer for the "write_riemann" plugin.
-EXTRA_DIST += riemann.proto
-if BUILD_PLUGIN_WRITE_RIEMANN
-CLEANFILES += riemann.pb-c.c riemann.pb-c.h
-
-BUILT_SOURCES += riemann.pb-c.c riemann.pb-c.h
-
-riemann.pb-c.c riemann.pb-c.h: riemann.proto
- $(AM_V_PROTOC_C)protoc-c -I$(srcdir) --c_out . $(srcdir)/riemann.proto
+ $(AM_V_PROTOC_C)$(PROTOC_C) -I$(srcdir) --c_out . $(srcdir)/pinba.proto
endif
install-exec-hook:
rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
-check_PROGRAMS = test_utils_mount test_utils_vl_lookup
-
-test_utils_mount_SOURCES = utils_mount_test.c testing.h
-test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
-if BUILD_WITH_LIBKSTAT
-test_utils_mount_LDADD += -lkstat
-endif
-
-test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
-test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
-if BUILD_WITH_LIBKSTAT
-test_utils_vl_lookup_LDADD += -lkstat
-endif
-
-TESTS = test_utils_mount test_utils_vl_lookup
-
if BUILD_PLUGIN_CEPH
test_plugin_ceph_SOURCES = ceph_test.c
test_plugin_ceph_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
test_plugin_ceph_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
-test_plugin_ceph_LDADD = daemon/libcommon.la daemon/libplugin_mock.la $(BUILD_WITH_LIBYAJL_LIBS)
+test_plugin_ceph_LDADD = daemon/libplugin_mock.la $(BUILD_WITH_LIBYAJL_LIBS)
check_PROGRAMS += test_plugin_ceph
TESTS += test_plugin_ceph
endif
diff --git a/src/aggregation.c b/src/aggregation.c
index 56e4955c247d3a4d8252d44e21b2f58d3e2be7bc..2744c89ecb8a9caff99bc543555dd72660a2719d 100644 (file)
--- a/src/aggregation.c
+++ b/src/aggregation.c
#include "collectd.h"
-#include <pthread.h>
-
#include "plugin.h"
#include "common.h"
-#include "configfile.h"
#include "meta_data.h"
#include "utils_cache.h" /* for uc_get_rate() */
#include "utils_subst.h"
DEBUG ("aggregation plugin: Creating new instance.");
- inst = malloc (sizeof (*inst));
+ inst = calloc (1, sizeof (*inst));
if (inst == NULL)
{
- ERROR ("aggregation plugin: malloc() failed.");
+ ERROR ("aggregation plugin: calloc() failed.");
return (NULL);
}
- memset (inst, 0, sizeof (*inst));
pthread_mutex_init (&inst->lock, /* attr = */ NULL);
inst->ds_type = ds->ds[0].type;
#define INIT_STATE(field) do { \
inst->state_ ## field = NULL; \
if (agg->calc_ ## field) { \
- inst->state_ ## field = malloc (sizeof (*inst->state_ ## field)); \
+ inst->state_ ## field = calloc (1, sizeof (*inst->state_ ## field)); \
if (inst->state_ ## field == NULL) { \
agg_instance_destroy (inst); \
free (inst); \
- ERROR ("aggregation plugin: malloc() failed."); \
+ ERROR ("aggregation plugin: calloc() failed."); \
return (NULL); \
} \
- memset (inst->state_ ## field, 0, sizeof (*inst->state_ ## field)); \
} \
} while (0)
else
sstrncpy (vl->plugin_instance, func, sizeof (vl->plugin_instance));
- memset (&v, 0, sizeof (v));
status = rate_to_value (&v, rate, state, inst->ds_type, t);
if (status != 0)
{
static int agg_config_handle_group_by (oconfig_item_t const *ci, /* {{{ */
aggregation_t *agg)
{
- int i;
-
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
char const *value;
aggregation_t *agg;
_Bool is_valid;
int status;
- int i;
- agg = malloc (sizeof (*agg));
+ agg = calloc (1, sizeof (*agg));
if (agg == NULL)
{
- ERROR ("aggregation plugin: malloc failed.");
+ ERROR ("aggregation plugin: calloc failed.");
return (-1);
}
- memset (agg, 0, sizeof (*agg));
sstrncpy (agg->ident.host, "/.*/", sizeof (agg->ident.host));
sstrncpy (agg->ident.plugin, "/.*/", sizeof (agg->ident.plugin));
sstrncpy (agg->ident.type_instance, "/.*/",
sizeof (agg->ident.type_instance));
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static int agg_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
pthread_mutex_lock (&agg_instance_list_lock);
if (lookup == NULL)
}
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static int agg_read (void) /* {{{ */
{
- agg_instance_t *this;
cdtime_t t;
int success;
return (0);
}
- for (this = agg_instance_list_head; this != NULL; this = this->next)
+ for (agg_instance_t *this = agg_instance_list_head; this != NULL; this = this->next)
{
int status;
diff --git a/src/amqp.c b/src/amqp.c
index 4206bdc1e3ee36b99192452b377943e007fb8af8..89f051e81960668c957abfe72239c542ed4681d2 100644 (file)
--- a/src/amqp.c
+++ b/src/amqp.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_cmd_putval.h"
#include "utils_format_json.h"
#include "utils_format_graphite.h"
-#include <pthread.h>
-
#include <amqp.h>
#include <amqp_framing.h>
static int camqp_shutdown (void) /* {{{ */
{
- size_t i;
-
DEBUG ("amqp plugin: Shutting down %zu subscriber threads.",
subscriber_threads_num);
subscriber_threads_running = 0;
- for (i = 0; i < subscriber_threads_num; i++)
+ for (size_t i = 0; i < subscriber_threads_num; i++)
{
/* FIXME: Sending a signal is not very elegant here. Maybe find out how
* to use a timeout in the thread and check for the variable in regular
if (tmp == NULL)
{
ERROR ("amqp plugin: realloc failed.");
- camqp_config_free (conf);
+ sfree (subscriber_threads);
return (ENOMEM);
}
subscriber_threads = tmp;
char errbuf[1024];
ERROR ("amqp plugin: pthread_create failed: %s",
sstrerror (status, errbuf, sizeof (errbuf)));
- camqp_config_free (conf);
return (status);
}
static int camqp_write_locked (camqp_config_t *conf, /* {{{ */
const char *buffer, const char *routing_key)
{
- amqp_basic_properties_t props;
int status;
status = camqp_connect (conf);
if (status != 0)
return (status);
- memset (&props, 0, sizeof (props));
- props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG
- | AMQP_BASIC_DELIVERY_MODE_FLAG
- | AMQP_BASIC_APP_ID_FLAG;
+ amqp_basic_properties_t props = {
+ ._flags = AMQP_BASIC_CONTENT_TYPE_FLAG
+ | AMQP_BASIC_DELIVERY_MODE_FLAG
+ | AMQP_BASIC_APP_ID_FLAG,
+ .delivery_mode = conf->delivery_mode,
+ .app_id = amqp_cstring_bytes("collectd")
+ };
+
if (conf->format == CAMQP_FORMAT_COMMAND)
props.content_type = amqp_cstring_bytes("text/collectd");
else if (conf->format == CAMQP_FORMAT_JSON)
props.content_type = amqp_cstring_bytes("text/graphite");
else
assert (23 == 42);
- props.delivery_mode = conf->delivery_mode;
- props.app_id = amqp_cstring_bytes("collectd");
status = amqp_basic_publish(conf->connection,
/* channel = */ 1,
@@ -817,15 +814,12 @@ static int camqp_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
if ((ds == NULL) || (vl == NULL) || (conf == NULL))
return (EINVAL);
- memset (buffer, 0, sizeof (buffer));
-
if (conf->routing_key != NULL)
{
sstrncpy (routing_key, conf->routing_key, sizeof (routing_key));
}
else
{
- size_t i;
ssnprintf (routing_key, sizeof (routing_key), "collectd/%s/%s/%s/%s/%s",
vl->host,
vl->plugin, vl->plugin_instance,
/* Switch slashes (the only character forbidden by collectd) and dots
* (the separation character used by AMQP). */
- for (i = 0; routing_key[i] != 0; i++)
+ for (size_t i = 0; routing_key[i] != 0; i++)
{
if (routing_key[i] == '.')
routing_key[i] = '/';
{
camqp_config_t *conf;
int status;
- int i;
- conf = malloc (sizeof (*conf));
+ conf = calloc (1, sizeof (*conf));
if (conf == NULL)
{
- ERROR ("amqp plugin: malloc failed.");
+ ERROR ("amqp plugin: calloc failed.");
return (ENOMEM);
}
/* Initialize "conf" {{{ */
- memset (conf, 0, sizeof (*conf));
conf->publish = publish;
conf->name = NULL;
conf->format = CAMQP_FORMAT_COMMAND;
return (status);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static int camqp_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/apache.c b/src/apache.c
index 5b6914c4d2e0fc040fe83f78f3cdf6a5f62b6c37..b57d08edc447c9005d32fded65b85d00d425b111 100644 (file)
--- a/src/apache.c
+++ b/src/apache.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include <curl/curl.h>
/* TODO: Remove this prototype */
static int apache_read_host (user_data_t *user_data);
-static void apache_free (apache_t *st)
+static void apache_free (void *arg)
{
+ apache_t *st = arg;
+
if (st == NULL)
return;
return (0);
}
- if (len <= 0)
+ if (len == 0)
return (len);
if ((st->apache_buffer_fill + len) >= st->apache_buffer_size)
{
char *temp;
- temp = (char *) realloc (st->apache_buffer,
+ temp = realloc (st->apache_buffer,
st->apache_buffer_fill + len + 1);
if (temp == NULL)
{
return (0);
}
- if (len <= 0)
+ if (len == 0)
return (len);
/* look for the Server header */
static int config_add (oconfig_item_t *ci)
{
apache_t *st;
- int i;
int status;
- st = malloc (sizeof (*st));
+ st = calloc (1, sizeof (*st));
if (st == NULL)
{
- ERROR ("apache plugin: malloc failed.");
+ ERROR ("apache plugin: calloc failed.");
return (-1);
}
- memset (st, 0, sizeof (*st));
st->timeout = -1;
}
assert (st->name != NULL);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (status == 0)
{
- user_data_t ud;
- char callback_name[3*DATA_MAX_NAME_LEN];
+ user_data_t ud = {
+ .data = st,
+ .free_func = apache_free
+ };
- memset (&ud, 0, sizeof (ud));
- ud.data = st;
- ud.free_func = (void *) apache_free;
+ char callback_name[3*DATA_MAX_NAME_LEN];
- memset (callback_name, 0, sizeof (callback_name));
ssnprintf (callback_name, sizeof (callback_name),
"apache/%s/%s",
(st->host != NULL) ? st->host : hostname_g,
status = plugin_register_complex_read (/* group = */ NULL,
/* name = */ callback_name,
/* callback = */ apache_read_host,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
}
static int config (oconfig_item_t *ci)
{
int status = 0;
- int i;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (st->timeout >= 0)
curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) st->timeout);
else
- curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
long long response_start = 0LL;
long long response_end = 0LL;
- int i;
- for (i = 0; buf[i] != '\0'; i++)
+ for (int i = 0; buf[i] != '\0'; i++)
{
if (buf[i] == '.') open++;
else if (buf[i] == '_') waiting++;
diff --git a/src/apcups.c b/src/apcups.c
index eb1f0622989b9793acc66cde043cb43e484808b3..70e7fcea86f100d28639450bf62f483a5d9abace 100644 (file)
--- a/src/apcups.c
+++ b/src/apcups.c
/*
* collectd - src/apcups.c
- * Copyright (C) 2006-2012 Florian octo Forster
+ * Copyright (C) 2006-2015 Florian octo Forster
* Copyright (C) 2006 Anthony Gialluca <tonyabg at charter.net>
* Copyright (C) 2000-2004 Kern Sibbald
* Copyright (C) 1996-1999 Andre M. Hedrick <andre at suse.com>
**/
#include "collectd.h"
+
#include "common.h" /* rrd_update_file */
#include "plugin.h" /* plugin_register, plugin_submit */
-#include "configfile.h" /* cf_register */
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
# include <netinet/in.h>
#endif
-#define NISPORT 3551
-#define MAXSTRING 256
-#define MODULE_NAME "apcups"
+#ifndef APCUPS_SERVER_TIMEOUT
+# define APCUPS_SERVER_TIMEOUT 15.0
+#endif
-#define APCUPS_DEFAULT_HOST "localhost"
+#ifndef APCUPS_DEFAULT_NODE
+# define APCUPS_DEFAULT_NODE "localhost"
+#endif
+
+#ifndef APCUPS_DEFAULT_SERVICE
+# define APCUPS_DEFAULT_SERVICE "3551"
+#endif
/*
* Private data types
* Private variables
*/
/* Default values for contacting daemon */
-static char *conf_host = NULL;
-static int conf_port = NISPORT;
+static char *conf_node = NULL;
+static char *conf_service = NULL;
/* Defaults to false for backwards compatibility. */
static _Bool conf_report_seconds = 0;
+static _Bool conf_persistent_conn = 1;
static int global_sockfd = -1;
static int count_retries = 0;
static int count_iterations = 0;
-static _Bool close_socket = 0;
-
-static const char *config_keys[] =
-{
- "Host",
- "Port",
- "ReportSeconds"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static int net_shutdown (int *fd)
{
if ((fd == NULL) || (*fd < 0))
return (EINVAL);
- swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+ (void)swrite (*fd, (void *) &packet_size, sizeof (packet_size));
close (*fd);
*fd = -1;
* Returns -1 on error
* Returns socket file descriptor otherwise
*/
-static int net_open (char *host, int port)
+static int net_open (char const *node, char const *service)
{
int sd;
int status;
- char port_str[8];
- struct addrinfo ai_hints;
struct addrinfo *ai_return;
struct addrinfo *ai_list;
- assert ((port > 0x00000000) && (port <= 0x0000FFFF));
-
- /* Convert the port to a string */
- ssnprintf (port_str, sizeof (port_str), "%i", port);
-
- /* Resolve name */
- memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
- ai_hints.ai_family = AF_INET; /* XXX: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
- ai_hints.ai_socktype = SOCK_STREAM;
+ /* TODO: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
+ struct addrinfo ai_hints = {
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_STREAM
+ };
- status = getaddrinfo (host, port_str, &ai_hints, &ai_return);
+ status = getaddrinfo (node, service, &ai_hints, &ai_return);
if (status != 0)
{
char errbuf[1024];
DEBUG ("apcups plugin: Done opening a socket %i", sd);
return (sd);
-} /* int net_open (char *host, char *service, int port) */
+} /* int net_open */
/*
* Receive a message from the other end. Each message consists of
* Returns zero on success
* Returns non-zero on error
*/
-static int net_send (int *sockfd, char *buff, int len)
+static int net_send (int *sockfd, const char *buff, int len)
{
uint16_t packet_size;
}
/* Get and print status from apcupsd NIS server */
-static int apc_query_server (char *host, int port,
+static int apc_query_server (char const *node, char const *service,
apc_detail_t *apcups_detail)
{
int n;
{
if (global_sockfd < 0)
{
- global_sockfd = net_open (host, port);
+ global_sockfd = net_open (node, service);
if (global_sockfd < 0)
{
ERROR ("apcups plugin: Connecting to the "
"first %i iterations. Will close the socket "
"in future iterations.",
count_retries, count_iterations);
- close_socket = 1;
+ conf_persistent_conn = 0;
}
while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
{
- assert ((unsigned int)n < sizeof (recvline));
- recvline[n] = '\0';
+ assert ((size_t)n < sizeof (recvline));
+ recvline[n] = 0;
#if APCMAIN
printf ("net_recv = `%s';\n", recvline);
#endif /* if APCMAIN */
}
status = errno; /* save errno, net_shutdown() may re-set it. */
- if (close_socket)
+ if (!conf_persistent_conn)
net_shutdown (&global_sockfd);
if (n < 0)
return (0);
}
-static int apcups_config (const char *key, const char *value)
+static int apcups_config (oconfig_item_t *ci)
{
- if (strcasecmp (key, "host") == 0)
- {
- if (conf_host != NULL)
- {
- free (conf_host);
- conf_host = NULL;
- }
- if ((conf_host = strdup (value)) == NULL)
- return (1);
- }
- else if (strcasecmp (key, "Port") == 0)
+ _Bool persistent_conn_set = 0;
+
+ for (int i = 0; i < ci->children_num; i++)
{
- int port_tmp = atoi (value);
- if (port_tmp < 1 || port_tmp > 65535)
- {
- WARNING ("apcups plugin: Invalid port: %i", port_tmp);
- return (1);
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp (child->key, "Host") == 0)
+ cf_util_get_string (child, &conf_node);
+ else if (strcasecmp (child->key, "Port") == 0)
+ cf_util_get_service (child, &conf_service);
+ else if (strcasecmp (child->key, "ReportSeconds") == 0)
+ cf_util_get_boolean (child, &conf_report_seconds);
+ else if (strcasecmp (child->key, "PersistentConnection") == 0) {
+ cf_util_get_boolean (child, &conf_persistent_conn);
+ persistent_conn_set = 1;
}
- conf_port = port_tmp;
- }
- else if (strcasecmp (key, "ReportSeconds") == 0)
- {
- if (IS_TRUE (value))
- conf_report_seconds = 1;
else
- conf_report_seconds = 0;
+ ERROR ("apcups plugin: Unknown config option \"%s\".", child->key);
}
- else
- {
- return (-1);
+
+ if (!persistent_conn_set) {
+ double interval = CDTIME_T_TO_DOUBLE(plugin_get_interval());
+ if (interval > APCUPS_SERVER_TIMEOUT) {
+ NOTICE ("apcups plugin: Plugin poll interval set to %.3f seconds. "
+ "Apcupsd NIS socket timeout is %.3f seconds, "
+ "PersistentConnection disabled by default.",
+ interval, APCUPS_SERVER_TIMEOUT);
+ conf_persistent_conn = 0;
+ }
}
+
return (0);
-}
+} /* int apcups_config */
-static void apc_submit_generic (char *type, char *type_inst, gauge_t value)
+static void apc_submit_generic (const char *type, const char *type_inst, gauge_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
.linefreq = NAN,
};
- int status = apc_query_server (conf_host == NULL
- ? APCUPS_DEFAULT_HOST
- : conf_host,
- conf_port, &apcups_detail);
+ int status = apc_query_server (conf_node == NULL
+ ? APCUPS_DEFAULT_NODE
+ : conf_node,
+ conf_service, &apcups_detail);
if (status != 0)
{
- DEBUG ("apcups plugin: apc_query_server (%s, %i) = %i",
- conf_host == NULL ? APCUPS_DEFAULT_HOST : conf_host,
- conf_port, status);
+ DEBUG ("apcups plugin: apc_query_server (\"%s\", \"%s\") = %d",
+ conf_node == NULL ? APCUPS_DEFAULT_NODE : conf_node,
+ conf_service, status);
return (status);
}
void module_register (void)
{
- plugin_register_config ("apcups", apcups_config, config_keys,
- config_keys_num);
+ plugin_register_complex_config ("apcups", apcups_config);
plugin_register_read ("apcups", apcups_read);
plugin_register_shutdown ("apcups", apcups_shutdown);
} /* void module_register */
diff --git a/src/apple_sensors.c b/src/apple_sensors.c
index 19d5a49f31731ead712a4d78409bdd87b492007e..48fbcb91e53117832fc26160df4f8ecd4fa96947 100644 (file)
--- a/src/apple_sensors.c
+++ b/src/apple_sensors.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
static int as_init (void)
{
kern_return_t status;
-
+
if (io_master_port != MACH_PORT_NULL)
{
mach_port_deallocate (mach_task_self (),
char inst[128];
int value_int;
double value_double;
- int i;
-
if (!io_master_port || (io_master_port == MACH_PORT_NULL))
return (-1);
kCFStringEncodingASCII))
continue;
inst[sizeof (inst) - 1] = '\0';
- for (i = 0; i < 128; i++)
+ for (int i = 0; i < 128; i++)
{
if (inst[i] == '\0')
break;
diff --git a/src/aquaero.c b/src/aquaero.c
index 5db988e60663f56c39c796596176ff587088c046..81a4efd4337257865dd78d293d065572c3aa7b7e 100644 (file)
--- a/src/aquaero.c
+++ b/src/aquaero.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
static int aquaero_config (oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
const char *type_instance_prefix, double *value_array, int len)
{
char type_instance[DATA_MAX_NAME_LEN];
- int i;
- for (i = 0; i < len; i++)
+ for (int i = 0; i < len; i++)
{
if (value_array[i] == AQ5_FLOAT_UNDEF)
continue;
aq5_settings_t aq_sett;
char *err_msg = NULL;
char type_instance[DATA_MAX_NAME_LEN];
- int i;
if (libaquaero5_poll(conf_device, &aq_data, &err_msg) < 0)
{
AQ5_NUM_OTHER_SENSORS);
/* Fans */
- for (i = 0; i < AQ5_NUM_FAN; i++)
+ for (int i = 0; i < AQ5_NUM_FAN; i++)
{
if ((aq_sett.fan_data_source[i] == NONE)
|| (aq_data.fan_vrm_temp[i] != AQ5_FLOAT_UNDEF))
diff --git a/src/ascent.c b/src/ascent.c
index 11175af5e6104afa7b39291fd77fd45441a0cb64..11bb97f0c6bce3b3abe457090053173d91a01737 100644 (file)
--- a/src/ascent.c
+++ b/src/ascent.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include <curl/curl.h>
#include <libxml/parser.h>
-static char *races_list[] = /* {{{ */
+static const char *races_list[] = /* {{{ */
{
NULL,
"Human", /* 1 */
}; /* }}} */
#define RACES_LIST_LENGTH STATIC_ARRAY_SIZE (races_list)
-static char *classes_list[] = /* {{{ */
+static const char *classes_list[] = /* {{{ */
{
NULL,
"Warrior", /* 1 */
}; /* }}} */
#define CLASSES_LIST_LENGTH STATIC_ARRAY_SIZE (classes_list)
-static char *genders_list[] = /* {{{ */
+static const char *genders_list[] = /* {{{ */
{
"Male",
"Female"
@@ -154,14 +154,14 @@ static size_t ascent_curl_callback (void *buf, size_t size, size_t nmemb, /* {{{
{
size_t len = size * nmemb;
- if (len <= 0)
+ if (len == 0)
return (len);
if ((ascent_buffer_fill + len) >= ascent_buffer_size)
{
char *temp;
- temp = (char *) realloc (ascent_buffer,
+ temp = realloc (ascent_buffer,
ascent_buffer_fill + len + 1);
if (temp == NULL)
{
@@ -181,20 +181,19 @@ static size_t ascent_curl_callback (void *buf, size_t size, size_t nmemb, /* {{{
static int ascent_submit_players (player_stats_t *ps) /* {{{ */
{
- size_t i;
gauge_t value;
- for (i = 0; i < RACES_LIST_LENGTH; i++)
+ for (size_t i = 0; i < RACES_LIST_LENGTH; i++)
if (races_list[i] != NULL)
ascent_submit_gauge ("by-race", "players", races_list[i],
(gauge_t) ps->races[i]);
- for (i = 0; i < CLASSES_LIST_LENGTH; i++)
+ for (size_t i = 0; i < CLASSES_LIST_LENGTH; i++)
if (classes_list[i] != NULL)
ascent_submit_gauge ("by-class", "players", classes_list[i],
(gauge_t) ps->classes[i]);
- for (i = 0; i < GENDERS_LIST_LENGTH; i++)
+ for (size_t i = 0; i < GENDERS_LIST_LENGTH; i++)
if (genders_list[i] != NULL)
ascent_submit_gauge ("by-gender", "players", genders_list[i],
(gauge_t) ps->genders[i]);
static int ascent_xml_sessions_plr (xmlDoc *doc, xmlNode *node, /* {{{ */
player_info_t *pi)
{
- xmlNode *child;
-
- for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+ for (xmlNode *child = node->xmlChildrenNode; child != NULL; child = child->next)
{
if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
|| (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
static int ascent_xml_sessions (xmlDoc *doc, xmlNode *node) /* {{{ */
{
- xmlNode *child;
- player_stats_t ps;
+ player_stats_t ps = {
+ .level_sum = 0
+ };
- memset (&ps, 0, sizeof (ps));
-
- for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+ for (xmlNode *child = node->xmlChildrenNode; child != NULL; child = child->next)
{
if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
|| (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
static int ascent_xml_status (xmlDoc *doc, xmlNode *node) /* {{{ */
{
- xmlNode *child;
-
- for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+ for (xmlNode *child = node->xmlChildrenNode; child != NULL; child = child->next)
{
if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
|| (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
{
xmlDoc *doc;
xmlNode *cur;
- xmlNode *child;
#if 0
doc = xmlParseMemory (data, strlen (data),
return (-1);
}
- for (child = cur->xmlChildrenNode; child != NULL; child = child->next)
+ for (xmlNode *child = cur->xmlChildrenNode; child != NULL; child = child->next)
{
if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
|| (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
if (timeout != NULL)
curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, atol(timeout));
else
- curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
diff --git a/src/barometer.c b/src/barometer.c
index aaedd70afd075a51293b354c7a792a5f3e81d7ec..998932daa826c308f95ce50fcb8c6958820ac527 100644 (file)
--- a/src/barometer.c
+++ b/src/barometer.c
**/
#include "collectd.h"
+
#include "common.h"
#include "utils_cache.h"
#include "plugin.h"
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <math.h>
+#include <sys/ioctl.h>
/* ------------ MPL115 defines ------------ */
/* I2C address of the MPL115 sensor */
*/
static int temp_list_add(temperature_list_t * list, const char * sensor)
{
- temperature_list_t * new_temp;
+ temperature_list_t *new_temp;
- new_temp = (temperature_list_t *) malloc(sizeof(*new_temp));
+ new_temp = malloc(sizeof (*new_temp));
if(new_temp == NULL)
return -1;
gauge_t * values = NULL; /**< rate values */
size_t values_num = 0; /**< number of rate values */
- int i;
gauge_t values_history[REF_TEMP_AVG_NUM];
list->initialized = 1;
list->num_values = values_num;
- for(i=0; i<values_num; ++i)
+ for(size_t i=0; i<values_num; ++i)
{
- DEBUG ("barometer: get_reference_temperature - rate %d: %lf **",
- i,
- values[i]);
+ DEBUG ("barometer: get_reference_temperature - rate %zu: %lf **",
+ i, values[i]);
if(!isnan(values[i]))
{
avg_sum += values[i];
continue;
}
- for(i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
+ for(size_t i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
{
- DEBUG ("barometer: get_reference_temperature - history %d: %lf",
- i,
- values_history[i]);
+ DEBUG ("barometer: get_reference_temperature - history %zu: %lf",
+ i, values_history[i]);
if(!isnan(values_history[i]))
{
avg_sum += values_history[i];
continue;
}
- for(i=0; i<values_num; ++i)
+ for(size_t i=0; i<values_num; ++i)
{
- DEBUG ("barometer: get_reference_temperature - rate last %d: %lf **",
- i,
- values[i]);
+ DEBUG ("barometer: get_reference_temperature - rate last %zu: %lf **",
+ i, values[i]);
if(!isnan(values[i]))
{
avg_sum += values[i];
already available. */
if(!avg_initialized)
{
- int i;
- for(i=0; i<config_oversample-1; ++i)
+ for(int i=0; i<config_oversample-1; ++i)
{
result = MPL115_read_averaged(&pressure, &temperature);
if(result)
diff --git a/src/battery.c b/src/battery.c
index c501a301d143a48920f32a55317701b0d769a381..0327d5d3f8b100575642e62e00dfeed92d4aa602 100644 (file)
--- a/src/battery.c
+++ b/src/battery.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "utils_complain.h"
-
#if HAVE_MACH_MACH_TYPES_H
# include <mach/mach_types.h>
#endif
} /* }}} void submit_capacity */
#if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
-static double dict_get_double (CFDictionaryRef dict, char *key_string) /* {{{ */
+static double dict_get_double (CFDictionaryRef dict, const char *key_string) /* {{{ */
{
double val_double;
long long val_int;
CFTypeRef ps_obj;
double temp_double;
- int i;
ps_raw = IOPSCopyPowerSourcesInfo ();
ps_array = IOPSCopyPowerSourcesList (ps_raw);
DEBUG ("ps_array_len == %i", ps_array_len);
- for (i = 0; i < ps_array_len; i++)
+ for (int i = 0; i < ps_array_len; i++)
{
ps_obj = CFArrayGetValueAtIndex (ps_array, i);
ps_dict = IOPSGetPowerSourceDescription (ps_raw, ps_obj);
CFDictionaryRef bat_root_dict;
CFArrayRef bat_info_arry;
CFIndex bat_info_arry_len;
- CFIndex bat_info_arry_pos;
CFDictionaryRef bat_info_dict;
double temp_double;
}
bat_info_arry_len = CFArrayGetCount (bat_info_arry);
- for (bat_info_arry_pos = 0;
+ for (CFIndex bat_info_arry_pos = 0;
bat_info_arry_pos < bat_info_arry_len;
bat_info_arry_pos++)
{
*ret_voltage = temp_double / 1000.0;
}
}
-
+
CFRelease (bat_root_dict);
}
* IOPowerSources. IOKit, on the other hand, only reports the full
* capacity. We use the two to calculate the current charged capacity. */
gauge_t charge_rel = NAN; /* Current charge in percent */
- gauge_t capacity_charged = NAN; /* Charged capacity */
+ gauge_t capacity_charged; /* Charged capacity */
gauge_t capacity_full = NAN; /* Total capacity */
gauge_t capacity_design = NAN; /* Full design capacity */
static int read_pmu (void) /* {{{ */
{
- int i;
-
+ int i = 0;
/* The upper limit here is just a safeguard. If there is a system with
* more than 100 batteries, this can easily be increased. */
- for (i = 0; i < 100; i++)
+ for (; i < 100; i++)
{
FILE *fh;
static int battery_config (oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/bind.c b/src/bind.c
index 6eac159cbcf78b1f36651aa7468f389a9baf74a8..9b6b32e3dada7811eca47ba32268b18decec1aff 100644 (file)
--- a/src/bind.c
+++ b/src/bind.c
#endif /* STRPTIME_NEEDS_STANDARDS */
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
/* Some versions of libcurl don't include this themselves and then don't have
* fd_set available. */
# define BIND_DEFAULT_URL "http://localhost:8053/"
#endif
-/*
+/*
* Some types used for the callback functions. `translation_table_ptr_t' and
* `list_info_ptr_t' are passed to the callbacks in the `void *user_data'
* pointer.
{
size_t len = size * nmemb;
- if (len <= 0)
+ if (len == 0)
return (len);
if ((bind_buffer_fill + len) >= bind_buffer_size)
{
char *temp;
- temp = realloc(bind_buffer, bind_buffer_fill + len + 1);
+ temp = realloc (bind_buffer, bind_buffer_fill + len + 1);
if (temp == NULL)
{
ERROR ("bind plugin: realloc failed.");
@@ -309,12 +309,11 @@ static int bind_xml_table_callback (const char *name, value_t value, /* {{{ */
time_t current_time, void *user_data)
{
translation_table_ptr_t *table = (translation_table_ptr_t *) user_data;
- size_t i;
if (table == NULL)
return (-1);
- for (i = 0; i < table->table_length; i++)
+ for (size_t i = 0; i < table->table_length; i++)
{
if (strcmp (table->table[i].xml_name, name) != 0)
continue;
xmlNode *node;
char *str_ptr;
char *tmp;
- struct tm tm;
+ struct tm tm = { 0 };
xpathObj = xmlXPathEvalExpression (BAD_CAST xpath_expression, xpathCtx);
if (xpathObj == NULL)
return (-1);
}
- memset (&tm, 0, sizeof(tm));
tmp = strptime (str_ptr, "%Y-%m-%dT%T", &tm);
xmlFree(str_ptr);
if (tmp == NULL)
return (0);
} /* }}} int bind_xml_read_timestamp */
-/*
+/*
* bind_parse_generic_name_value
*
* Reads statistics in the form:
@@ -491,7 +489,6 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ *
{
xmlXPathObject *xpathObj = NULL;
int num_entries;
- int i;
xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
if (xpathObj == NULL)
@@ -503,19 +500,18 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ *
num_entries = 0;
/* Iterate over all matching nodes. */
- for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+ for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
{
xmlNode *name_node = NULL;
xmlNode *counter = NULL;
xmlNode *parent;
- xmlNode *child;
parent = xpathObj->nodesetval->nodeTab[i];
DEBUG ("bind plugin: bind_parse_generic_name_value: parent->name = %s;",
(char *) parent->name);
/* Iterate over all child nodes. */
- for (child = parent->xmlChildrenNode;
+ for (xmlNode *child = parent->xmlChildrenNode;
child != NULL;
child = child->next)
{
@@ -559,7 +555,7 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ *
return (0);
} /* }}} int bind_parse_generic_name_value */
-/*
+/*
* bind_parse_generic_value_list
*
* Reads statistics in the form:
@@ -578,7 +574,6 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ *
{
xmlXPathObject *xpathObj = NULL;
int num_entries;
- int i;
xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
if (xpathObj == NULL)
@@ -590,12 +585,10 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ *
num_entries = 0;
/* Iterate over all matching nodes. */
- for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+ for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
{
- xmlNode *child;
-
/* Iterate over all child nodes. */
- for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
+ for (xmlNode *child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
child != NULL;
child = child->next)
{
@@ -649,7 +642,6 @@ static int bind_parse_generic_name_attr_value_list (const char *xpath_expression
{
xmlXPathObject *xpathObj = NULL;
int num_entries;
- int i;
xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
if (xpathObj == NULL)
@@ -661,12 +653,10 @@ static int bind_parse_generic_name_attr_value_list (const char *xpath_expression
num_entries = 0;
/* Iterate over all matching nodes. */
- for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+ for (int i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
{
- xmlNode *child;
-
/* Iterate over all child nodes. */
- for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
+ for (xmlNode *child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
child != NULL;
child = child->next)
{
{
xmlXPathObject *path_obj;
char *zone_name = NULL;
- int i;
size_t j;
if (version >= 3)
return (-1);
}
- for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
+ for (int i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
{
zone_name = (char *) xmlNodeListGetString (doc,
path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1);
{ /* Parse the <counters> tag {{{ */
char plugin_instance[DATA_MAX_NAME_LEN];
translation_table_ptr_t table_ptr =
- {
+ {
nsstats_translation_table,
nsstats_translation_table_length,
plugin_instance
{
xmlXPathObject *zone_nodes = NULL;
xmlXPathContext *zone_path_context;
- int i;
zone_path_context = xmlXPathNewContext (doc);
if (zone_path_context == NULL)
return (-1);
}
- for (i = 0; i < zone_nodes->nodesetval->nodeNr; i++)
+ for (int i = 0; i < zone_nodes->nodesetval->nodeNr; i++)
{
node = zone_nodes->nodesetval->nodeTab[i];
assert (node != NULL);
{
char *view_name = NULL;
cb_view_t *view;
- int i;
size_t j;
if (version == 3)
return (-1);
}
- for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
+ for (int i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
{
view_name = (char *) xmlNodeListGetString (doc,
path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1);
{
char plugin_instance[DATA_MAX_NAME_LEN];
translation_table_ptr_t table_ptr =
- {
+ {
resstats_translation_table,
resstats_translation_table_length,
plugin_instance
{
xmlXPathObject *view_nodes = NULL;
xmlXPathContext *view_path_context;
- int i;
view_path_context = xmlXPathNewContext (doc);
if (view_path_context == NULL)
return (-1);
}
- for (i = 0; i < view_nodes->nodesetval->nodeNr; i++)
+ for (int i = 0; i < view_nodes->nodesetval->nodeNr; i++)
{
xmlNode *node;
xmlXPathContext *xpathCtx = NULL;
xmlXPathObject *xpathObj = NULL;
int ret = -1;
- int i;
doc = xmlParseMemory (data, strlen (data));
if (doc == NULL)
}
else
{
- for (i = 0; i < xpathObj->nodesetval->nodeNr; i++)
+ for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++)
{
xmlNode *node;
char *attr_version;
return (-1);
}
- for (i = 0; i < xpathObj->nodesetval->nodeNr; i++)
+ for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++)
{
xmlNode *node;
char *attr_version;
return (-1);
}
- tmp = (char **) realloc (view->zones,
+ tmp = realloc (view->zones,
sizeof (char *) * (view->zones_num + 1));
if (tmp == NULL)
{
static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */
{
cb_view_t *tmp;
- int i;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
return (-1);
}
- tmp = (cb_view_t *) realloc (views, sizeof (*views) * (views_num + 1));
+ tmp = realloc (views, sizeof (*views) * (views_num + 1));
if (tmp == NULL)
{
ERROR ("bind plugin: realloc failed.");
return (-1);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static int bind_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
#ifdef HAVE_CURLOPT_TIMEOUT_MS
curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (timeout >= 0) ?
- (long) timeout : CDTIME_T_TO_MS(plugin_get_interval()));
+ (long) timeout : (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
diff --git a/src/ceph.c b/src/ceph.c
index 9c53a3e76590e1ba490c83e24c26551815c935cf..e6d3767b3140d786698f054796b23b4ed903b78f 100644 (file)
--- a/src/ceph.c
+++ b/src/ceph.c
#define _BSD_SOURCE
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#if HAVE_YAJL_YAJL_VERSION_H
#include <yajl/yajl_version.h>
#endif
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
#include <limits.h>
#include <poll.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
-#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
};
/** Valid types for ceph defined in types.db */
-const char * ceph_dset_types [CEPH_DSET_TYPES_NUM] =
+static const char * const ceph_dset_types [CEPH_DSET_TYPES_NUM] =
{"ceph_latency", "ceph_bytes", "ceph_rate"};
/******* ceph_daemon *******/
static struct ceph_daemon **g_daemons = NULL;
/** Number of elements in g_daemons */
-static int g_num_daemons = 0;
+static size_t g_num_daemons = 0;
/**
* A set of data that we build up in memory while parsing the JSON.
#define BUFFER_ADD(dest, src) do { \
size_t dest_size = sizeof (dest); \
- strncat ((dest), (src), dest_size - strlen (dest)); \
+ size_t dest_len = strlen (dest); \
+ if (dest_size > dest_len) { \
+ sstrncpy ((dest) + dest_len, (src), dest_size - dest_len); \
+ } \
(dest)[dest_size - 1] = 0; \
} while (0)
{
yajl_struct *state = (yajl_struct*) ctx;
char buffer[number_len+1];
- char key[2 * DATA_MAX_NAME_LEN];
+ char key[2 * DATA_MAX_NAME_LEN] = { 0 };
_Bool latency_type = 0;
- size_t i;
int status;
memcpy(buffer, number_val, number_len);
- buffer[sizeof(buffer) - 1] = 0;
+ buffer[sizeof(buffer) - 1] = '\0';
- memset (key, 0, sizeof (key));
- for (i = 0; i < state->depth; i++)
+ for (size_t i = 0; i < state->depth; i++)
{
if (state->stack[i] == NULL)
continue;
{
latency_type = 1;
+ /* depth >= 2 => (stack[-1] != NULL && stack[-2] != NULL) */
+ assert ((state->depth < 2)
+ || ((state->stack[state->depth - 1] != NULL)
+ && (state->stack[state->depth - 2] != NULL)));
+
/* Super-special case for filestore.journal_wr_bytes.avgcount: For
* some reason, Ceph schema encodes this as a count/sum pair while all
* other "Bytes" data (excluding used/capacity bytes for OSD space) uses
static void ceph_daemons_print(void)
{
- int i;
- for(i = 0; i < g_num_daemons; ++i)
+ for(size_t i = 0; i < g_num_daemons; ++i)
{
ceph_daemon_print(g_daemons[i]);
}
static void ceph_daemon_free(struct ceph_daemon *d)
{
- int i = 0;
- for(; i < d->last_idx; i++)
+ for(int i = 0; i < d->last_idx; i++)
{
sfree(d->last_poll_data[i]);
}
sfree(d->last_poll_data);
d->last_poll_data = NULL;
d->last_idx = 0;
- for(i = 0; i < d->ds_num; i++)
+
+ for(int i = 0; i < d->ds_num; i++)
{
sfree(d->ds_names[i]);
}
/* count_parts returns the number of elements a "foo.bar.baz" style key has. */
static size_t count_parts (char const *key)
{
- char const *ptr;
size_t parts_num = 0;
- for (ptr = key; ptr != NULL; ptr = strchr (ptr + 1, '.'))
+ for (const char *ptr = key; ptr != NULL; ptr = strchr (ptr + 1, '.'))
parts_num++;
return parts_num;
{
uint32_t type;
char ds_name[DATA_MAX_NAME_LEN];
- memset(ds_name, 0, sizeof(ds_name));
if(convert_special_metrics)
{
return -ENOMEM;
}
- d->ds_names[d->ds_num] = malloc(sizeof(char) * DATA_MAX_NAME_LEN);
+ d->ds_names[d->ds_num] = malloc(DATA_MAX_NAME_LEN);
if(!d->ds_names[d->ds_num])
{
return -ENOMEM;
static int cc_add_daemon_config(oconfig_item_t *ci)
{
- int ret, i;
- struct ceph_daemon *nd, cd;
+ int ret;
+ struct ceph_daemon *nd, cd = { 0 };
struct ceph_daemon **tmp;
- memset(&cd, 0, sizeof(struct ceph_daemon));
if((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
return ret;
}
- for(i=0; i < ci->children_num; i++)
+ for(int i=0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
}
g_daemons = tmp;
- nd = malloc(sizeof(*nd));
+ nd = malloc(sizeof (*nd));
if(!nd)
{
return ENOMEM;
}
memcpy(nd, &cd, sizeof(*nd));
- g_daemons[g_num_daemons++] = nd;
+ g_daemons[g_num_daemons] = nd;
+ g_num_daemons++;
return 0;
}
static int ceph_config(oconfig_item_t *ci)
{
- int ret, i;
+ int ret;
- for(i = 0; i < ci->children_num; ++i)
+ for(int i = 0; i < ci->children_num; ++i)
{
oconfig_item_t *child = ci->children + i;
if(strcasecmp("Daemon", child->key) == 0)
static int add_last(struct ceph_daemon *d, const char *ds_n, double cur_sum,
uint64_t cur_count)
{
- d->last_poll_data[d->last_idx] = malloc(1 * sizeof(struct last_data));
+ d->last_poll_data[d->last_idx] = malloc(sizeof (*d->last_poll_data[d->last_idx]));
if(!d->last_poll_data[d->last_idx])
{
return -ENOMEM;
if(!d->last_poll_data)
{
- d->last_poll_data = malloc(1 * sizeof(struct last_data *));
+ d->last_poll_data = malloc(sizeof (*d->last_poll_data));
if(!d->last_poll_data)
{
return -ENOMEM;
*/
static int backup_search_for_last_avg(struct ceph_daemon *d, const char *ds_n)
{
- int i = 0;
- for(; i < d->last_idx; i++)
+ for(int i = 0; i < d->last_idx; i++)
{
if(strcmp(d->last_poll_data[i]->ds_name, ds_n) == 0)
{
@@ -960,12 +965,11 @@ static double get_last_avg(struct ceph_daemon *d, const char *ds_n, int index,
*/
static uint32_t backup_search_for_type(struct ceph_daemon *d, char *ds_name)
{
- int idx = 0;
- for(; idx < d->ds_num; idx++)
+ for(int i = 0; i < d->ds_num; i++)
{
- if(strcmp(d->ds_names[idx], ds_name) == 0)
+ if(strcmp(d->ds_names[i], ds_name) == 0)
{
- return d->ds_types[idx];
+ return d->ds_types[i];
}
}
return DSET_TYPE_UNFOUND;
int index = vtmp->index;
char ds_name[DATA_MAX_NAME_LEN];
- memset(ds_name, 0, sizeof(ds_name));
if (parse_keys (ds_name, sizeof (ds_name), key))
{
@@ -1087,7 +1090,7 @@ static int node_handler_fetch_data(void *arg, const char *val, const char *key)
static int cconn_connect(struct cconn *io)
{
- struct sockaddr_un address;
+ struct sockaddr_un address = { 0 };
int flags, fd, err;
if(io->state != CSTATE_UNCONNECTED)
{
"failed: error %d", err);
return err;
}
- memset(&address, 0, sizeof(struct sockaddr_un));
address.sun_family = AF_UNIX;
snprintf(address.sun_path, sizeof(address.sun_path), "%s",
io->d->asok_path);
*/
static int cconn_main_loop(uint32_t request_type)
{
- int i, ret, some_unreachable = 0;
+ int ret, some_unreachable = 0;
struct timeval end_tv;
struct cconn io_array[g_num_daemons];
/* create cconn array */
memset(io_array, 0, sizeof(io_array));
- for(i = 0; i < g_num_daemons; ++i)
+ for(size_t i = 0; i < g_num_daemons; ++i)
{
io_array[i].d = g_daemons[i];
io_array[i].request_type = request_type;
struct pollfd fds[g_num_daemons];
memset(fds, 0, sizeof(fds));
nfds = 0;
- for(i = 0; i < g_num_daemons; ++i)
+ for(size_t i = 0; i < g_num_daemons; ++i)
{
struct cconn *io = io_array + i;
ret = cconn_prepare(io, fds + nfds);
if(ret < 0)
{
- WARNING("ceph plugin: cconn_prepare(name=%s,i=%d,st=%d)=%d",
+ WARNING("ceph plugin: cconn_prepare(name=%s,i=%zu,st=%d)=%d",
io->d->name, i, io->state, ret);
cconn_close(io);
io->request_type = ASOK_REQ_NONE;
ERROR("ceph plugin: poll(2) error: %d", ret);
goto done;
}
- for(i = 0; i < nfds; ++i)
+ for(int i = 0; i < nfds; ++i)
{
struct cconn *io = polled_io_array[i];
int revents = fds[i].revents;
if(revents == 0)
{
/* do nothing */
+ continue;
}
else if(cconn_validate_revents(io, revents))
{
}
}
}
- done: for(i = 0; i < g_num_daemons; ++i)
+ done: for(size_t i = 0; i < g_num_daemons; ++i)
{
cconn_close(io_array + i);
}
/******* lifecycle *******/
static int ceph_init(void)
{
- int ret;
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_DAC_OVERRIDE)
+ if (check_capability (CAP_DAC_OVERRIDE) != 0)
+ {
+ if (getuid () == 0)
+ WARNING ("ceph plugin: Running collectd as root, but the "
+ "CAP_DAC_OVERRIDE capability is missing. The plugin's read "
+ "function will probably fail. Is your init system dropping "
+ "capabilities?");
+ else
+ WARNING ("ceph plugin: collectd doesn't have the CAP_DAC_OVERRIDE "
+ "capability. If you don't want to run collectd as root, try running "
+ "\"setcap cap_dac_override=ep\" on the collectd binary.");
+ }
+#endif
+
ceph_daemons_print();
- ret = cconn_main_loop(ASOK_REQ_VERSION);
+ if (g_num_daemons < 1)
+ {
+ ERROR ("ceph plugin: No daemons configured. See the \"Daemon\" config option.");
+ return ENOENT;
+ }
- return (ret) ? ret : 0;
+ return cconn_main_loop(ASOK_REQ_VERSION);
}
static int ceph_shutdown(void)
{
- int i;
- for(i = 0; i < g_num_daemons; ++i)
+ for(size_t i = 0; i < g_num_daemons; ++i)
{
ceph_daemon_free(g_daemons[i]);
}
diff --git a/src/ceph_test.c b/src/ceph_test.c
index ae67125fc881fe1f63c2e34a0317930b03564bb5..91f084f7be9fb618fb44432f096279895704f564 100644 (file)
--- a/src/ceph_test.c
+++ b/src/ceph_test.c
struct case_s
{
- char *key;
- char *value;
+ const char *key;
+ const char *value;
};
typedef struct case_s case_t;
yajl_handle hndl;
#if HAVE_YAJL_V2
hndl = yajl_alloc (&callbacks, NULL, &ctx);
- CHECK_ZERO (traverse_json ((unsigned char *) json, (uint32_t) strlen (json), hndl));
+ CHECK_ZERO (traverse_json ((const unsigned char *) json, (uint32_t) strlen (json), hndl));
CHECK_ZERO (yajl_complete_parse (hndl));
#else
hndl = yajl_alloc (&callbacks, NULL, NULL, &ctx);
- CHECK_ZERO (traverse_json ((unsigned char *) json, (uint32_t) strlen (json), hndl));
+ CHECK_ZERO (traverse_json ((const unsigned char *) json, (uint32_t) strlen (json), hndl));
CHECK_ZERO (yajl_parse_complete (hndl));
#endif
+ yajl_free (hndl);
return 0;
}
DEF_TEST(parse_keys)
{
struct {
- char *str;
- char *want;
+ const char *str;
+ const char *want;
} cases[] = {
{"WBThrottle.bytes_dirtied.description.bytes_wb.description.ios_dirtied.description.ios_wb.type", "WBThrottle.bytesDirtied.description.bytesWb.description.iosDirt"},
{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
{
- char got[DATA_MAX_NAME_LEN];
-
- memset (got, 0, sizeof (got));
+ char got[64];
CHECK_ZERO (parse_keys (got, sizeof (got), cases[i].str));
-
- CHECK_ZERO (strcmp (got, cases[i].want));
+ EXPECT_EQ_STR (cases[i].want, got);
}
return 0;
diff --git a/src/cgroups.c b/src/cgroups.c
index 6d419722b7ef385ea0b8607f2b5b5056c849a408..f7c7e0d6345676ab77c79d8c6f0a880331b75273 100644 (file)
--- a/src/cgroups.c
+++ b/src/cgroups.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_mount.h"
#include "utils_ignorelist.h"
static int cgroups_read (void)
{
- cu_mount_t *mnt_list;
- cu_mount_t *mnt_ptr;
+ cu_mount_t *mnt_list = NULL;
_Bool cgroup_found = 0;
- mnt_list = NULL;
if (cu_mount_getlist (&mnt_list) == NULL)
{
ERROR ("cgroups plugin: cu_mount_getlist failed.");
return (-1);
}
- for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
+ for (cu_mount_t *mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
{
/* Find the cgroup mountpoint which contains the cpuacct
* controller. */
diff --git a/src/chrony.c b/src/chrony.c
--- /dev/null
+++ b/src/chrony.c
@@ -0,0 +1,1123 @@
+/* chrony plugin for collectd (monitoring of chrony time server daemon)
+ **********************************************************************
+ * Copyright (C) Claudius M Zingerli, ZSeng, 2015-2016
+ *
+ * Internals roughly based on the ntpd plugin
+ * Some functions copied from chronyd/web (as marked)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * TODO:
+ * - More robust udp parsing (using offsets instead of structs?)
+ * -> Currently chrony parses its data the same way as we do (using structs)
+ * - Plausibility checks on values received
+ * -> Done at higher levels
+ */
+
+#include "collectd.h"
+
+#include "common.h" /* auxiliary functions */
+#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
+
+#if HAVE_NETDB_H
+# include <netdb.h> /* struct addrinfo */
+#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h> /* ntohs/ntohl */
+#endif
+
+
+#define CONFIG_KEY_HOST "Host"
+#define CONFIG_KEY_PORT "Port"
+#define CONFIG_KEY_TIMEOUT "Timeout"
+
+#define URAND_DEVICE_PATH "/dev/urandom" /* Used to initialize seq nr generator */
+#define RAND_DEVICE_PATH "/dev/random" /* Used to initialize seq nr generator (fall back) */
+
+static const char *g_config_keys[] = {
+ CONFIG_KEY_HOST,
+ CONFIG_KEY_PORT,
+ CONFIG_KEY_TIMEOUT
+};
+
+static int g_config_keys_num = STATIC_ARRAY_SIZE(g_config_keys);
+static int g_chrony_is_connected;
+static int g_chrony_socket = -1;
+static time_t g_chrony_timeout = -1;
+static char *g_chrony_plugin_instance;
+static char *g_chrony_host;
+static char *g_chrony_port;
+static uint32_t g_chrony_rand = 1;
+static uint32_t g_chrony_seq_is_initialized;
+
+#define PLUGIN_NAME_SHORT "chrony"
+#define PLUGIN_NAME PLUGIN_NAME_SHORT " plugin"
+#define DAEMON_NAME PLUGIN_NAME_SHORT
+#define CHRONY_DEFAULT_HOST "localhost"
+#define CHRONY_DEFAULT_PORT "323"
+#define CHRONY_DEFAULT_TIMEOUT 2
+
+/* Return codes (collectd expects non-zero on errors) */
+#define CHRONY_RC_OK 0
+#define CHRONY_RC_FAIL 1
+
+/* Chronyd command packet variables adapted from chrony/candm.h (GPL2) */
+#define PROTO_VERSION_NUMBER 6
+#define IPADDR_UNSPEC 0
+#define IPADDR_INET4 1
+#define IPADDR_INET6 2
+#define IPV6_STR_MAX_SIZE (8*4+7+1)
+
+typedef enum
+{
+ PKT_TYPE_CMD_REQUEST = 1,
+ PKT_TYPE_CMD_REPLY = 2
+} ePacketType;
+
+typedef enum
+{
+ REQ_N_SOURCES = 14,
+ REQ_SOURCE_DATA = 15,
+ REQ_TRACKING = 33,
+ REQ_SOURCE_STATS = 34
+} eDaemonRequests;
+
+
+typedef enum
+{
+ RPY_NULL = 1,
+ RPY_N_SOURCES = 2,
+ RPY_SOURCE_DATA = 3,
+ RPY_MANUAL_TIMESTAMP = 4,
+ RPY_TRACKING = 5,
+ RPY_SOURCE_STATS = 6,
+ RPY_RTC = 7
+} eDaemonReplies;
+
+
+#if defined(__GNUC__) || defined (__SUNPRO_C) || defined(lint)
+# /* extension to enforce struct packing. */
+# define ATTRIB_PACKED __attribute__((packed))
+#else
+# error Not defining packed attribute (unknown compiler)
+# define ATTRIB_PACKED
+#endif
+
+typedef struct ATTRIB_PACKED
+{
+ int32_t value;
+} tFloat;
+
+typedef struct ATTRIB_PACKED
+{
+ uint32_t tv_sec_high;
+ uint32_t tv_sec_low;
+ uint32_t tv_nsec;
+} tTimeval;
+
+typedef enum
+{
+ STT_SUCCESS = 0,
+ STT_FAILED = 1,
+ STT_UNAUTH = 2,
+ STT_INVALID = 3,
+ STT_NOSUCHSOURCE = 4,
+ STT_INVALIDTS = 5,
+ STT_NOTENABLED = 6,
+ STT_BADSUBNET = 7,
+ STT_ACCESSALLOWED = 8,
+ STT_ACCESSDENIED = 9,
+ STT_NOHOSTACCESS = 10,
+ STT_SOURCEALREADYKNOWN = 11,
+ STT_TOOMANYSOURCES = 12,
+ STT_NORTC = 13,
+ STT_BADRTCFILE = 14,
+ STT_INACTIVE = 15,
+ STT_BADSAMPLE = 16,
+ STT_INVALIDAF = 17,
+ STT_BADPKTVERSION = 18,
+ STT_BADPKTLENGTH = 19
+} eChrony_Status;
+
+/* Chrony client request packets */
+typedef struct ATTRIB_PACKED
+{
+ uint8_t f_dummy0[80]; /* Chrony expects 80bytes dummy data (Avoiding UDP Amplification) */
+} tChrony_Req_Tracking;
+
+typedef struct ATTRIB_PACKED
+{
+ uint32_t f_n_sources;
+} tChrony_Req_N_Sources;
+
+typedef struct ATTRIB_PACKED
+{
+ int32_t f_index;
+ uint8_t f_dummy0[44];
+} tChrony_Req_Source_data;
+
+typedef struct ATTRIB_PACKED
+{
+ int32_t f_index;
+ uint8_t f_dummy0[56];
+} tChrony_Req_Source_stats;
+
+typedef struct ATTRIB_PACKED
+{
+ struct
+ {
+ uint8_t f_version;
+ uint8_t f_type;
+ uint8_t f_dummy0;
+ uint8_t f_dummy1;
+ uint16_t f_cmd;
+ uint16_t f_cmd_try;
+ uint32_t f_seq;
+
+ uint32_t f_dummy2;
+ uint32_t f_dummy3;
+ } header; /* Packed: 20Bytes */
+ union
+ {
+ tChrony_Req_N_Sources n_sources;
+ tChrony_Req_Source_data source_data;
+ tChrony_Req_Source_stats source_stats;
+ tChrony_Req_Tracking tracking;
+ } body;
+ uint8_t padding[4 + 16]; /* Padding to match minimal response size */
+} tChrony_Request;
+
+/* Chrony daemon response packets */
+typedef struct ATTRIB_PACKED
+{
+ uint32_t f_n_sources;
+} tChrony_Resp_N_Sources;
+
+typedef struct ATTRIB_PACKED
+{
+ union
+ {
+ uint32_t ip4;
+ uint8_t ip6[16];
+ } addr;
+ uint16_t f_family;
+} tChrony_IPAddr;
+
+typedef struct ATTRIB_PACKED
+{
+ tChrony_IPAddr addr;
+ uint16_t dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+ int16_t f_poll; /* 2^f_poll = Time between polls (s) */
+ uint16_t f_stratum; /* Remote clock stratum */
+ uint16_t f_state; /* 0 = RPY_SD_ST_SYNC, 1 = RPY_SD_ST_UNREACH, 2 = RPY_SD_ST_FALSETICKER */
+ /* 3 = RPY_SD_ST_JITTERY, 4 = RPY_SD_ST_CANDIDATE, 5 = RPY_SD_ST_OUTLIER */
+ uint16_t f_mode; /* 0 = RPY_SD_MD_CLIENT, 1 = RPY_SD_MD_PEER, 2 = RPY_SD_MD_REF */
+ uint16_t f_flags; /* unused */
+ uint16_t f_reachability; /* Bit mask of successfull tries to reach the source */
+
+ uint32_t f_since_sample; /* Time since last sample (s) */
+ tFloat f_origin_latest_meas; /* */
+ tFloat f_latest_meas; /* */
+ tFloat f_latest_meas_err; /* */
+} tChrony_Resp_Source_data;
+
+typedef struct ATTRIB_PACKED
+{
+ uint32_t f_ref_id;
+ tChrony_IPAddr addr;
+ uint16_t dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+ uint32_t f_n_samples; /* Number of measurements done */
+ uint32_t f_n_runs; /* How many measurements to come */
+ uint32_t f_span_seconds; /* For how long we're measuring */
+ tFloat f_rtc_seconds_fast; /* ??? */
+ tFloat f_rtc_gain_rate_ppm; /* Estimated relative frequency error */
+ tFloat f_skew_ppm; /* Clock skew (ppm) (worst case freq est error (skew: peak2peak)) */
+ tFloat f_est_offset; /* Estimated offset of source */
+ tFloat f_est_offset_err; /* Error of estimation */
+} tChrony_Resp_Source_stats;
+
+typedef struct ATTRIB_PACKED
+{
+ uint32_t f_ref_id;
+ tChrony_IPAddr addr;
+ uint16_t dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+ uint16_t f_stratum;
+ uint16_t f_leap_status;
+ tTimeval f_ref_time;
+ tFloat f_current_correction;
+ tFloat f_last_offset;
+ tFloat f_rms_offset;
+ tFloat f_freq_ppm;
+ tFloat f_resid_freq_ppm;
+ tFloat f_skew_ppm;
+ tFloat f_root_delay;
+ tFloat f_root_dispersion;
+ tFloat f_last_update_interval;
+} tChrony_Resp_Tracking;
+
+typedef struct ATTRIB_PACKED
+{
+ struct
+ {
+ uint8_t f_version;
+ uint8_t f_type;
+ uint8_t f_dummy0;
+ uint8_t f_dummy1;
+ uint16_t f_cmd;
+ uint16_t f_reply;
+ uint16_t f_status;
+ uint16_t f_dummy2;
+ uint16_t f_dummy3;
+ uint16_t f_dummy4;
+ uint32_t f_seq;
+ uint32_t f_dummy5;
+ uint32_t f_dummy6;
+ } header; /* Packed: 28 Bytes */
+
+ union
+ {
+ tChrony_Resp_N_Sources n_sources;
+ tChrony_Resp_Source_data source_data;
+ tChrony_Resp_Source_stats source_stats;
+ tChrony_Resp_Tracking tracking;
+ } body;
+
+ uint8_t padding[1024];
+} tChrony_Response;
+
+
+/*****************************************************************************/
+/* Internal functions */
+/*****************************************************************************/
+
+/* connect_client code adapted from: http://long.ccaba.upc.edu/long/045Guidelines/eva/ipv6.html#daytimeClient6 */
+/* License granted by Eva M Castro via e-mail on 2016-02-18 under the terms of GPLv3 */
+static int
+connect_client(const char *p_hostname,
+ const char *p_service, int p_family, int p_socktype)
+{
+ struct addrinfo *res, *ressave;
+ int n, sockfd;
+
+ struct addrinfo ai_hints = {
+ .ai_family = p_family,
+ .ai_socktype = p_socktype
+ };
+
+ n = getaddrinfo(p_hostname, p_service, &ai_hints, &res);
+
+ if (n < 0)
+ {
+ ERROR(PLUGIN_NAME ": getaddrinfo error:: [%s]", gai_strerror(n));
+ return -1;
+ }
+
+ ressave = res;
+
+ sockfd = -1;
+ while (res)
+ {
+ sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+
+ if (!(sockfd < 0))
+ {
+ if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
+ {
+ /* Success */
+ break;
+ }
+
+ close(sockfd);
+ sockfd = -1;
+ }
+ res = res->ai_next;
+ }
+
+ freeaddrinfo(ressave);
+ return sockfd;
+}
+
+
+/* niptoha code originally from: git://git.tuxfamily.org/gitroot/chrony/chrony.git:util.c */
+/* Original code licensed as GPLv2, by Richard P. Purnow, Miroslav Lichvar */
+/* Original name: char * UTI_IPToString(IPAddr *addr)*/
+static char *
+niptoha(const tChrony_IPAddr * addr, char *p_buf, size_t p_buf_size)
+{
+ int rc = 1;
+ unsigned long a, b, c, d, ip;
+
+ switch (ntohs(addr->f_family))
+ {
+ case IPADDR_UNSPEC:
+ rc = snprintf(p_buf, p_buf_size, "[UNSPEC]");
+ break;
+ case IPADDR_INET4:
+ ip = ntohl(addr->addr.ip4);
+ a = (ip >> 24) & 0xff;
+ b = (ip >> 16) & 0xff;
+ c = (ip >> 8) & 0xff;
+ d = (ip >> 0) & 0xff;
+ rc = snprintf(p_buf, p_buf_size, "%ld.%ld.%ld.%ld", a, b, c, d);
+ break;
+ case IPADDR_INET6:
+ {
+ const char *rp = inet_ntop(AF_INET6, addr->addr.ip6, p_buf, p_buf_size);
+ if (rp == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error converting ipv6 address to string. Errno = %d", errno);
+ rc = snprintf(p_buf, p_buf_size, "[UNKNOWN]");
+ }
+ break;
+ }
+ default:
+ rc = snprintf(p_buf, p_buf_size, "[UNKNOWN]");
+ }
+ assert(rc > 0);
+ return p_buf;
+}
+
+
+static int
+chrony_set_timeout(void)
+{
+ /* Set the socket's timeout to g_chrony_timeout; a value of 0 signals infinite timeout */
+ /* Returns 0 on success, !0 on error (check errno) */
+
+ struct timeval tv;
+ tv.tv_sec = g_chrony_timeout;
+ tv.tv_usec = 0;
+
+ assert(g_chrony_socket >= 0);
+ if (setsockopt(g_chrony_socket, SOL_SOCKET,
+ SO_RCVTIMEO, (char *) &tv, sizeof(struct timeval)) < 0)
+ {
+ return CHRONY_RC_FAIL;
+ }
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_connect(void)
+{
+ /* Connects to the chrony daemon */
+ /* Returns 0 on success, !0 on error (check errno) */
+ int socket;
+
+ if (g_chrony_host == NULL)
+ {
+ g_chrony_host = strdup(CHRONY_DEFAULT_HOST);
+ if (g_chrony_host == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error duplicating chrony host name");
+ return CHRONY_RC_FAIL;
+ }
+ }
+ if (g_chrony_port == NULL)
+ {
+ g_chrony_port = strdup(CHRONY_DEFAULT_PORT);
+ if (g_chrony_port == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error duplicating chrony port string");
+ return CHRONY_RC_FAIL;
+ }
+ }
+ if (g_chrony_timeout < 0)
+ {
+ g_chrony_timeout = CHRONY_DEFAULT_TIMEOUT;
+ assert(g_chrony_timeout >= 0);
+ }
+
+ DEBUG(PLUGIN_NAME ": Connecting to %s:%s", g_chrony_host, g_chrony_port);
+ socket = connect_client(g_chrony_host, g_chrony_port, AF_UNSPEC, SOCK_DGRAM);
+ if (socket < 0)
+ {
+ ERROR(PLUGIN_NAME ": Error connecting to daemon. Errno = %d", errno);
+ return CHRONY_RC_FAIL;
+ }
+ DEBUG(PLUGIN_NAME ": Connected");
+ g_chrony_socket = socket;
+
+ if (chrony_set_timeout())
+ {
+ ERROR(PLUGIN_NAME ": Error setting timeout to %llds. Errno = %d",
+ (long long)g_chrony_timeout, errno);
+ return CHRONY_RC_FAIL;
+ }
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_send_request(const tChrony_Request * p_req, size_t p_req_size)
+{
+ if (send(g_chrony_socket, p_req, p_req_size, 0) < 0)
+ {
+ ERROR(PLUGIN_NAME ": Error sending packet. Errno = %d", errno);
+ return CHRONY_RC_FAIL;
+ }
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_recv_response(tChrony_Response * p_resp, size_t p_resp_max_size,
+ size_t * p_resp_size)
+{
+ ssize_t rc = recv(g_chrony_socket, p_resp, p_resp_max_size, 0);
+ if (rc <= 0)
+ {
+ ERROR(PLUGIN_NAME ": Error receiving packet: %s (%d)", strerror(errno),
+ errno);
+ return CHRONY_RC_FAIL;
+ }
+ else
+ {
+ *p_resp_size = rc;
+ return CHRONY_RC_OK;
+ }
+}
+
+
+static int
+chrony_query(const int p_command, tChrony_Request * p_req,
+ tChrony_Response * p_resp, size_t * p_resp_size)
+{
+ /* Check connection. We simply perform one try as collectd already handles retries */
+ assert(p_req);
+ assert(p_resp);
+ assert(p_resp_size);
+
+ if (g_chrony_is_connected == 0)
+ {
+ if (chrony_connect() == CHRONY_RC_OK)
+ {
+ g_chrony_is_connected = 1;
+ }
+ else
+ {
+ ERROR(PLUGIN_NAME ": Unable to connect. Errno = %d", errno);
+ return CHRONY_RC_FAIL;
+ }
+ }
+
+ do
+ {
+ int valid_command = 0;
+ size_t req_size = sizeof(p_req->header) + sizeof(p_req->padding);
+ size_t resp_size = sizeof(p_resp->header);
+ uint16_t resp_code = RPY_NULL;
+ switch (p_command)
+ {
+ case REQ_TRACKING:
+ req_size += sizeof(p_req->body.tracking);
+ resp_size += sizeof(p_resp->body.tracking);
+ resp_code = RPY_TRACKING;
+ valid_command = 1;
+ break;
+ case REQ_N_SOURCES:
+ req_size += sizeof(p_req->body.n_sources);
+ resp_size += sizeof(p_resp->body.n_sources);
+ resp_code = RPY_N_SOURCES;
+ valid_command = 1;
+ break;
+ case REQ_SOURCE_DATA:
+ req_size += sizeof(p_req->body.source_data);
+ resp_size += sizeof(p_resp->body.source_data);
+ resp_code = RPY_SOURCE_DATA;
+ valid_command = 1;
+ break;
+ case REQ_SOURCE_STATS:
+ req_size += sizeof(p_req->body.source_stats);
+ resp_size += sizeof(p_resp->body.source_stats);
+ resp_code = RPY_SOURCE_STATS;
+ valid_command = 1;
+ break;
+ default:
+ ERROR(PLUGIN_NAME ": Unknown request command (Was: %d)", p_command);
+ break;
+ }
+
+ if (valid_command == 0)
+ break;
+
+ uint32_t seq_nr = rand_r(&g_chrony_rand);
+ p_req->header.f_cmd = htons(p_command);
+ p_req->header.f_cmd_try = 0;
+ p_req->header.f_seq = seq_nr;
+
+ DEBUG(PLUGIN_NAME ": Sending request (.cmd = %d, .seq = %d)", p_command,
+ seq_nr);
+ if (chrony_send_request(p_req, req_size) != 0)
+ break;
+
+ DEBUG(PLUGIN_NAME ": Waiting for response");
+ if (chrony_recv_response(p_resp, resp_size, p_resp_size) != 0)
+ break;
+
+ DEBUG(PLUGIN_NAME
+ ": Received response: .version = %u, .type = %u, .cmd = %u, .reply = %u, .status = %u, .seq = %u",
+ p_resp->header.f_version, p_resp->header.f_type,
+ ntohs(p_resp->header.f_cmd), ntohs(p_resp->header.f_reply),
+ ntohs(p_resp->header.f_status), p_resp->header.f_seq);
+
+ if (p_resp->header.f_version != p_req->header.f_version)
+ {
+ ERROR(PLUGIN_NAME ": Wrong protocol version (Was: %d, expected: %d)",
+ p_resp->header.f_version, p_req->header.f_version);
+ return CHRONY_RC_FAIL;
+ }
+ if (p_resp->header.f_type != PKT_TYPE_CMD_REPLY)
+ {
+ ERROR(PLUGIN_NAME ": Wrong packet type (Was: %d, expected: %d)",
+ p_resp->header.f_type, PKT_TYPE_CMD_REPLY);
+ return CHRONY_RC_FAIL;
+ }
+ if (p_resp->header.f_seq != seq_nr)
+ {
+ /* FIXME: Implement sequence number handling */
+ ERROR(PLUGIN_NAME
+ ": Unexpected sequence number (Was: %d, expected: %d)",
+ p_resp->header.f_seq, p_req->header.f_seq);
+ return CHRONY_RC_FAIL;
+ }
+ if (p_resp->header.f_cmd != p_req->header.f_cmd)
+ {
+ ERROR(PLUGIN_NAME ": Wrong reply command (Was: %d, expected: %d)",
+ p_resp->header.f_cmd, p_req->header.f_cmd);
+ return CHRONY_RC_FAIL;
+ }
+
+ if (ntohs(p_resp->header.f_reply) != resp_code)
+ {
+ ERROR(PLUGIN_NAME ": Wrong reply code (Was: %d, expected: %d)",
+ ntohs(p_resp->header.f_reply), resp_code);
+ return CHRONY_RC_FAIL;
+ }
+
+ switch (p_resp->header.f_status)
+ {
+ case STT_SUCCESS:
+ DEBUG(PLUGIN_NAME ": Reply packet status STT_SUCCESS");
+ break;
+ default:
+ ERROR(PLUGIN_NAME
+ ": Reply packet contains error status: %d (expected: %d)",
+ p_resp->header.f_status, STT_SUCCESS);
+ return CHRONY_RC_FAIL;
+ }
+
+ /* Good result */
+ return CHRONY_RC_OK;
+ }
+ while (0);
+
+ /* Some error occured */
+ return CHRONY_RC_FAIL;
+}
+
+
+static void
+chrony_init_req(tChrony_Request * p_req)
+{
+ memset(p_req, 0, sizeof(*p_req));
+ p_req->header.f_version = PROTO_VERSION_NUMBER;
+ p_req->header.f_type = PKT_TYPE_CMD_REQUEST;
+ p_req->header.f_dummy0 = 0;
+ p_req->header.f_dummy1 = 0;
+ p_req->header.f_dummy2 = 0;
+ p_req->header.f_dummy3 = 0;
+}
+
+
+/* ntohf code originally from: git://git.tuxfamily.org/gitroot/chrony/chrony.git:util.c */
+/* Original code licensed as GPLv2, by Richard P. Purnow, Miroslav Lichvar */
+/* Original name: double UTI_tFloatNetworkToHost(tFloat f) */
+static double
+ntohf(tFloat p_float)
+{
+ /* Convert tFloat in Network-bit-order to double in host-bit-order */
+
+#define FLOAT_EXP_BITS 7
+#define FLOAT_EXP_MIN (-(1 << (FLOAT_EXP_BITS - 1)))
+#define FLOAT_EXP_MAX (-FLOAT_EXP_MIN - 1)
+#define FLOAT_COEF_BITS ((int)sizeof (int32_t) * 8 - FLOAT_EXP_BITS)
+#define FLOAT_COEF_MIN (-(1 << (FLOAT_COEF_BITS - 1)))
+#define FLOAT_COEF_MAX (-FLOAT_COEF_MIN - 1)
+
+ int32_t exp, coef;
+ uint32_t uval;
+
+ uval = ntohl(p_float.value);
+ exp = (uval >> FLOAT_COEF_BITS) - FLOAT_COEF_BITS;
+ if (exp >= 1 << (FLOAT_EXP_BITS - 1))
+ exp -= 1 << FLOAT_EXP_BITS;
+
+ /* coef = (x << FLOAT_EXP_BITS) >> FLOAT_EXP_BITS; */
+ coef = uval % (1U << FLOAT_COEF_BITS);
+ if (coef >= 1 << (FLOAT_COEF_BITS - 1))
+ coef -= 1 << FLOAT_COEF_BITS;
+
+ return coef * pow(2.0, exp);
+}
+
+
+static void
+chrony_push_data(const char *p_type, const char *p_type_inst, double p_value)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = p_value; /* TODO: Check type??? (counter, gauge, derive, absolute) */
+
+ vl.values = values;
+ vl.values_len = 1;
+
+ /* XXX: Shall g_chrony_host/g_chrony_port be reflected in the plugin's output? */
+ /* hostname_g is set in daemon/collectd.c (from config, via gethostname or by resolving localhost) */
+ /* defined as: char hostname_g[DATA_MAX_NAME_LEN]; (never NULL) */
+ sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+ sstrncpy(vl.plugin, PLUGIN_NAME_SHORT, sizeof(vl.plugin));
+ if (g_chrony_plugin_instance != NULL)
+ {
+ sstrncpy(vl.plugin_instance, g_chrony_plugin_instance,
+ sizeof(vl.plugin_instance));
+ }
+ if (p_type != NULL)
+ sstrncpy(vl.type, p_type, sizeof(vl.type));
+
+ if (p_type_inst != NULL)
+ sstrncpy(vl.type_instance, p_type_inst, sizeof(vl.type_instance));
+
+ plugin_dispatch_values(&vl);
+}
+
+
+static void
+chrony_push_data_valid(const char *p_type, const char *p_type_inst, const int p_is_valid,
+ double p_value)
+{
+ /* Push real value if p_is_valid is true, push NAN if p_is_valid is not true (idea from ntp plugin) */
+ if (p_is_valid == 0)
+ p_value = NAN;
+
+ chrony_push_data(p_type, p_type_inst, p_value);
+}
+
+
+static int
+chrony_init_seq(void)
+{
+ /* Initialize the sequence number generator from /dev/urandom */
+ /* Fallbacks: /dev/random and time(NULL) */
+
+ int fh;
+
+ /* Try urandom */
+ fh = open(URAND_DEVICE_PATH, O_RDONLY);
+ if (fh >= 0)
+ {
+ ssize_t rc = read(fh, &g_chrony_rand, sizeof(g_chrony_rand));
+ if (rc != sizeof(g_chrony_rand))
+ {
+ ERROR(PLUGIN_NAME ": Reading from random source \'%s\'failed: %s (%d)",
+ URAND_DEVICE_PATH, strerror(errno), errno);
+ close(fh);
+ return CHRONY_RC_FAIL;
+ }
+ close(fh);
+ DEBUG(PLUGIN_NAME ": Seeding RNG from " URAND_DEVICE_PATH);
+ }
+ else
+ {
+ if (errno == ENOENT)
+ {
+ /* URAND_DEVICE_PATH device not found. Try RAND_DEVICE_PATH as fall-back */
+ fh = open(RAND_DEVICE_PATH, O_RDONLY);
+ if (fh >= 0)
+ {
+ ssize_t rc = read(fh, &g_chrony_rand, sizeof(g_chrony_rand));
+ if (rc != sizeof(g_chrony_rand))
+ {
+ ERROR(PLUGIN_NAME
+ ": Reading from random source \'%s\'failed: %s (%d)",
+ RAND_DEVICE_PATH, strerror(errno), errno);
+ close(fh);
+ return CHRONY_RC_FAIL;
+ }
+ close(fh);
+ DEBUG(PLUGIN_NAME ": Seeding RNG from " RAND_DEVICE_PATH);
+ }
+ else
+ {
+ /* Error opening RAND_DEVICE_PATH. Try time(NULL) as fall-back */
+ DEBUG(PLUGIN_NAME ": Seeding RNG from time(NULL)");
+ g_chrony_rand = time(NULL) ^ getpid();
+ }
+ }
+ else
+ {
+ ERROR(PLUGIN_NAME ": Opening random source \'%s\' failed: %s (%d)",
+ URAND_DEVICE_PATH, strerror(errno), errno);
+ return CHRONY_RC_FAIL;
+ }
+ }
+
+ return CHRONY_RC_OK;
+}
+
+
+/*****************************************************************************/
+/* Exported functions */
+/*****************************************************************************/
+static int
+chrony_config(const char *p_key, const char *p_value)
+{
+ assert(p_key);
+ assert(p_value);
+
+ /* Parse config variables */
+ if (strcasecmp(p_key, CONFIG_KEY_HOST) == 0)
+ {
+ if (g_chrony_host != NULL)
+ free(g_chrony_host);
+
+ if ((g_chrony_host = strdup(p_value)) == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error duplicating host name");
+ return CHRONY_RC_FAIL;
+ }
+ }
+ else
+ {
+ if (strcasecmp(p_key, CONFIG_KEY_PORT) == 0)
+ {
+ if (g_chrony_port != NULL)
+ free(g_chrony_port);
+
+ if ((g_chrony_port = strdup(p_value)) == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error duplicating port name");
+ return CHRONY_RC_FAIL;
+ }
+ }
+ else
+ {
+ if (strcasecmp(p_key, CONFIG_KEY_TIMEOUT) == 0)
+ {
+ time_t tosec = strtol(p_value, NULL, 0);
+ g_chrony_timeout = tosec;
+ }
+ else
+ {
+ WARNING(PLUGIN_NAME ": Unknown configuration variable: %s %s", p_key, p_value);
+ return CHRONY_RC_FAIL;
+ }
+ }
+ }
+ /* XXX: We could set g_chrony_plugin_instance here to "g_chrony_host-g_chrony_port", but as multiple instances aren't yet supported, we skip this for now */
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_daemon_stats(void)
+{
+ /* Perform Tracking request */
+ int rc;
+ size_t chrony_resp_size;
+ tChrony_Request chrony_req;
+ tChrony_Response chrony_resp;
+
+ chrony_init_req(&chrony_req);
+ rc =
+ chrony_query(REQ_TRACKING, &chrony_req, &chrony_resp, &chrony_resp_size);
+ if (rc != 0)
+ {
+ ERROR(PLUGIN_NAME ": chrony_query (REQ_TRACKING) failed with status %i",
+ rc);
+ return rc;
+ }
+#if COLLECT_DEBUG
+ {
+ char src_addr[IPV6_STR_MAX_SIZE] = { 0 };
+ niptoha(&chrony_resp.body.tracking.addr, src_addr, sizeof(src_addr));
+ DEBUG(PLUGIN_NAME ": Daemon stat: .addr = %s, .ref_id= %u, .stratum = %u, .leap_status = %u, .ref_time = %u:%u:%u, .current_correction = %f, .last_offset = %f, .rms_offset = %f, .freq_ppm = %f, .skew_ppm = %f, .root_delay = %f, .root_dispersion = %f, .last_update_interval = %f", src_addr, ntohs(chrony_resp.body.tracking.f_ref_id),
+ ntohs(chrony_resp.body.tracking.f_stratum),
+ ntohs(chrony_resp.body.tracking.f_leap_status),
+ ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_high),
+ ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_low),
+ ntohl(chrony_resp.body.tracking.f_ref_time.tv_nsec),
+ ntohf(chrony_resp.body.tracking.f_current_correction),
+ ntohf(chrony_resp.body.tracking.f_last_offset),
+ ntohf(chrony_resp.body.tracking.f_rms_offset),
+ ntohf(chrony_resp.body.tracking.f_freq_ppm),
+ ntohf(chrony_resp.body.tracking.f_skew_ppm),
+ ntohf(chrony_resp.body.tracking.f_root_delay),
+ ntohf(chrony_resp.body.tracking.f_root_dispersion),
+ ntohf(chrony_resp.body.tracking.f_last_update_interval));
+ }
+#endif
+
+ double time_ref = ntohl(chrony_resp.body.tracking.f_ref_time.tv_nsec);
+ time_ref /= 1000000000.0;
+ time_ref += ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_low);
+ if (chrony_resp.body.tracking.f_ref_time.tv_sec_high)
+ {
+ double secs_high =
+ ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_high);
+ secs_high *= 4294967296.0;
+ time_ref += secs_high;
+ }
+
+ /* Forward results to collectd-daemon */
+ /* Type_instance is always 'chrony' to tag daemon-wide data */
+ /* Type Type_instan Value */
+ chrony_push_data("clock_stratum", DAEMON_NAME, ntohs(chrony_resp.body.tracking.f_stratum));
+ chrony_push_data("time_ref", DAEMON_NAME, time_ref); /* unit: s */
+ chrony_push_data("time_offset_ntp", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_current_correction)); /* Offset between system time and NTP, unit: s */
+ chrony_push_data("time_offset", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_last_offset)); /* Estimated Offset of the NTP time, unit: s */
+ chrony_push_data("time_offset_rms", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_rms_offset)); /* averaged value of the above, unit: s */
+ chrony_push_data("frequency_error", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_freq_ppm)); /* Frequency error of the local osc, unit: ppm */
+ chrony_push_data("clock_skew_ppm", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_skew_ppm));
+ chrony_push_data("root_delay", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_root_delay)); /* Network latency between local daemon and the current source */
+ chrony_push_data("root_dispersion", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_root_dispersion));
+ chrony_push_data("clock_last_update", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_last_update_interval));
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_sources_count(unsigned int *p_count)
+{
+ /* Requests the number of time sources from the chrony daemon */
+ int rc;
+ size_t chrony_resp_size;
+ tChrony_Request chrony_req;
+ tChrony_Response chrony_resp;
+
+ DEBUG(PLUGIN_NAME ": Requesting data");
+ chrony_init_req(&chrony_req);
+ rc =
+ chrony_query(REQ_N_SOURCES, &chrony_req, &chrony_resp, &chrony_resp_size);
+ if (rc != 0)
+ {
+ ERROR(PLUGIN_NAME ": chrony_query (REQ_N_SOURCES) failed with status %i",
+ rc);
+ return rc;
+ }
+
+ *p_count = ntohl(chrony_resp.body.n_sources.f_n_sources);
+ DEBUG(PLUGIN_NAME ": Getting data of %d clock sources", *p_count);
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_source_data(int p_src_idx, int *p_is_reachable)
+{
+ /* Perform Source data request for source #p_src_idx */
+ int rc;
+ size_t chrony_resp_size;
+ tChrony_Request chrony_req;
+ tChrony_Response chrony_resp;
+
+ char src_addr[IPV6_STR_MAX_SIZE] = { 0 };
+
+ chrony_init_req(&chrony_req);
+ chrony_req.body.source_data.f_index = htonl(p_src_idx);
+ rc =
+ chrony_query(REQ_SOURCE_DATA, &chrony_req, &chrony_resp,
+ &chrony_resp_size);
+ if (rc != 0)
+ {
+ ERROR(PLUGIN_NAME
+ ": chrony_query (REQ_SOURCE_DATA) failed with status %i", rc);
+ return rc;
+ }
+
+ niptoha(&chrony_resp.body.source_data.addr, src_addr, sizeof(src_addr));
+ DEBUG(PLUGIN_NAME
+ ": Source[%d] data: .addr = %s, .poll = %u, .stratum = %u, .state = %u, .mode = %u, .flags = %u, .reach = %u, .latest_meas_ago = %u, .orig_latest_meas = %f, .latest_meas = %f, .latest_meas_err = %f",
+ p_src_idx, src_addr, ntohs(chrony_resp.body.source_data.f_poll),
+ ntohs(chrony_resp.body.source_data.f_stratum),
+ ntohs(chrony_resp.body.source_data.f_state),
+ ntohs(chrony_resp.body.source_data.f_mode),
+ ntohs(chrony_resp.body.source_data.f_flags),
+ ntohs(chrony_resp.body.source_data.f_reachability),
+ ntohl(chrony_resp.body.source_data.f_since_sample),
+ ntohf(chrony_resp.body.source_data.f_origin_latest_meas),
+ ntohf(chrony_resp.body.source_data.f_latest_meas),
+ ntohf(chrony_resp.body.source_data.f_latest_meas_err));
+
+ /* Push NaN if source is currently not reachable */
+ int is_reachable =
+ ntohs(chrony_resp.body.source_data.f_reachability) & 0x01;
+ *p_is_reachable = is_reachable;
+
+ /* Forward results to collectd-daemon */
+ chrony_push_data_valid("clock_stratum", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_stratum));
+ chrony_push_data_valid("clock_state", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_state));
+ chrony_push_data_valid("clock_mode", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_mode));
+ chrony_push_data_valid("clock_reachability", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_reachability));
+ chrony_push_data_valid("clock_last_meas", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_since_sample));
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_source_stats(int p_src_idx, const int *p_is_reachable)
+{
+ /* Perform Source stats request for source #p_src_idx */
+ int rc;
+ size_t chrony_resp_size;
+ tChrony_Request chrony_req;
+ tChrony_Response chrony_resp;
+ double skew_ppm, frequency_error, time_offset;
+
+ char src_addr[IPV6_STR_MAX_SIZE] = { 0 };
+
+ if (*p_is_reachable == 0)
+ {
+ skew_ppm = 0;
+ frequency_error = 0;
+ time_offset = 0;
+ }
+ else
+ {
+ chrony_init_req(&chrony_req);
+ chrony_req.body.source_stats.f_index = htonl(p_src_idx);
+ rc =
+ chrony_query(REQ_SOURCE_STATS, &chrony_req, &chrony_resp,
+ &chrony_resp_size);
+ if (rc != 0)
+ {
+ ERROR(PLUGIN_NAME
+ ": chrony_query (REQ_SOURCE_STATS) failed with status %i", rc);
+ return rc;
+ }
+
+ skew_ppm = ntohf(chrony_resp.body.source_stats.f_skew_ppm);
+ frequency_error =
+ ntohf(chrony_resp.body.source_stats.f_rtc_gain_rate_ppm);
+ time_offset = ntohf(chrony_resp.body.source_stats.f_est_offset);
+
+ niptoha(&chrony_resp.body.source_stats.addr, src_addr, sizeof(src_addr));
+ DEBUG(PLUGIN_NAME
+ ": Source[%d] stat: .addr = %s, .ref_id= %u, .n_samples = %u, "
+ ".n_runs = %u, .span_seconds = %u, .rtc_seconds_fast = %f, "
+ ".rtc_gain_rate_ppm = %f, .skew_ppm= %f, .est_offset = %f, .est_offset_err = %f",
+ p_src_idx, src_addr,
+ ntohl(chrony_resp.body.source_stats.f_ref_id),
+ ntohl(chrony_resp.body.source_stats.f_n_samples),
+ ntohl(chrony_resp.body.source_stats.f_n_runs),
+ ntohl(chrony_resp.body.source_stats.f_span_seconds),
+ ntohf(chrony_resp.body.source_stats.f_rtc_seconds_fast),
+ frequency_error, skew_ppm, time_offset,
+ ntohf(chrony_resp.body.source_stats.f_est_offset_err));
+
+ } /* if (*is_reachable) */
+
+ /* Forward results to collectd-daemon */
+ chrony_push_data_valid("clock_skew_ppm", src_addr, *p_is_reachable, skew_ppm);
+ chrony_push_data_valid("frequency_error", src_addr, *p_is_reachable, frequency_error); /* unit: ppm */
+ chrony_push_data_valid("time_offset", src_addr, *p_is_reachable, time_offset); /* unit: s */
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_read(void)
+{
+ /* collectd read callback: Perform data acquisition */
+ int rc;
+ unsigned int n_sources;
+
+ if (g_chrony_seq_is_initialized == 0)
+ {
+ /* Seed RNG for sequence number generation */
+ rc = chrony_init_seq();
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ g_chrony_seq_is_initialized = 1;
+ }
+
+ /* Get daemon stats */
+ rc = chrony_request_daemon_stats();
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ /* Get number of time sources, then check every source for status */
+ rc = chrony_request_sources_count(&n_sources);
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ for (unsigned int now_src = 0; now_src < n_sources; ++now_src)
+ {
+ int is_reachable;
+ rc = chrony_request_source_data(now_src, &is_reachable);
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ rc = chrony_request_source_stats(now_src, &is_reachable);
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ }
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_shutdown(void)
+{
+ /* Collectd shutdown callback: Free mem */
+ if (g_chrony_is_connected != 0)
+ {
+ close(g_chrony_socket);
+ g_chrony_is_connected = 0;
+ }
+ if (g_chrony_host != NULL)
+ sfree(g_chrony_host);
+
+ if (g_chrony_port != NULL)
+ sfree(g_chrony_port);
+
+ if (g_chrony_plugin_instance != NULL)
+ sfree(g_chrony_plugin_instance);
+
+ return CHRONY_RC_OK;
+}
+
+
+void
+module_register(void)
+{
+ plugin_register_config(PLUGIN_NAME_SHORT, chrony_config, g_config_keys,
+ g_config_keys_num);
+ plugin_register_read(PLUGIN_NAME_SHORT, chrony_read);
+ plugin_register_shutdown(PLUGIN_NAME_SHORT, chrony_shutdown);
+}
diff --git a/src/collectd-java.pod b/src/collectd-java.pod
index aade08a456b701aff4fdc94f70f1907617de1127..afa7e48a6516c1bd82aef5358d3301cbb5827be6 100644 (file)
--- a/src/collectd-java.pod
+++ b/src/collectd-java.pod
Works like the option of the same name directly beneath the I<MBean> block, but
sets the type instance instead. I<(optional)>
+=item B<PluginName> I<name>
+
+When set, overrides the default setting for the I<plugin> field
+(C<GenericJMX>).
+
=item B<Table> B<true>|B<false>
Set this to true if the returned attribute is a I<composite type>. If set to
diff --git a/src/collectd-lua.pod b/src/collectd-lua.pod
--- /dev/null
+++ b/src/collectd-lua.pod
@@ -0,0 +1,163 @@
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-lua - Documentation of collectd's C<Lua plugin>
+
+=head1 SYNOPSIS
+
+ LoadPlugin lua
+ # ...
+ <Plugin lua>
+ BasePath "/path/to/your/lua/scripts"
+ Script "script1.lua"
+ Script "script2.lua"
+ </Plugin>
+
+=head1 DESCRIPTION
+
+The C<Lua plugin> embeds a Lua interpreter into collectd and provides an
+interface to collectd's plugin system. This makes it possible to write plugins
+for collectd in Lua. This is a lot more efficient than executing a
+Lua script every time you want to read a value with the C<exec plugin> (see
+L<collectd-exec(5)>) and provides a lot more functionality, too.
+
+The minimum required Lua version is I<5.1>.
+
+=head1 CONFIGURATION
+
+=over 4
+
+=item B<LoadPlugin> I<Lua>
+
+Loads the Lua plugin.
+
+=item B<BasePath> I<Name>
+
+The directory the C<Lua plugin> looks in to find script B<Script>.
+If set, this is also prepended to B<package.path>.
+
+=item B<Script> I<Name>
+
+The script the C<Lua plugin> is going to run.
+If B<BasePath> is not specified, this needs to be an absolute path.
+
+=back
+
+=head1 WRITING YOUR OWN PLUGINS
+
+Writing your own plugins is quite simple. collectd manages plugins by means of
+B<dispatch functions> which call the appropriate B<callback functions>
+registered by the plugins. Any plugin basically consists of the implementation
+of these callback functions and initializing code which registers the
+functions with collectd. See the section "EXAMPLES" below for a really basic
+example. The following types of B<callback functions> are implemented in the
+Lua plugin (all of them are optional):
+
+=over 4
+
+=item read functions
+
+These are used to collect the actual data. It is called once
+per interval (see the B<Interval> configuration option of collectd). Usually
+it will call B<collectd.dispatch_values> to dispatch the values to collectd
+which will pass them on to all registered B<write functions>. If this function
+does not return 0 the plugin will be skipped for an increasing
+amount of time until it returns normally again.
+
+=item write functions
+
+These are used to write the dispatched values. They are called
+once for every value that was dispatched by any plugin.
+
+=back
+
+=head1 FUNCTIONS
+
+The following functions are provided to Lua modules:
+
+=over 4
+
+=item register_read(callback)
+
+The callback will be called without arguments.
+If this callback function does not return 0 the next call will be delayed by
+an increasing interval.
+
+=item register_write
+
+The callback function will be called with one argument passed, which will be a
+table of values.
+If this callback function does not return 0 next call will be delayed by
+an increasing interval.
+
+=item log_error, log_warning, log_notice, log_info, log_debug(I<message>)
+
+Log a message with the specified severity.
+
+=back
+
+=head1 EXAMPLES
+
+=over 4
+
+A very simple read function might look like:
+
+ function read()
+ collectd.log_info("read function called")
+ t = {
+ host = 'localhost',
+ plugin = 'myplugin',
+ type = 'counter',
+ values = {42},
+ }
+ collectd.dispatch_values(t)
+ return 0
+ end
+
+A very simple write function might look like:
+
+ function write(vl)
+ for i = 1, #vl.values do
+ collectd.log_info(vl.host .. '.' .. vl.plugin .. '.' .. vl.type .. ' ' .. vl.values[i])
+ end
+ return 0
+ end
+
+To register those functions with collectd:
+
+ collectd.register_read(read)
+ collectd.register_write(write)
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<lua(1)>,
+
+=head1 AUTHOR
+
+The C<Lua plugin> has been written by
+Julien Ammous E<lt>j.ammous<nbsp>atE<nbsp>gmail.comE<gt>,
+Florian Forster E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt> and
+Ruben Kerkhof E<lt>ruben<nbsp>atE<nbsp>rubenkerkhof.com<gt> and
+
+This manpage has been written by Ruben Kerkhof
+E<lt>ruben<nbsp>atE<nbsp>rubenkerkhof.com<gt>.
+It is based on the L<collectd-perl(5)> manual page by
+Florian Forster E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt> and
+Sebastian Harl E<lt>shE<nbsp>atE<nbsp>tokkee.orgE<gt>.
+
+=cut
diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c
index 8b0f867949e1f09c1b8f015598c8dd08e8d8925c..12187f3070de63fb551929daa93a50a2985d1251 100644 (file)
--- a/src/collectd-nagios.c
+++ b/src/collectd-nagios.c
static _Bool nan_is_error_g = 0;
static char **match_ds_g = NULL;
-static int match_ds_num_g = 0;
+static size_t match_ds_num_g = 0;
/* `strdup' is an XSI extension. I don't want to pull in all of XSI just for
* that, so here's an own implementation.. It's easy enough. The GCC attributes
gauge_t *new_values;
char **new_names;
- size_t i;
-
if (match_ds_g == NULL)
return (RET_OKAY);
new_values = (gauge_t *)calloc (match_ds_num_g, sizeof (*new_values));
if (new_values == NULL)
{
- fprintf (stderr, "malloc failed: %s\n", strerror (errno));
+ fprintf (stderr, "calloc failed: %s\n", strerror (errno));
return (RET_UNKNOWN);
}
new_names = (char **)calloc (match_ds_num_g, sizeof (*new_names));
if (new_names == NULL)
{
- fprintf (stderr, "malloc failed: %s\n", strerror (errno));
+ fprintf (stderr, "calloc failed: %s\n", strerror (errno));
free (new_values);
return (RET_UNKNOWN);
}
- for (i = 0; i < (size_t) match_ds_num_g; i++)
+ for (size_t i = 0; i < match_ds_num_g; i++)
{
size_t j;
}
free (*values);
- for (i = 0; i < *values_num; i++)
+ for (size_t i = 0; i < *values_num; i++)
free ((*values_names)[i]);
free (*values_names);
return (((ret - range->invert) == 0) ? 0 : 1);
} /* int match_range */
+__attribute__((noreturn))
static void usage (const char *name)
{
fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
char *hostname = NULL;
int status;
- size_t i;
status = lcc_listval (connection, &ret_ident, &ret_ident_num);
if (status != 0) {
return (RET_UNKNOWN);
}
- for (i = 0; i < ret_ident_num; ++i) {
+ for (size_t i = 0; i < ret_ident_num; ++i) {
char id[1024];
if ((hostname_g != NULL) && (strcasecmp (hostname_g, ret_ident[i].host)))
int num_okay = 0;
const char *status_str = "UNKNOWN";
int status_code = RET_UNKNOWN;
- size_t i;
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
{
if (isnan (values[i]))
{
if (values_num > 0)
{
printf (" |");
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
printf (" %s=%f;;;;", values_names[i], values[i]);
}
printf ("\n");
static int do_check_con_average (size_t values_num,
double *values, char **values_names)
{
- size_t i;
double total;
int total_num;
double average;
total = 0.0;
total_num = 0;
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
{
if (isnan (values[i]))
{
}
printf ("%s: %g average |", status_str, average);
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
printf (" %s=%f;;;;", values_names[i], values[i]);
printf ("\n");
static int do_check_con_sum (size_t values_num,
double *values, char **values_names)
{
- size_t i;
double total;
int total_num;
const char *status_str = "UNKNOWN";
total = 0.0;
total_num = 0;
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
{
if (isnan (values[i]))
{
}
printf ("%s: %g sum |", status_str, total);
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
printf (" %s=%f;;;;", values_names[i], values[i]);
printf ("\n");
static int do_check_con_percentage (size_t values_num,
double *values, char **values_names)
{
- size_t i;
double sum = 0.0;
double percentage;
return (RET_WARNING);
}
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
{
if (isnan (values[i]))
{
}
printf ("%s: %lf percent |", status_str, percentage);
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
printf (" %s=%lf;;;;", values_names[i], values[i]);
return (status_code);
} /* int do_check_con_percentage */
size_t values_num;
char ident_str[1024];
lcc_identifier_t ident;
- size_t i;
int status;
snprintf (ident_str, sizeof (ident_str), "%s/%s",
hostname_g, value_string_g);
ident_str[sizeof (ident_str) - 1] = 0;
- memset (&ident, 0, sizeof (ident));
status = lcc_string_to_identifier (connection, &ident, ident_str);
if (status != 0)
{
status = RET_UNKNOWN;
if (consolitation_g == CON_NONE)
- status = do_check_con_none (values_num, values, values_names);
+ status = do_check_con_none (values_num, values, values_names);
else if (consolitation_g == CON_AVERAGE)
- status = do_check_con_average (values_num, values, values_names);
+ status = do_check_con_average (values_num, values, values_names);
else if (consolitation_g == CON_SUM)
status = do_check_con_sum (values_num, values, values_names);
else if (consolitation_g == CON_PERCENTAGE)
free (values);
if (values_names != NULL)
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
free (values_names[i]);
free (values_names);
case 'd':
{
char **tmp;
- tmp = (char **) realloc (match_ds_g,
+ tmp = realloc (match_ds_g,
(match_ds_num_g + 1)
* sizeof (char *));
if (tmp == NULL)
index 773a6cd4b7919b1d950794c63b49dc401e43a4c1..16b26afad1af0a820059656fd0d1d10d89d39b35 100644 (file)
--- a/src/collectd-python.pod
+++ b/src/collectd-python.pod
Python-script every time you want to read a value with the C<exec plugin> (see
L<collectd-exec(5)>) and provides a lot more functionality, too.
-The minimum required Python version is I<2.3>.
+The minimum required Python version is I<2.6>.
=head1 CONFIGURATION
=item *
-B<2.> collectd will block I<SIGINT>. Pressing I<Ctrl+C> will usually cause
+B<2.> Python will be handling I<SIGINT>. Pressing I<Ctrl+C> will usually cause
collectd to shut down. This would be problematic in an interactive session,
-therefore this signal will be blocked. You can still use it to interrupt
-syscalls like sleep and pause but it won't generate a I<KeyboardInterrupt>
-exception either.
+therefore Python will be handling it in interactive sessions. This allows you
+to use I<Ctrl+C> to interrupt Python code without killing collectd. This also
+means you can catch I<KeyboardInterrupt> exceptions which does not work during
+normal operation.
To quit collectd send I<EOF> (press I<Ctrl+D> at the beginning of a new line).
A very simple read function might look like:
+ import random
+
def read(data=None):
vl = collectd.Values(type='gauge')
vl.plugin='python.spam'
To register those functions with collectd:
- collectd.register_read(read);
- collectd.register_write(write);
+ collectd.register_read(read)
+ collectd.register_write(write)
See the section L<"CLASSES"> above for a complete documentation of the data
types used by the read, write and match functions.
-=head1 NOTES
-
-=over 4
-
-=item *
-
-Please feel free to send in new plugins to collectd's mailing list at
-E<lt>collectdE<nbsp>atE<nbsp>collectd.orgE<gt> for review and, possibly,
-inclusion in the main distribution. In the latter case, we will take care of
-keeping the plugin up to date and adapting it to new versions of collectd.
-
-Before submitting your plugin, please take a look at
-L<http://collectd.org/dev-info.shtml>.
-
-=back
-
=head1 CAVEATS
=over 4
diff --git a/src/collectd-tg.c b/src/collectd-tg.c
index 71814a2955357a9a07df0390be43152c9e659060..273265c338e32ac88833a15a8e758c8529b54607 100644 (file)
--- a/src/collectd-tg.c
+++ b/src/collectd-tg.c
#include <time.h>
#include <signal.h>
#include <errno.h>
+#include <math.h>
+#include <sys/time.h>
#include "utils_heap.h"
#include "libcollectdclient/collectd/client.h"
#include "libcollectdclient/collectd/network.h"
-#include "libcollectdclient/collectd/network_buffer.h"
#define DEF_NUM_HOSTS 1000
#define DEF_NUM_PLUGINS 20
loop = 0;
} /* }}} void signal_handler */
+#if HAVE_CLOCK_GETTIME
+static double dtime (void) /* {{{ */
+{
+ struct timespec ts = { 0 };
+
+ if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0)
+ perror ("clock_gettime");
+
+ return ((double) ts.tv_sec) + (((double) ts.tv_nsec) / 1e9);
+} /* }}} double dtime */
+#else
+/* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
+static double dtime (void) /* {{{ */
+{
+ struct timeval tv = { 0 };
+
+ if (gettimeofday (&tv, /* timezone = */ NULL) != 0)
+ perror ("gettimeofday");
+
+ return ((double) tv.tv_sec) + (((double) tv.tv_usec) / 1e6);
+} /* }}} double dtime */
+#endif
+
static int compare_time (const void *v0, const void *v1) /* {{{ */
{
const lcc_value_list_t *vl0 = v0;
lcc_value_list_t *vl;
int host_num;
- vl = malloc (sizeof (*vl));
+ vl = calloc (1, sizeof (*vl));
if (vl == NULL)
{
- fprintf (stderr, "malloc failed.\n");
+ fprintf (stderr, "calloc failed.\n");
return (NULL);
}
- memset (vl, 0, sizeof (*vl));
vl->values = calloc (/* nmemb = */ 1, sizeof (*vl->values));
if (vl->values == NULL)
host_num = get_boundet_random (0, conf_num_hosts);
vl->interval = conf_interval;
- vl->time = 1.0 + time (NULL)
+ vl->time = 1.0 + dtime ()
+ (host_num % (1 + (int) vl->interval));
if (get_boundet_random (0, 2) == 0)
if (vl->values_types[0] == LCC_TYPE_GAUGE)
vl->values[0].gauge = 100.0 * ((gauge_t) random ()) / (((gauge_t) RAND_MAX) + 1.0);
else
- vl->values[0].derive += get_boundet_random (0, 100);
+ vl->values[0].derive += (derive_t) get_boundet_random (0, 100);
status = lcc_network_values_send (net, vl);
if (status != 0)
int main (int argc, char **argv) /* {{{ */
{
- int i;
- time_t last_time;
+ double last_time;
int values_sent = 0;
read_options (argc, argv);
else
{
lcc_server_t *srv;
-
+
srv = lcc_server_create (net, conf_destination, conf_service);
if (srv == NULL)
{
fprintf (stdout, "Creating %i values ... ", conf_num_values);
fflush (stdout);
- for (i = 0; i < conf_num_values; i++)
+ for (int i = 0; i < conf_num_values; i++)
{
lcc_value_list_t *vl;
printf ("%i values have been sent.\n", values_sent);
/* Check if we need to sleep */
- time_t now = time (NULL);
+ double now = dtime ();
while (now < vl->time)
{
- /* 1 / 100 second */
- struct timespec ts = { 0, 10000000 };
+ double diff = vl->time - now;
+ struct timespec ts = {
+ .tv_sec = (time_t) diff,
+ };
+ ts.tv_nsec = (long) ((diff - ((double) ts.tv_sec)) * 1e9);
+
nanosleep (&ts, /* remaining = */ NULL);
- now = time (NULL);
+ now = dtime ();
if (!loop)
break;
lcc_network_destroy (net);
exit (EXIT_SUCCESS);
- return (0);
} /* }}} int main */
/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index eb335d81638429f9c602bd53f2db14df1042190d..f0ac28713b1f30195df8e20683b314dec92402c9 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
#@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
#@BUILD_PLUGIN_CEPH_TRUE@LoadPlugin ceph
#@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
+#@BUILD_PLUGIN_CHRONY_TRUE@LoadPlugin chrony
#@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
#@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
@BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
#@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
+#@BUILD_PLUGIN_CPUSLEEP_TRUE@LoadPlugin cpusleep
@LOAD_PLUGIN_CSV@LoadPlugin csv
#@BUILD_PLUGIN_CURL_TRUE@LoadPlugin curl
#@BUILD_PLUGIN_CURL_JSON_TRUE@LoadPlugin curl_json
#@BUILD_PLUGIN_FILECOUNT_TRUE@LoadPlugin filecount
#@BUILD_PLUGIN_FSCACHE_TRUE@LoadPlugin fscache
#@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond
+#@BUILD_PLUGIN_GPS_TRUE@LoadPlugin gps
+#@BUILD_PLUGIN_GRPC_TRUE@LoadPlugin grpc
#@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
#@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
#@BUILD_PLUGIN_JAVA_TRUE@LoadPlugin java
@BUILD_PLUGIN_LOAD_TRUE@@BUILD_PLUGIN_LOAD_TRUE@LoadPlugin load
#@BUILD_PLUGIN_LPAR_TRUE@LoadPlugin lpar
+#@BUILD_PLUGIN_LUA_TRUE@LoadPlugin lua
#@BUILD_PLUGIN_LVM_TRUE@LoadPlugin lvm
#@BUILD_PLUGIN_MADWIFI_TRUE@LoadPlugin madwifi
#@BUILD_PLUGIN_MBMON_TRUE@LoadPlugin mbmon
@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_PLUGIN_MEMORY_TRUE@LoadPlugin memory
#@BUILD_PLUGIN_MIC_TRUE@LoadPlugin mic
#@BUILD_PLUGIN_MODBUS_TRUE@LoadPlugin modbus
+#@BUILD_PLUGIN_MQTT_TRUE@LoadPlugin mqtt
#@BUILD_PLUGIN_MULTIMETER_TRUE@LoadPlugin multimeter
#@BUILD_PLUGIN_MYSQL_TRUE@LoadPlugin mysql
#@BUILD_PLUGIN_NETAPP_TRUE@LoadPlugin netapp
#@BUILD_PLUGIN_NGINX_TRUE@LoadPlugin nginx
#@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@LoadPlugin notify_desktop
#@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
+#@BUILD_PLUGIN_NOTIFY_NAGIOS_TRUE@LoadPlugin notify_nagios
#@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
#@BUILD_PLUGIN_NUMA_TRUE@LoadPlugin numa
#@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
#@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@LoadPlugin write_riemann
#@BUILD_PLUGIN_WRITE_SENSU_TRUE@LoadPlugin write_sensu
#@BUILD_PLUGIN_WRITE_TSDB_TRUE@LoadPlugin write_tsdb
+#@BUILD_PLUGIN_XENCPU_TRUE@LoadPlugin xencpu
#@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
#@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
+#@BUILD_PLUGIN_ZONE_TRUE@LoadPlugin zone
#@BUILD_PLUGIN_ZOOKEEPER_TRUE@LoadPlugin zookeeper
##############################################################################
# Host "localhost"
# Port "3551"
# ReportSeconds true
+# PersistentConnection true
#</Plugin>
#<Plugin aquaero>
# </Daemon>
#</Plugin>
+#<Plugin chrony>
+# Host "localhost"
+# Port "323"
+# Timeout "2"
+#</Plugin>
+
#<Plugin cgroups>
# CGroup "libvirt"
# IgnoreSelected false
# </Metric>
#</Plugin>
+#<Plugin gps>
+# Host "127.0.0.1"
+# Port "2947"
+# Timeout 0.015
+# PauseConnect 5
+#</Plugin>
+
+#<Plugin grpc>
+# <Server "example.com" "50051">
+# EnableSSL true
+# SSLCACertificateFile "/path/to/root.pem"
+# SSLCertificateFile "/path/to/server.pem"
+# SSLCertificateKeyFile "/path/to/server.key"
+# </Server>
+# <Listen "0.0.0.0" "50051">
+# EnableSSL true
+# SSLCACertificateFile "/path/to/root.pem"
+# SSLCertificateFile "/path/to/client.pem"
+# SSLCertificateKeyFile "/path/to/client.key"
+# </Listen>
+#</Plugin>
+
#<Plugin hddtemp>
# Host "127.0.0.1"
# Port "7634"
#<Plugin interface>
# Interface "eth0"
# IgnoreSelected false
+# ReportInactive true
+# UniqueName false
#</Plugin>
#<Plugin ipmi>
# ReportBySerial false
#</Plugin>
+#<Plugin lua>
+# BasePath "@prefix@/share/@PACKAGE_NAME@/lua"
+# Script "script1.lua"
+# Script "script2.lua"
+#</Plugin>
+
#<Plugin madwifi>
# Interface "wlan0"
# IgnoreSelected false
# </Host>
#</Plugin>
+#<Plugin mqtt>
+# <Publish "name">
+# Host "localhost"
+# Port 1883
+# ClientId "localhost"
+# User "user"
+# Password "secret"
+# QoS 0
+# Prefix "collectd"
+# StoreRates true
+# Retain false
+# CACert "/etc/ssl/ca.crt"
+# CertificateFile "/etc/ssl/client.crt"
+# CertificateKeyFile "/etc/ssl/client.pem"
+# TLSProtocol "tlsv1.2"
+# CipherSuite "ciphers"
+# </Publish>
+# <Subscribe "name">
+# Host "localhost"
+# Port 1883
+# ClientId "localhost"
+# User "user"
+# Password "secret"
+# QoS 2
+# Topic "collectd/#"
+# CleanSession true
+# </Subscribe>
+#</Plugin>
+
#<Plugin mysql>
# <Database db_name>
# Host "database.serv.er"
# User "db_user"
# Password "secret"
# Database "db_name"
+# SSLKey "/path/to/key.pem"
+# SSLCert "/path/to/cert.pem"
+# SSLCA "/path/to/ca.pem"
+# SSLCAPath "/path/to/cas/"
+# SSLCipher "DHE-RSA-AES256-SHA"
# MasterStats true
# ConnectTimeout 10
# InnodbStats true
# SlaveStats true
# SlaveNotifications true
# </Database>
+# <Database galera>
+# Alias "galera"
+# Host "localhost"
+# Socket "/var/run/mysql/mysqld.sock"
+# WsrepStats true
+# </Database>
#</Plugin>
#<Plugin netapp>
# Recipient "email2@domain2.com"
#</Plugin>
+#<Plugin notify_nagios>
+# CommandFile "/usr/local/nagios/var/rw/nagios.cmd"
+#</Plugin>
+
#<Plugin ntpd>
# Host "localhost"
# Port 123
# DeleteTimers false
# DeleteGauges false
# DeleteSets false
+# CounterSum false
# TimerPercentile 90.0
# TimerPercentile 95.0
# TimerPercentile 99.0
## None of the following option should be set manually
## This plugin automatically detect most optimal options
## Only set values here if:
-## - The module ask you to
+## - The module asks you to
## - You want to disable the collection of some data
-## - Your (intel) CPU is not supported (yet) by the module
-## - The module generate a lot of errors 'MSR offset 0x... read failed'
+## - Your (Intel) CPU is not supported (yet) by the module
+## - The module generates a lot of errors 'MSR offset 0x... read failed'
## In the last two cases, please open a bug request
#
# TCCActivationTemp "100"
# Host "localhost"
# Port "2003"
# Protocol "tcp"
+# ReconnectInterval 0
# LogSendErrors true
# Prefix "collectd"
# Postfix "collectd"
# ClientKey "/etc/ssl/client.pem"
# ClientCert "/etc/ssl/client.crt"
# ClientKeyPass "secret"
+# Header "X-Custom-Header: custom_value"
# SSLVersion "TLSv1"
# Format "Command"
+# Metrics true
+# Notifications false
# StoreRates false
# BufferSize 4096
# LowSpeedLimit 0
# Host "localhost"
# Port "6379"
# Timeout 1000
+# Prefix "collectd/"
# </Node>
#</Plugin>
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index e476c48f1127533839d4cccbbc19c15ecf16245b..9c97137ce8b9121f0536efb3cef1d335aafac189 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
The syntax of this config file is similar to the config file of the famous
I<Apache> webserver. Each line contains either an option (a key and a list of
one or more values) or a section-start or -end. Empty lines and everything
-after a non-quoted hash-symbol (C<#>) is ignored. I<Keys> are unquoted
+after a non-quoted hash-symbol (C<#>) are ignored. I<Keys> are unquoted
strings, consisting only of alphanumeric characters and the underscore (C<_>)
character. Keys are handled case insensitive by I<collectd> itself and all
plugins included with it. I<Values> can either be an I<unquoted string>, a
=item B<BaseDir> I<Directory>
-Sets the base directory. This is the directory beneath all RRD-files are
+Sets the base directory. This is the directory beneath which all RRD-files are
created. Possibly more subdirectories are created. This is also the working
directory for the daemon.
Only the first B<LoadPlugin> statement or block for a given plugin name has any
effect. This is useful when you want to split up the configuration into smaller
files and want each file to be "self contained", i.e. it contains a B<Plugin>
-block I<and> then appropriate B<LoadPlugin> statement. The downside is that if
+block I<and> the appropriate B<LoadPlugin> statement. The downside is that if
you have multiple conflicting B<LoadPlugin> blocks, e.g. when they specify
different intervals, only one of them (the first one encountered) will take
effect and all others will be silently ignored.
=item B<Interval> I<Seconds>
Sets a plugin-specific interval for collecting metrics. This overrides the
-global B<Interval> setting. If a plugin provides own support for specifying an
-interval, that setting will take precedence.
+global B<Interval> setting. If a plugin provides its own support for specifying
+an interval, that setting will take precedence.
+
+=item B<FlushInterval> I<Seconds>
+
+Specifies the interval, in seconds, to call the flush callback if it's
+defined in this plugin. By default, this is disabled.
+
+=item B<FlushTimeout> I<Seconds>
+
+Specifies the value of the timeout argument of the flush callback.
=back
=back
-If more than one files are included by a single B<Include> option, the files
+If more than one file is included by a single B<Include> option, the files
will be included in lexicographical order (as defined by the C<strcmp>
function). Thus, you can e.E<nbsp>g. use numbered prefixes to specify the
order in which the files are loaded.
=item B<MaxReadInterval> I<Seconds>
-Read plugin doubles interval between queries after each failed attempt
+A read plugin doubles the interval between queries after each failed attempt
to get data.
This options limits the maximum value of the interval. The default value is
The I<AMQP plugin> can be used to communicate with other instances of
I<collectd> or third party applications using an AMQP message broker. Values
are sent to or received from the broker, which handles routing, queueing and
-possibly filtering or messages.
+possibly filtering out messages.
+
+B<Synopsis:>
<Plugin "amqp">
# Send values to an AMQP broker
TCP-Port to connect to. Defaults to B<3551>.
-=item B<ReportSeconds> B<true|false>
+=item B<ReportSeconds> B<true>|B<false>
If set to B<true>, the time reported in the C<timeleft> metric will be
converted to seconds. This is the recommended setting. If set to B<false>, the
default for backwards compatibility, the time will be reported in minutes.
+=item B<PersistentConnection> B<true>|B<false>
+
+The plugin is designed to keep the connection to I<apcupsd> open between reads.
+If plugin poll interval is greater than 15 seconds (hardcoded socket close
+timeout in I<apcupsd> NIS), then this option is B<false> by default.
+
+You can instruct the plugin to close the connection after each read by setting
+this option to B<false> or force keeping the connection by setting it to B<true>.
+
+If I<apcupsd> appears to close the connection due to inactivity quite quickly,
+the plugin will try to detect this problem and switch to an open-read-close mode.
+
=back
=head2 Plugin C<aquaero>
=back
+=head2 Plugin C<chrony>
+
+The C<chrony> plugin collects ntp data from a B<chronyd> server, such as clock
+skew and per-peer stratum.
+
+For talking to B<chronyd>, it mimics what the B<chronyc> control program does
+on the wire.
+
+Available configuration options for the C<chrony> plugin:
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the host running B<chronyd>. Defaults to B<localhost>.
+
+=item B<Port> I<Port>
+
+UDP-Port to connect to. Defaults to B<323>.
+
+=item B<Timeout> I<Timeout>
+
+Connection timeout in seconds. Defaults to B<2>.
+
+=back
+
=head2 Plugin C<conntrack>
This plugin collects IP conntrack statistics.
Jiffies. By setting this option to B<true>, you can request percentage values
in the un-aggregated (per-CPU, per-state) mode as well.
+=item B<ReportNumCpu> B<false>|B<true>
+
+When set to B<true>, reports the number of available CPUs.
+Defaults to B<false>.
+
=back
=head2 Plugin C<cpufreq>
@@ -1414,6 +1468,16 @@ installed) to get the current CPU frequency. If this file does not exist make
sure B<cpufreqd> (L<http://cpufreqd.sourceforge.net/>) or a similar tool is
installed and an "cpu governor" (that's a kernel module) is loaded.
+=head2 Plugin C<cpusleep>
+
+This plugin doesn't have any options. It reads CLOCK_BOOTTIME and
+CLOCK_MONOTONIC and reports the difference between these clocks. Since
+BOOTTIME clock increments while device is suspended and MONOTONIC
+clock does not, the derivative of the difference between these clocks
+gives the relative amount of time the device has spent in suspend
+state. The recorded value is in milliseconds of sleep per seconds of
+wall clock.
+
=head2 Plugin C<csv>
=over 4
=back
+=head2 cURL Statistics
+
+All cURL-based plugins support collection of generic, request-based
+statistics. These are disabled by default and can be enabled selectively for
+each page or URL queried from the curl, curl_json, or curl_xml plugins. See
+the documentation of those plugins for specific information. This section
+describes the available metrics that can be configured for each plugin. All
+options are disabled by default.
+
+See L<http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html> for more details.
+
+=over 4
+
+=item B<TotalTime> B<true|false>
+
+Total time of the transfer, including name resolving, TCP connect, etc.
+
+=item B<NamelookupTime> B<true|false>
+
+Time it took from the start until name resolving was completed.
+
+=item B<ConnectTime> B<true|false>
+
+Time it took from the start until the connect to the remote host (or proxy)
+was completed.
+
+=item B<AppconnectTime> B<true|false>
+
+Time it took from the start until the SSL/SSH connect/handshake to the remote
+host was completed.
+
+=item B<PretransferTime> B<true|false>
+
+Time it took from the start until just before the transfer begins.
+
+=item B<StarttransferTime> B<true|false>
+
+Time it took from the start until the first byte was received.
+
+=item B<RedirectTime> B<true|false>
+
+Time it took for all redirection steps include name lookup, connect,
+pre-transfer and transfer before final transaction was started.
+
+=item B<RedirectCount> B<true|false>
+
+The total number of redirections that were actually followed.
+
+=item B<SizeUpload> B<true|false>
+
+The total amount of bytes that were uploaded.
+
+=item B<SizeDownload> B<true|false>
+
+The total amount of bytes that were downloaded.
+
+=item B<SpeedDownload> B<true|false>
+
+The average download speed that curl measured for the complete download.
+
+=item B<SpeedUpload> B<true|false>
+
+The average upload speed that curl measured for the complete upload.
+
+=item B<HeaderSize> B<true|false>
+
+The total size of all the headers received.
+
+=item B<RequestSize> B<true|false>
+
+The total size of the issued requests.
+
+=item B<ContentLengthDownload> B<true|false>
+
+The content-length of the download.
+
+=item B<ContentLengthUpload> B<true|false>
+
+The specified size of the upload.
+
+=item B<NumConnects> B<true|false>
+
+The number of new connections that were created to achieve the transfer.
+
+=back
+
=head2 Plugin C<curl>
The curl plugin uses the B<libcurl> (L<http://curl.haxx.se/>) to read web pages
@@ -1534,11 +1684,21 @@ Beware that requests will get aborted if they take too long to complete. Adjust
B<Timeout> accordingly if you expect B<MeasureResponseTime> to report such slow
requests.
+This option is similar to enabling the B<TotalTime> statistic but it's
+measured by collectd instead of cURL.
+
=item B<MeasureResponseCode> B<true>|B<false>
Measure response code for the request. If this setting is enabled, B<Match>
blocks (see below) are optional. Disabled by default.
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote web site. See the section "cURL Statistics"
+above for details. If this setting is enabled, B<Match> blocks (see below) are
+optional.
+
=item B<E<lt>MatchE<gt>>
One or more B<Match> blocks that define how to match information in the data
=over 4
+=item B<Host> I<Name>
+
+Use I<Name> as the host name when submitting values. Defaults to the global
+host name setting.
+
=item B<Instance> I<Instance>
Sets the plugin instance to I<Instance>.
These options behave exactly equivalent to the appropriate options of the
I<cURL> plugin. Please see there for a detailed description.
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote URL. See the section "cURL Statistics" above
+for details.
+
=back
The following options are valid within B<Key> blocks:
These options behave exactly equivalent to the appropriate options of the
I<cURL plugin>. Please see there for a detailed description.
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote URL. See the section "cURL Statistics" above
+for details.
+
=item E<lt>B<XPath> I<XPath-expression>E<gt>
Within each B<URL> block, there must be one or more B<XPath> blocks. Each
</Query>
<Database "product_information">
Driver "mysql"
+ Interval 120
DriverOption "host" "localhost"
DriverOption "username" "collectd"
DriverOption "password" "aZo6daiw"
=over 4
+=item B<Interval> I<Interval>
+
+Sets the interval (in seconds) in which the values will be collected from this
+database. By default the global B<Interval> setting will be used.
+
=item B<Driver> I<Driver>
Specifies the driver to use to connect to the database. In many cases those
=item B<MappedOnly> B<true>|B<false>
-When set to B<true>, only metrics that can be mapped to to a I<type> will be
+When set to B<true>, only metrics that can be mapped to a I<type> will be
collected, all other metrics will be ignored. Defaults to B<false>.
=back
=back
+=head2 Plugin C<gps>
+
+The C<gps plugin> connects to gpsd on the host machine.
+The host, port, timeout and pause are configurable.
+
+This is useful if you run an NTP server using a GPS for source and you want to
+monitor it.
+
+Mind your GPS must send $--GSA for having the data reported!
+
+The following elements are collected:
+
+=over 4
+
+=item B<satellites>
+
+Number of satellites used for fix (type instance "used") and in view (type
+instance "visible"). 0 means no GPS satellites are visible.
+
+=item B<dilution_of_precision>
+
+Vertical and horizontal dilution (type instance "horizontal" or "vertical").
+It should be between 0 and 3.
+Look at the documentation of your GPS to know more.
+
+=back
+
+Synopsis:
+
+ LoadPlugin gps
+ <Plugin "gps">
+ # Connect to localhost on gpsd regular port:
+ Host "127.0.0.1"
+ Port "2947"
+ # 15 ms timeout
+ Timeout 0.015
+ # PauseConnect of 5 sec. between connection attempts.
+ PauseConnect 5
+ </Plugin>
+
+Available configuration options:
+
+=over 4
+
+=item B<Host> I<Host>
+
+The host on which gpsd daemon runs. Defaults to B<localhost>.
+
+=item B<Port> I<Port>
+
+Port to connect to gpsd on the host machine. Defaults to B<2947>.
+
+=item B<Timeout> I<Seconds>
+
+Timeout in seconds (default 0.015 sec).
+
+The GPS data stream is fetch by the plugin form the daemon.
+It waits for data to be available, if none arrives it times out
+and loop for another reading.
+Mind to put a low value gpsd expects value in the micro-seconds area
+(recommended is 500 us) since the waiting function is blocking.
+Value must be between 500 us and 5 sec., if outside that range the
+default value is applied.
+
+This only applies from gpsd release-2.95.
+
+=item B<PauseConnect> I<Seconds>
+
+Pause to apply between attempts of connection to gpsd in seconds (default 5 sec).
+
+=back
+
+=head2 Plugin C<grpc>
+
+The I<grpc> plugin provides an RPC interface to submit values to or query
+values from collectd based on the open source gRPC framework. It exposes an
+end-point for dispatching values to the daemon.
+
+The B<gRPC> homepage can be found at L<https://grpc.io/>.
+
+=over 4
+
+=item B<Server> I<Host> I<Port>
+
+The B<Server> statement sets the address of a server to which to send metrics
+via the C<DispatchValues> function.
+
+The argument I<Host> may be a hostname, an IPv4 address, or an IPv6 address.
+
+Optionally, B<Server> may be specified as a configuration block which supports
+the following options:
+
+=over 4
+
+=item B<EnableSSL> B<false>|B<true>
+
+Whether to require SSL for outgoing connections. Default: false.
+
+=item B<SSLCACertificateFile> I<Filename>
+
+=item B<SSLCertificateFile> I<Filename>
+
+=item B<SSLCertificateKeyFile> I<Filename>
+
+Filenames specifying SSL certificate and key material to be used with SSL
+connections.
+
+=back
+
+=item B<Listen> I<Host> I<Port>
+
+The B<Listen> statement sets the network address to bind to. When multiple
+statements are specified, the daemon will bind to all of them. If none are
+specified, it defaults to B<0.0.0.0:50051>.
+
+The argument I<Host> may be a hostname, an IPv4 address, or an IPv6 address.
+
+Optionally, B<Listen> may be specified as a configuration block which
+supports the following options:
+
+=over 4
+
+=item B<EnableSSL> I<true>|I<false>
+
+Whether to enable SSL for incoming connections. Default: false.
+
+=item B<SSLCACertificateFile> I<Filename>
+
+=item B<SSLCertificateFile> I<Filename>
+
+=item B<SSLCertificateKeyFile> I<Filename>
+
+Filenames specifying SSL certificate and key material to be used with SSL
+connections.
+
+=back
+
+=back
+
=head2 Plugin C<hddtemp>
To get values from B<hddtemp> collectd connects to B<localhost> (127.0.0.1),
with I<veth> and all interfaces with names starting with I<tun> followed by
at least one digit.
+=item B<ReportInactive> I<true>|I<false>
+
+When set to I<false>, only interfaces with non-zero traffic will be
+reported. Note that the check is done by looking into whether a
+package was sent at any time from boot and the corresponding counter
+is non-zero. So, if the interface has been sending data in the past
+since boot, but not during the reported time-interval, it will still
+be reported.
+
+The default value is I<true> and results in collection of the data
+from all interfaces that are selected by B<Interface> and
+B<IgnoreSelected> options.
+
+=item B<UniqueName> I<true>|I<false>
+
+Interface name is not unique on Solaris (KSTAT), interface name is unique
+only within a module/instance. Following tuple is considered unique:
+ (ks_module, ks_instance, ks_name)
+If this option is set to true, interface name contains above three fields
+separated by an underscore. For more info on KSTAT, visit
+L<http://docs.oracle.com/cd/E23824_01/html/821-1468/kstat-3kstat.html#REFMAN3Ekstat-3kstat>
+
+This option is only available on Solaris.
=back
=back
+=head2 Plugin C<lua>
+
+This plugin embeds a Lua interpreter into collectd and provides an interface
+to collectd's plugin system. See L<collectd-lua(5)> for its documentation.
+
+
=head2 Plugin C<mbmon>
The C<mbmon plugin> uses mbmon to retrieve temperature, voltage, etc.
=back
+=back
+
+=head2 Plugin C<mqtt>
+
+The I<MQTT plugin> can send metrics to MQTT (B<Publish> blocks) and receive
+values from MQTT (B<Subscribe> blocks).
+
+B<Synopsis:>
+
+ <Plugin mqtt>
+ <Publish "name">
+ Host "mqtt.example.com"
+ Prefix "collectd"
+ </Publish>
+ <Subscribe "name">
+ Host "mqtt.example.com"
+ Topic "collectd/#"
+ </Subscribe>
+ </Plugin>
+
+The plugin's configuration is in B<Publish> and/or B<Subscribe> blocks,
+configuring the sending and receiving direction respectively. The plugin will
+register a write callback named C<mqtt/I<name>> where I<name> is the string
+argument given to the B<Publish> block. Both types of blocks share many but not
+all of the following options. If an option is valid in only one of the blocks,
+it will be mentioned explicitly.
+
+B<Options:>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the MQTT broker to connect to.
+
+=item B<Port> I<Service>
+
+Port number or service name of the MQTT broker to connect to.
+
+=item B<User> I<UserName>
+
+Username used when authenticating to the MQTT broker.
+
+=item B<Password> I<Password>
+
+Password used when authenticating to the MQTT broker.
+
+=item B<ClientId> I<ClientId>
+
+MQTT client ID to use. Defaults to the hostname used by I<collectd>.
+
+=item B<QoS> [B<0>-B<2>]
+
+Sets the I<Quality of Service>, with the values C<0>, C<1> and C<2> meaning:
+
+=over 4
+
+=item B<0>
+
+At most once
+
+=item B<1>
+
+At least once
+
+=item B<2>
+
+Exactly once
+
+=back
+
+In B<Publish> blocks, this option determines the QoS flag set on outgoing
+messages and defaults to B<0>. In B<Subscribe> blocks, determines the maximum
+QoS setting the client is going to accept and defaults to B<2>. If the QoS flag
+on a message is larger than the maximum accepted QoS of a subscriber, the
+message's QoS will be downgraded.
+
+=item B<Prefix> I<Prefix> (Publish only)
+
+This plugin will use one topic per I<value list> which will looks like a path.
+I<Prefix> is used as the first path element and defaults to B<collectd>.
+
+An example topic name would be:
+
+ collectd/cpu-0/cpu-user
+
+=item B<Retain> B<false>|B<true> (Publish only)
+
+Controls whether the MQTT broker will retain (keep a copy of) the last message
+sent to each topic and deliver it to new subscribers. Defaults to B<false>.
+
+=item B<StoreRates> B<true>|B<false> (Publish only)
+
+Controls whether C<DERIVE> and C<COUNTER> metrics are converted to a I<rate>
+before sending. Defaults to B<true>.
+
+=item B<CleanSession> B<true>|B<false> (Subscribe only)
+
+Controls whether the MQTT "cleans" the session up after the subscriber
+disconnects or if it maintains the subscriber's subscriptions and all messages
+that arrive while the subscriber is disconnected. Defaults to B<true>.
+
+=item B<Topic> I<TopicName> (Subscribe only)
+
+Configures the topic(s) to subscribe to. You can use the single level C<+> and
+multi level C<#> wildcards. Defaults to B<collectd/#>, i.e. all topics beneath
+the B<collectd> branch.
+
+=item B<CACert> I<file>
+
+Path to the PEM-encoded CA certificate file. Setting this option enables TLS
+communication with the MQTT broker, and as such, B<Port> should be the TLS-enabled
+port of the MQTT broker.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<CertificateFile> I<file>
+
+Path to the PEM-encoded certificate file to use as client certificate when
+connecting to the MQTT broker.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<CertificateKeyFile> I<file>
+
+Path to the unencrypted PEM-encoded key file corresponding to B<CertificateFile>.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<TLSProtocol> I<protocol>
+
+If configured, this specifies the string protocol version (e.g. C<tlsv1>,
+C<tlsv1.2>) to use for the TLS connection to the broker. If not set a default
+version is used which depends on the version of OpenSSL the Mosquitto library
+was linked against.
+
+=item B<CipherSuite> I<ciphersuite>
+
+A string describing the ciphers available for use. See L<ciphers(1)> and the
+C<openssl ciphers> utility for more information. If unset, the default ciphers
+will be used.
+
+
=back
=head2 Plugin C<mysql>
Port "3306"
MasterStats true
ConnectTimeout 10
+ SSLKey "/path/to/key.pem"
+ SSLCert "/path/to/cert.pem"
+ SSLCA "/path/to/ca.pem"
+ SSLCAPath "/path/to/cas/"
+ SSLCipher "DHE-RSA-AES256-SHA"
</Database>
<Database bar>
SlaveStats true
SlaveNotifications true
</Database>
+
+ <Database galera>
+ Alias "galera"
+ Host "localhost"
+ Socket "/var/run/mysql/mysqld.sock"
+ WsrepStats true
+ </Database>
</Plugin>
A B<Database> block defines one connection to a MySQL database. It accepts a
single argument which specifies the name of the database. None of the other
options are required. MySQL will use default values as documented in the
-section "mysql_real_connect()" in the B<MySQL reference manual>.
+"mysql_real_connect()" and "mysql_ssl_set()" sections in the
+B<MySQL reference manual>.
=over 4
If enabled, the plugin sends a notification if the replication slave I/O and /
or SQL threads are not running. Defaults to B<false>.
+=item B<WsrepStats> I<true|false>
+
+ Enable the collection of wsrep plugin statistics, used in Master-Master
+ replication setups like in MySQL Galera/Percona XtraDB Cluster.
+ User needs only privileges to execute 'SHOW GLOBAL STATUS'
+
=item B<ConnectTimeout> I<Seconds>
Sets the connect timeout for the MySQL client.
+=item B<SSLKey> I<Path>
+
+If provided, the X509 key in PEM format.
+
+=item B<SSLCert> I<Path>
+
+If provided, the X509 cert in PEM format.
+
+=item B<SSLCA> I<Path>
+
+If provided, the CA file in PEM format (check OpenSSL docs).
+
+=item B<SSLCAPath> I<Path>
+
+If provided, the CA directory (check OpenSSL docs).
+
+=item B<SSLCipher> I<String>
+
+If provided, the SSL cipher to use.
+
=back
=head2 Plugin C<netapp>
=back
+=head2 Plugin C<notify_nagios>
+
+The I<notify_nagios> plugin writes notifications to Nagios' I<command file> as
+a I<passive service check result>.
+
+Available configuration options:
+
+=over 4
+
+=item B<CommandFile> I<Path>
+
+Sets the I<command file> to write to. Defaults to F</usr/local/nagios/var/rw/nagios.cmd>.
+
+=back
+
=head2 Plugin C<ntpd>
The C<ntpd> plugin collects per-peer ntp data such as time offset and time
Sets the URL to use to connect to the I<OpenLDAP> server. This option is
I<mandatory>.
+=item B<BindDN> I<BindDN>
+
+Name in the form of an LDAP distinguished name intended to be used for
+authentication. Defaults to empty string to establish an anonymous authorization.
+
+=item B<Password> I<Password>
+
+Password for simple bind authentication. If this option is not set,
+unauthenticated bind operation is used.
+
=item B<StartTLS> B<true|false>
Defines whether TLS must be used when connecting to the I<OpenLDAP> server.
=item B<Timeout> I<Seconds>
-Sets the timeout value for ldap operations. Defaults to B<-1> which results in
-an infinite timeout.
+Sets the timeout value for ldap operations, in seconds. By default, the
+configured B<Interval> is used to set the timeout. Use B<-1> to disable
+(infinite timeout).
=item B<Version> I<Version>
Sets the Time-To-Live of generated ICMP packets.
+=item B<Size> I<size>
+
+Sets the size of the data payload in ICMP packet to specified I<size> (it
+will be filled with regular ASCII pattern). If not set, default 56 byte
+long string is used so that the packet size of an ICMPv4 packet is exactly
+64 bytes, similar to the behaviour of normal ping(1) command.
+
=item B<SourceAddress> I<host>
Sets the source address to use. I<host> may either be a numerical network
database definition. It accepts a single mandatory argument which specifies
the name of the query. The names of all queries have to be unique (see the
B<MinVersion> and B<MaxVersion> options below for an exception to this
-rule). The following configuration options are available to define the query:
+rule).
-In each B<Query> block, there is one or more B<Result> blocks. B<Result>
-blocks define how to handle the values returned from the query. They define
-which column holds which value and how to dispatch that value to the daemon.
-Multiple B<Result> blocks may be used to extract multiple values from a single
-query.
+In each B<Query> block, there is one or more B<Result> blocks. Multiple
+B<Result> blocks may be used to extract multiple values from a single query.
+
+The following configuration options are available to define the query:
=over 4
The returned lines will be handled separately one after another.
-=item B<Param> I<hostname>|I<database>|I<username>|I<interval>
+=item B<Param> I<hostname>|I<database>|I<instance>|I<username>|I<interval>
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
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<PluginInstanceFrom> I<column>
+
+Specify how to create the "PluginInstance" for reporting this query results.
+Only one column is supported. You may concatenate fields and string values in
+the query statement to get the required results.
+
+=item B<MinVersion> I<version>
+
+=item B<MaxVersion> 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 B<Result> block defines how to handle the values returned from the query.
+It defines which column holds which value and how to dispatch that value to
+the daemon.
+
+=over 4
+
=item B<Type> I<type>
The I<type> name to be used when dispatching the values. The type describes
details on types and their configuration. The number and type of values (as
selected by the B<ValuesFrom> option) has to match the type of the given name.
-This option is required inside a B<Result> block.
+This option is mandatory.
=item B<InstancePrefix> I<prefix>
@@ -5028,20 +5618,6 @@ This option is required inside a B<Result> block and may be specified multiple
times. If multiple B<ValuesFrom> options are specified, the columns are read
in the given order.
-=item B<MinVersion> I<version>
-
-=item B<MaxVersion> 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
name (which is the default, if this option has not been specified). This
allows one to query multiple databases of the same name on the same host (e.g.
when running multiple database server versions in parallel).
+The plugin instance name can also be set from the query result using
+the B<PluginInstanceFrom> option in B<Query> block.
=item B<Host> I<hostname>
allows one to "group" several processes together. I<name> must not contain
slashes.
+=item B<CollectContextSwitch> I<Boolean>
+
+Collect context switch of the process.
+
=back
=head2 Plugin C<protocols>
@@ -5943,6 +6525,12 @@ few ones. This option enables you to do that: By setting B<IgnoreSelected> to
I<true> the effect of B<Sensor> is inverted: All selected sensors are ignored
and all other sensors are collected.
+=item B<UseLabels> I<true>|I<false>
+
+Configures how sensor readings are reported. When set to I<true>, sensor
+readings are reported using their descriptive label (e.g. "VCore"). When set to
+I<false> (the default) the sensor name is used ("in0").
+
=back
=head2 Plugin C<sigrok>
@@ -6045,6 +6633,22 @@ collected. If at least one B<Disk> option is given and no B<IgnoreSelected> or
set to B<false>, B<only> matching disks will be collected. If B<IgnoreSelected>
is set to B<true>, all disks are collected B<except> the ones matched.
+=item B<IgnoreSleepMode> B<true>|B<false>
+
+Normally, the C<smart> plugin will ignore disks that are reported to be asleep.
+This option disables the sleep mode check and allows the plugin to collect data
+from these disks anyway. This is useful in cases where libatasmart mistakenly
+reports disks as asleep because it has not been updated to incorporate support
+for newer idle states in the ATA spec.
+
+=item B<UseSerial> B<true>|B<false>
+
+A disk's kernel name (e.g., sda) can change from one boot to the next. If this
+option is enabled, the C<smart> plugin will use the disk's serial number (e.g.,
+HGST_HUH728080ALE600_2EJ8VH8X) instead of the kernel name as the key for
+storing data. This ensures that the data for a given disk will be kept together
+even if the kernel name changes.
+
=back
=head2 Plugin C<snmp>
@@ -6091,6 +6695,12 @@ rate of counters and size of sets will be zero, timers report C<NaN> and gauges
are unchanged. If set to B<True>, the such metrics are not dispatched and
removed from the internal cache.
+=item B<CounterSum> B<false>|B<true>
+
+When enabled, creates a C<count> metric which reports the change since the last
+read. This option primarily exists for compatibility with the I<statsd>
+implementation by Etsy.
+
=item B<TimerPercentile> I<Percent>
Calculate and dispatch the configured percentile, i.e. compute the latency, so
=item B<AllPortsSummary> I<true>|I<false>
If this option is set to I<true> a summary of statistics from all connections
-are collectd. This option defaults to I<false>.
+are collected. This option defaults to I<false>.
=back
=item B<DigitalTemperatureSensor> I<true>|I<false>
Boolean enabling the collection of the temperature of each core.
-This option should only be used if the automated detectionfails or
+This option should only be used if the automated detectionfails or
if you want to disable this feature.
=item B<DigitalTemperatureSensor> I<true>|I<false>
Boolean enabling the collection of the temperature of each package.
-This option should only be used if the automated detectionfails or
+This option should only be used if the automated detectionfails or
if you want to disable this feature.
=item B<TCCActivationTemp> I<Temperature>
B<address> means use the interface's mac address. This is useful since the
interface path might change between reboots of a guest or across migrations.
-=item B<PluginInstanceFormat> B<name|uuid>
+=item B<PluginInstanceFormat> B<name|uuid|none>
When the virt plugin logs data, it sets the plugin_instance of the collected
-data according to this setting. The default is to use the guest name as provided
-by the hypervisor, which is equal to setting B<name>.
+data according to this setting. The default is to not set the plugin_instance.
+B<name> means use the guest's name as provided by the hypervisor.
B<uuid> means use the guest's UUID.
-You can also specify combinations of these fields. For example B<name uuid>
-means to concatenate the guest name and UUID (with a literal colon character
-between, thus I<"foo:1234-1234-1234-1234">).
+You can also specify combinations of the B<name> and B<uuid> fields.
+For example B<name uuid> means to concatenate the guest name and UUID
+(with a literal colon character between, thus I<"foo:1234-1234-1234-1234">).
=back
Protocol to use when connecting to I<Graphite>. Defaults to C<tcp>.
+=item B<ReconnectInterval> I<Seconds>
+
+When set to non-zero, forces the connection to the Graphite backend to be
+closed and re-opend periodically. This behavior is desirable in environments
+where the connection to the Graphite backend is done through load balancers,
+for example. When set to zero, the default, the connetion is kept open for as
+long as possible.
+
=item B<LogSendErrors> B<false>|B<true>
If set to B<true> (the default), logs errors when sending data to I<Graphite>.
Password required to load the private key in B<ClientKey>.
+=item B<Header> I<Header>
+
+A HTTP header to add to the request. Multiple headers are added if this option is specified more than once. Example:
+
+ Header "X-Custom-Header: custom_value"
+
=item B<SSLVersion> B<SSLv2>|B<SSLv3>|B<TLSv1>|B<TLSv1_0>|B<TLSv1_1>|B<TLSv1_2>
Define which SSL protocol version must be used. By default C<libcurl> will
attempt to figure out the remote SSL protocol version. See
L<curl_easy_setopt(3)> for more details.
-=item B<Format> B<Command>|B<JSON>
+=item B<Format> B<Command>|B<JSON>|B<KAIROSDB>
Format of the output to generate. If set to B<Command>, will create output that
is understood by the I<Exec> and I<UnixSock> plugins. When set to B<JSON>, will
-create output in the I<JavaScript Object Notation> (JSON).
+create output in the I<JavaScript Object Notation> (JSON). When set to KAIROSDB
+, will create output in the KairosDB format.
Defaults to B<Command>.
+=item B<Metrics> B<true>|B<false>
+
+Controls whether I<metrics> are POSTed to this location. Defaults to B<true>.
+
+=item B<Notifications> B<false>|B<true>
+
+Controls whether I<notifications> are POSTed to this location. Defaults to B<false>.
+
=item B<StoreRates> B<true|false>
If set to B<true>, convert counter values to rates. If set to B<false> (the
@@ -7398,6 +8031,10 @@ complete. When this limit is reached, the POST operation will be aborted, and
all the data in the current send buffer will probably be lost. Defaults to 0,
which means the connection never times out.
+=item B<LogHttpError> B<false>|B<true>
+
+Enables printing of HTTP error code to log. Turned off by default.
+
The C<write_http> plugin regularly submits the collected values to the HTTP
server. How frequently this happens depends on how much data you are collecting
and the size of B<BufferSize>. The optimal value to set B<Timeout> to is
Host "localhost"
Port "6379"
Timeout 1000
+ Prefix "collectd/"
+ Database 1
+ MaxSetSize -1
+ StoreRates true
</Node>
</Plugin>
Values are submitted to I<Sorted Sets>, using the metric name as the key, and
the timestamp as the score. Retrieving a date range can then be done using the
C<ZRANGEBYSCORE> I<Redis> command. Additionally, all the identifiers of these
-I<Sorted Sets> are kept in a I<Set> called C<collectd/values> and can be
-retrieved using the C<SMEMBERS> I<Redis> command. See
+I<Sorted Sets> are kept in a I<Set> called C<collectd/values> (or
+C<${prefix}/values> if the B<Prefix> option was specified) and can be retrieved
+using the C<SMEMBERS> I<Redis> command. You can specify the database to use
+with the B<Database> parameter (default is C<0>). See
L<http://redis.io/commands#sorted_set> and L<http://redis.io/commands#set> for
details.
The B<Timeout> option sets the socket connection timeout, in milliseconds.
+=item B<Prefix> I<Prefix>
+
+Prefix used when constructing the name of the I<Sorted Sets> and the I<Set>
+containing all metrics. Defaults to C<collectd/>, so metrics will have names
+like C<collectd/cpu-0/cpu-user>. When setting this to something different, it
+is recommended but not required to include a trailing slash in I<Prefix>.
+
+=item B<Database> I<Index>
+
+This index selects the redis database to use for writing operations. Defaults
+to C<0>.
+
+=item B<MaxSetSize> I<Items>
+
+The B<MaxSetSize> option limits the number of items that the I<Sorted Sets> can
+hold. Negative values for I<Items> sets no limit, which is the default behavior.
+
+=item B<StoreRates> B<true>|B<false>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer number.
+
=back
=head2 Plugin C<write_riemann>
Service name or port number to connect to. Defaults to C<5555>.
-=item B<Protocol> B<UDP>|B<TCP>
+=item B<Protocol> B<UDP>|B<TCP>|B<TLS>
Specify the protocol to use when communicating with I<Riemann>. Defaults to
B<TCP>.
+=item B<TLSCertFile> I<Path>
+
+When using the B<TLS> protocol, path to a PEM certificate to present
+to remote host.
+
+=item B<TLSCAFile> I<Path>
+
+When using the B<TLS> protocol, path to a PEM CA certificate to
+use to validate the remote hosts's identity.
+
+=item B<TLSKeyFile> I<Path>
+
+When using the B<TLS> protocol, path to a PEM private key associated
+with the certificate defined by B<TLSCertFile>.
+
=item B<Batch> B<true>|B<false>
If set to B<true> and B<Protocol> is set to B<TCP>,
Maximum payload size for a riemann packet. Defaults to 8192
+=item B<BatchFlushTimeout> I<seconds>
+
+Maximum amount of seconds to wait in between to batch flushes.
+No timeout by default.
+
=item B<StoreRates> B<true>|B<false>
If set to B<true> (the default), convert counter values to rates. If set to
=back
+=head2 Plugin C<xencpu>
+
+This plugin collects metrics of hardware CPU load for machine running Xen
+hypervisor. Load is calculated from 'idle time' value, provided by Xen.
+Result is reported using the C<percent> type, for each CPU (core).
+
+This plugin doesn't have any options (yet).
+
=head2 Plugin C<zookeeper>
The I<zookeeper plugin> will collect statistics from a I<Zookeeper> server
=item B<TypeInstance> I<String>
+=item B<MetaData> I<String> I<String>
+
Set the appropriate field to the given string. The strings for plugin instance
and type instance may be empty, the strings for host and plugin may not be
empty. It's currently not possible to set the type of a value this way.
diff --git a/src/collectdctl.c b/src/collectdctl.c
index d019d2742f3db6bef5d98f653ed144cdf4a42895..8c884796403edfa9c6d69aec38421d6dbad359e7 100644 (file)
--- a/src/collectdctl.c
+++ b/src/collectdctl.c
#include "libcollectdclient/collectd/client.h"
+#ifndef PREFIX
+# define PREFIX "/opt/" PACKAGE_NAME
+#endif
+
+#ifndef LOCALSTATEDIR
+# define LOCALSTATEDIR PREFIX "/var"
+#endif
+
#define DEFAULT_SOCK LOCALSTATEDIR"/run/"PACKAGE_NAME"-unixsock"
extern char *optarg;
extern int optind;
+__attribute__((noreturn))
static void exit_usage (const char *name, int status) {
fprintf ((status == 0) ? stdout : stderr,
"Usage: %s [options] <command> [cmd options]\n\n"
return count;
} /* count_chars */
-static int array_grow (void **array, int *array_len, size_t elem_size)
+static int array_grow (void **array, size_t *array_len, size_t elem_size)
{
void *tmp;
char **ret_values_names = NULL;
int status;
- size_t i;
assert (strcasecmp (argv[0], "getval") == 0);
return (-1);
}
- memset (&ident, 0, sizeof (ident));
status = parse_identifier (c, argv[1], &ident);
if (status != 0)
return (status);
if (ret_values != NULL) \
free (ret_values); \
if (ret_values_names != NULL) { \
- for (i = 0; i < ret_values_num; ++i) \
+ for (size_t i = 0; i < ret_values_num; ++i) \
free (ret_values_names[i]); \
free (ret_values_names); \
} \
BAIL_OUT (-1);
}
- for (i = 0; i < ret_values_num; ++i)
+ for (size_t i = 0; i < ret_values_num; ++i)
printf ("%s=%e\n", ret_values_names[i], ret_values[i]);
BAIL_OUT (0);
#undef BAIL_OUT
int timeout = -1;
lcc_identifier_t *identifiers = NULL;
- int identifiers_num = 0;
+ size_t identifiers_num = 0;
char **plugins = NULL;
- int plugins_num = 0;
+ size_t plugins_num = 0;
int status;
- int i;
assert (strcasecmp (argv[0], "flush") == 0);
return (s); \
} while (0)
- for (i = 1; i < argc; ++i) {
+ for (int i = 1; i < argc; ++i) {
char *key, *value;
key = argv[i];
plugins[0] = NULL;
}
- for (i = 0; i < plugins_num; ++i) {
+ for (size_t i = 0; i < plugins_num; ++i) {
if (identifiers_num == 0) {
status = lcc_flush (c, plugins[i], NULL, timeout);
if (status != 0)
(plugins[i] == NULL) ? "(all)" : plugins[i], lcc_strerror (c));
}
else {
- int j;
-
- for (j = 0; j < identifiers_num; ++j) {
+ for (size_t j = 0; j < identifiers_num; ++j) {
status = lcc_flush (c, plugins[i], identifiers + j, timeout);
if (status != 0) {
char id[1024];
size_t ret_ident_num = 0;
int status;
- size_t i;
assert (strcasecmp (argv[0], "listval") == 0);
BAIL_OUT (status);
}
- for (i = 0; i < ret_ident_num; ++i) {
+ for (size_t i = 0; i < ret_ident_num; ++i) {
char id[1024];
status = lcc_identifier_to_string (c, id, sizeof (id), ret_ident + i);
size_t values_len = 0;
int status;
- int i;
assert (strcasecmp (argv[0], "putval") == 0);
if (status != 0)
return (status);
- for (i = 2; i < argc; ++i) {
+ for (int i = 2; i < argc; ++i) {
char *tmp;
tmp = strchr (argv[i], (int)'=');
values_len = 0;
value = tmp;
- while (value != 0) {
+ while (value != NULL) {
char *dot, *endptr;
tmp = strchr (value, (int)':');
values_types[values_len] = LCC_TYPE_GAUGE;
}
else { /* integer */
- values[values_len].counter = strtol (value, &endptr, 0);
+ values[values_len].counter = (counter_t) strtoull (value, &endptr, 0);
values_types[values_len] = LCC_TYPE_COUNTER;
}
++values_len;
int status;
while (42) {
- int n;
+ int opt;
- n = getopt (argc, argv, "s:h");
+ opt = getopt (argc, argv, "s:h");
- if (n == -1)
+ if (opt == -1)
break;
- switch (n) {
+ switch (opt) {
case 's':
snprintf (address, sizeof (address), "unix:%s", optarg);
address[sizeof (address) - 1] = '\0';
break;
case 'h':
exit_usage (argv[0], 0);
- break;
default:
exit_usage (argv[0], 1);
}
diff --git a/src/collectdmon.c b/src/collectdmon.c
index 33f02b45694d889d07613a05110230c1b32d7442..61daa58c6ba1f07a4fbfa3716125b3fcb0be73b2 100644 (file)
--- a/src/collectdmon.c
+++ b/src/collectdmon.c
#include <unistd.h>
+#ifndef PREFIX
+# define PREFIX "/opt/" PACKAGE_NAME
+#endif
+
+#ifndef LOCALSTATEDIR
+# define LOCALSTATEDIR PREFIX "/var"
+#endif
+
#ifndef COLLECTDMON_PIDFILE
# define COLLECTDMON_PIDFILE LOCALSTATEDIR"/run/collectdmon.pid"
#endif /* ! COLLECTDMON_PIDFILE */
static int loop = 0;
static int restart = 0;
-static char *pidfile = NULL;
-static pid_t collectd_pid = 0;
+static const char *pidfile = NULL;
+static pid_t collectd_pid = 0;
-static void exit_usage (char *name)
+__attribute__((noreturn))
+static void exit_usage (const char *name)
{
printf ("Usage: %s <options> [-- <collectd options>]\n"
static int daemonize (void)
{
struct rlimit rl;
+ int dev_null;
pid_t pid = 0;
int i = 0;
for (i = 0; i < (int)rl.rlim_max; ++i)
close (i);
- errno = 0;
- if (open ("/dev/null", O_RDWR) != 0) {
- syslog (LOG_ERR, "Error: couldn't connect STDIN to /dev/null: %s",
- strerror (errno));
+ dev_null = open ("/dev/null", O_RDWR);
+ if (dev_null == -1) {
+ syslog (LOG_ERR, "Error: couldn't open /dev/null: %s", strerror (errno));
return -1;
}
- errno = 0;
- if (dup (0) != 1) {
- syslog (LOG_ERR, "Error: couldn't connect STDOUT to /dev/null: %s",
- strerror (errno));
+ if (dup2 (dev_null, STDIN_FILENO) == -1) {
+ close (dev_null);
+ syslog (LOG_ERR, "Error: couldn't connect STDIN to /dev/null: %s", strerror (errno));
return -1;
}
- errno = 0;
- if (dup (0) != 2) {
- syslog (LOG_ERR, "Error: couldn't connect STDERR to /dev/null: %s",
- strerror (errno));
+ if (dup2 (dev_null, STDOUT_FILENO) == -1) {
+ close (dev_null);
+ syslog (LOG_ERR, "Error: couldn't connect STDOUT to /dev/null: %s", strerror (errno));
return -1;
}
+
+ if (dup2 (dev_null, STDERR_FILENO) == -1) {
+ close (dev_null);
+ syslog (LOG_ERR, "Error: couldn't connect STDERR to /dev/null: %s", strerror (errno));
+ return -1;
+ }
+
+ if ((dev_null != STDIN_FILENO) && (dev_null != STDOUT_FILENO) && (dev_null != STDERR_FILENO))
+ close (dev_null);
+
return 0;
} /* daemonize */
diff --git a/src/conntrack.c b/src/conntrack.c
index 49a33551d6ec4167adf9e74171092cb5cfd8a0f9..ce90ede34749e5e30b4014e99193539119f5ea68 100644 (file)
--- a/src/conntrack.c
+++ b/src/conntrack.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
{
value_t conntrack, conntrack_max, conntrack_pct;
FILE *fh;
- char buffer[64];
+ char buffer[64] = { 0 };
size_t buffer_len;
fh = fopen (old_files?CONNTRACK_FILE_OLD:CONNTRACK_FILE, "r");
if (fh == NULL)
return (-1);
- memset (buffer, 0, sizeof (buffer));
if (fgets (buffer, sizeof (buffer), fh) == NULL)
{
fclose (fh);
void module_register (void)
{
- plugin_register_config ("conntrack", conntrack_config,
+ plugin_register_config ("conntrack", conntrack_config,
config_keys, config_keys_num);
plugin_register_read ("conntrack", conntrack_read);
} /* void module_register */
diff --git a/src/contextswitch.c b/src/contextswitch.c
index 344f76e76f0c29242ac20821d8efb25f83f12871..76e2a6c0b935c9225d50e96e7c2405554f459476 100644 (file)
--- a/src/contextswitch.c
+++ b/src/contextswitch.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
diff --git a/src/cpu.c b/src/cpu.c
index c9462506dca025a633ccf3f591de8c23f2671c1a..1ac5b4a3b94a9cea50835485befc4adf7c934b88 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
static _Bool report_by_cpu = 1;
static _Bool report_by_state = 1;
static _Bool report_percent = 0;
+static _Bool report_num_cpu = 0;
static const char *config_keys[] =
{
"ReportByCpu",
"ReportByState",
+ "ReportNumCpu",
"ValuesPercentage"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
report_percent = IS_TRUE (value) ? 1 : 0;
else if (strcasecmp (key, "ReportByState") == 0)
report_by_state = IS_TRUE (value) ? 1 : 0;
+ else if (strcasecmp (key, "ReportNumCpu") == 0)
+ report_num_cpu = IS_TRUE (value) ? 1 : 0;
else
return (-1);
* array. */
static void aggregate (gauge_t *sum_by_state) /* {{{ */
{
- size_t cpu_num;
- size_t state;
-
- for (state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
+ for (size_t state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
sum_by_state[state] = NAN;
- for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+ for (size_t cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
{
cpu_state_t *this_cpu_states = get_cpu_state (cpu_num, 0);
this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate = NAN;
- for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+ for (size_t state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
{
if (!this_cpu_states[state].has_value)
continue;
static void cpu_commit_one (int cpu_num, /* {{{ */
gauge_t rates[static COLLECTD_CPU_STATE_MAX])
{
- size_t state;
gauge_t sum;
sum = rates[COLLECTD_CPU_STATE_ACTIVE];
return;
}
- for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+ for (size_t state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
{
gauge_t percent = 100.0 * rates[state] / sum;
submit_percent (cpu_num, state, percent);
}
} /* }}} void cpu_commit_one */
+/* Commits the number of cores */
+static void cpu_commit_num_cpu (gauge_t num_cpu) /* {{{ */
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = num_cpu;
+
+ vl.values = values;
+ vl.values_len = 1;
+
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "cpu", sizeof (vl.plugin));
+ sstrncpy (vl.type, "count", sizeof (vl.type));
+
+ plugin_dispatch_values (&vl);
+} /* }}} void cpu_commit_num_cpu */
+
/* Resets the internal aggregation. This is called by the read callback after
* each iteration / after each call to cpu_commit(). */
static void cpu_reset (void) /* {{{ */
{
- size_t i;
-
- for (i = 0; i < cpu_states_num; i++)
+ for (size_t i = 0; i < cpu_states_num; i++)
cpu_states[i].has_value = 0;
global_cpu_num = 0;
/* Legacy behavior: Dispatches the raw derive values without any aggregation. */
static void cpu_commit_without_aggregation (void) /* {{{ */
{
- int state;
-
- for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+ for (int state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
{
- size_t cpu_num;
-
- for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+ for (size_t cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
{
cpu_state_t *s = get_cpu_state (cpu_num, state);
gauge_t global_rates[COLLECTD_CPU_STATE_MAX] = {
NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN /* Batman! */
};
- size_t cpu_num;
+
+ if (report_num_cpu)
+ cpu_commit_num_cpu ((gauge_t) global_cpu_num);
if (report_by_state && report_by_cpu && !report_percent)
{
return;
}
- for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+ for (size_t cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
{
cpu_state_t *this_cpu_states = get_cpu_state (cpu_num, 0);
gauge_t local_rates[COLLECTD_CPU_STATE_MAX] = {
NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN
};
- size_t state;
- for (state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
+ for (size_t state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
if (this_cpu_states[state].has_value)
local_rates[state] = this_cpu_states[state].rate;
/* Adds a derive value to the internal state. This should be used by each read
* function for each state. At the end of the iteration, the read function
* should call cpu_commit(). */
-static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now) /* {{{ */
+static int cpu_stage (size_t cpu_num, size_t state, derive_t d, cdtime_t now) /* {{{ */
{
int status;
cpu_state_t *s;
- value_t v;
+ gauge_t rate = NAN;
+ value_t val = {.derive = d};
if (state >= COLLECTD_CPU_STATE_ACTIVE)
return (EINVAL);
@@ -554,12 +569,11 @@ static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now
s = get_cpu_state (cpu_num, state);
- v.gauge = NAN;
- status = value_to_rate (&v, value, &s->conv, DS_TYPE_DERIVE, now);
+ status = value_to_rate (&rate, val, DS_TYPE_DERIVE, now, &s->conv);
if (status != 0)
return (status);
- s->rate = v.gauge;
+ s->rate = rate;
s->has_value = 1;
return (0);
} /* }}} int cpu_stage */
cdtime_t now = cdtime ();
#if PROCESSOR_CPU_LOAD_INFO /* {{{ */
- int cpu;
-
kern_return_t status;
processor_cpu_load_info_data_t cpu_info;
host_t cpu_host;
- for (cpu = 0; cpu < cpu_list_len; cpu++)
+ for (mach_msg_type_number_t cpu = 0; cpu < cpu_list_len; cpu++)
{
cpu_host = 0;
cpu_info_len = PROCESSOR_BASIC_INFO_COUNT;
/* }}} #endif defined(KERNEL_LINUX) */
#elif defined(HAVE_LIBKSTAT) /* {{{ */
- int cpu;
static cpu_stat_t cs;
if (kc == NULL)
return (-1);
- for (cpu = 0; cpu < numcpu; cpu++)
+ for (int cpu = 0; cpu < numcpu; cpu++)
{
if (kstat_read (kc, ksp[cpu], &cs) == -1)
continue; /* error message? */
uint64_t cpuinfo[numcpu][CPUSTATES];
size_t cpuinfo_size;
int status;
- int i;
if (numcpu < 1)
{
#if defined(KERN_CPTIME2)
if (numcpu > 1) {
- for (i = 0; i < numcpu; i++) {
+ for (int i = 0; i < numcpu; i++) {
int mib[] = {CTL_KERN, KERN_CPTIME2, i};
cpuinfo_size = sizeof (cpuinfo[0]);
return (-1);
}
- for(i = 0; i < CPUSTATES; i++) {
+ for(int i = 0; i < CPUSTATES; i++) {
cpuinfo[0][i] = cpuinfo_tmp[i];
}
}
- for (i = 0; i < numcpu; i++) {
+ for (int i = 0; i < numcpu; i++) {
cpu_stage (i, COLLECTD_CPU_STATE_USER, (derive_t) cpuinfo[i][CP_USER], now);
cpu_stage (i, COLLECTD_CPU_STATE_NICE, (derive_t) cpuinfo[i][CP_NICE], now);
cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM, (derive_t) cpuinfo[i][CP_SYS], now);
#elif defined(HAVE_SYSCTLBYNAME) && defined(HAVE_SYSCTL_KERN_CP_TIMES) /* {{{ */
long cpuinfo[maxcpu][CPUSTATES];
size_t cpuinfo_size;
- int i;
memset (cpuinfo, 0, sizeof (cpuinfo));
return (-1);
}
- for (i = 0; i < numcpu; i++) {
+ for (int i = 0; i < numcpu; i++) {
cpu_stage (i, COLLECTD_CPU_STATE_USER, (derive_t) cpuinfo[i][CP_USER], now);
cpu_stage (i, COLLECTD_CPU_STATE_NICE, (derive_t) cpuinfo[i][CP_NICE], now);
cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM, (derive_t) cpuinfo[i][CP_SYS], now);
#elif defined(HAVE_PERFSTAT) /* {{{ */
perfstat_id_t id;
- int i, cpus;
+ int cpus;
numcpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
if(numcpu == -1)
if (pnumcpu != numcpu || perfcpu == NULL)
{
- if (perfcpu != NULL)
- free(perfcpu);
+ free(perfcpu);
perfcpu = malloc(numcpu * sizeof(perfstat_cpu_t));
}
pnumcpu = numcpu;
return (-1);
}
- for (i = 0; i < cpus; i++)
+ for (int i = 0; i < cpus; i++)
{
cpu_stage (i, COLLECTD_CPU_STATE_IDLE, (derive_t) perfcpu[i].idle, now);
cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM, (derive_t) perfcpu[i].sys, now);
diff --git a/src/cpufreq.c b/src/cpufreq.c
index b92b1d095226c6a9deea13fa6731d5a68b213478..1e9e857980c68c3ebcb19af9e9b8c15d3f83ddcc 100644 (file)
--- a/src/cpufreq.c
+++ b/src/cpufreq.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
{
int status;
unsigned long long val;
- int i = 0;
FILE *fp;
char filename[256];
char buffer[16];
- for (i = 0; i < num_cpu; i++)
+ for (int i = 0; i < num_cpu; i++)
{
status = ssnprintf (filename, sizeof (filename),
"/sys/devices/system/cpu/cpu%d/cpufreq/"
diff --git a/src/cpusleep.c b/src/cpusleep.c
--- /dev/null
+++ b/src/cpusleep.c
@@ -0,0 +1,79 @@
+/**
+ * collectd - src/cpusleep.c
+ * Copyright (C) 2016 rinigus
+ *
+ * The MIT License (MIT)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * rinigus <http://github.com/rinigus>
+ *
+ * CPU sleep is reported in milliseconds of sleep per second of wall
+ * time. For that, the time difference between BOOT and MONOTONIC clocks
+ * is reported using derive type.
+**/
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+#include <time.h>
+
+static void cpusleep_submit(derive_t cpu_sleep) {
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].derive = cpu_sleep;
+
+ vl.values = values;
+ vl.values_len = 1;
+ sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+ sstrncpy(vl.plugin, "cpusleep", sizeof(vl.plugin));
+ sstrncpy(vl.type, "total_time_in_ms", sizeof(vl.type));
+
+ plugin_dispatch_values(&vl);
+}
+
+static int cpusleep_read(void) {
+ struct timespec b, m;
+ if (clock_gettime(CLOCK_BOOTTIME, &b) < 0) {
+ ERROR("cpusleep plugin: clock_boottime failed");
+ return (-1);
+ }
+
+ if (clock_gettime(CLOCK_MONOTONIC, &m) < 0) {
+ ERROR("cpusleep plugin: clock_monotonic failed");
+ return (-1);
+ }
+
+ // to avoid false positives in counter overflow due to reboot,
+ // derive is used. Sleep is calculated in milliseconds
+ derive_t diffsec = b.tv_sec - m.tv_sec;
+ derive_t diffnsec = b.tv_nsec - m.tv_nsec;
+ derive_t sleep = diffsec * 1000 + diffnsec / 1000000;
+
+ cpusleep_submit(sleep);
+
+ return (0);
+}
+
+void module_register(void) {
+ plugin_register_read("cpusleep", cpusleep_read);
+} /* void module_register */
diff --git a/src/cpython.h b/src/cpython.h
index 81e580d485c9bd58c625df40b369edd75dd94e75..070d33af9e61df3a6abe968a223bc5533985f227 100644 (file)
--- a/src/cpython.h
+++ b/src/cpython.h
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Sven Trenkel <collectd at semidefinite.de>
+ * Sven Trenkel <collectd at semidefinite.de>
**/
/* Some python versions don't include this by default. */
PyGILState_Release(gil_state);\
}
-/* Python 2.4 has this macro, older versions do not. */
-#ifndef Py_VISIT
-#define Py_VISIT(o) do {\
- int _vret;\
- if ((o) != NULL) {\
- _vret = visit((o), arg);\
- if (_vret != 0)\
- return _vret;\
- }\
-} while (0)
-#endif
-
-/* Python 2.4 has this macro, older versions do not. */
-#ifndef Py_CLEAR
-#define Py_CLEAR(o) do {\
- PyObject *tmp = o;\
- (o) = NULL;\
- Py_XDECREF(tmp);\
-} while (0)
-#endif
-
-/* Python 2.4 has this macro, older versions do not. */
-#ifndef Py_RETURN_NONE
-# define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
-#endif
-
/* This macro is a shortcut for calls like
* x = PyObject_Repr(x);
* This can't be done like this example because this would leak
} while (0)
static inline void CPY_STRCAT(PyObject **a, PyObject *b) {
PyObject *ret;
-
+
if (!a || !*a)
return;
-
+
ret = PyUnicode_Concat(*a, b);
Py_DECREF(*a);
*a = ret;
return PyBytes_FromString(buf);
#else
return PyString_FromString(buf);
-#endif
+#endif
}
void cpy_log_exception(const char *context);
PyObject *values; /* Sequence */
PyObject *children; /* Sequence */
} Config;
-PyTypeObject ConfigType;
+extern PyTypeObject ConfigType;
typedef struct {
PyObject_HEAD /* No semicolon! */
char type[DATA_MAX_NAME_LEN];
char type_instance[DATA_MAX_NAME_LEN];
} PluginData;
-PyTypeObject PluginDataType;
+extern PyTypeObject PluginDataType;
#define PluginData_New() PyObject_CallFunctionObjArgs((PyObject *) &PluginDataType, (void *) 0)
typedef struct {
PyObject *meta; /* dict */
double interval;
} Values;
-PyTypeObject ValuesType;
+extern PyTypeObject ValuesType;
#define Values_New() PyObject_CallFunctionObjArgs((PyObject *) &ValuesType, (void *) 0)
typedef struct {
int severity;
char message[NOTIF_MAX_MSG_LEN];
} Notification;
-PyTypeObject NotificationType;
+extern PyTypeObject NotificationType;
#define Notification_New() PyObject_CallFunctionObjArgs((PyObject *) &NotificationType, (void *) 0)
typedef PyLongObject Signed;
-PyTypeObject SignedType;
+extern PyTypeObject SignedType;
typedef PyLongObject Unsigned;
-PyTypeObject UnsignedType;
+extern PyTypeObject UnsignedType;
diff --git a/src/csv.c b/src/csv.c
index 07728734cc727ab0f8991480fd27c65298aabed1..e008ecfe0f6fdeafe10caa20b9d7ca2eaf44c2f6 100644 (file)
--- a/src/csv.c
+++ b/src/csv.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include "utils_cache.h"
{
int offset;
int status;
- int i;
gauge_t *rates = NULL;
assert (0 == strcmp (ds->type, vl->type));
return (-1);
offset = status;
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if ((ds->ds[i].type != DS_TYPE_COUNTER)
&& (ds->ds[i].type != DS_TYPE_GAUGE)
static int csv_create_file (const char *filename, const data_set_t *ds)
{
FILE *csv;
- int i;
if (check_create_dir (filename))
return (-1);
}
fprintf (csv, "epoch");
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
fprintf (csv, ",%s", ds->ds[i].name);
fprintf (csv, "\n");
char values[4096];
FILE *csv;
int csv_fd;
- struct flock fl;
+ struct flock fl = { 0 };
int status;
if (0 != strcmp (ds->type, vl->type)) {
if (use_stdio)
{
- size_t i;
-
escape_string (filename, sizeof (filename));
/* Replace commas by colons for PUTVAL compatible output. */
- for (i = 0; i < sizeof (values); i++)
+ for (size_t i = 0; i < sizeof (values); i++)
{
if (values[i] == 0)
break;
}
csv_fd = fileno (csv);
- memset (&fl, '\0', sizeof (fl));
- fl.l_start = 0;
- fl.l_len = 0; /* till end of file */
fl.l_pid = getpid ();
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
diff --git a/src/curl.c b/src/curl.c
index 470f25db9094e5ebd2743a49fc72ca9dbfedfcd1..74ef13c97463469e42f878b3235f328b2ed11f1f 100644 (file)
--- a/src/curl.c
+++ b/src/curl.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
+#include "utils_curl_stats.h"
#include "utils_match.h"
#include "utils_time.h"
_Bool response_time;
_Bool response_code;
int timeout;
+ curl_stats_t *stats;
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
size_t len;
len = size * nmemb;
- if (len <= 0)
+ if (len == 0)
return (len);
wp = user_data;
size_t temp_size;
temp_size = wp->buffer_fill + len + 1;
- temp = (char *) realloc (wp->buffer, temp_size);
+ temp = realloc (wp->buffer, temp_size);
if (temp == NULL)
{
ERROR ("curl plugin: realloc failed.");
sfree (wp->cacert);
sfree (wp->post_body);
curl_slist_free_all (wp->headers);
+ curl_stats_destroy (wp->stats);
sfree (wp->buffer);
{
web_match_t *match;
int status;
- int i;
if (ci->values_num != 0)
{
WARNING ("curl plugin: Ignoring arguments for the `Match' block.");
}
- match = (web_match_t *) malloc (sizeof (*match));
+ match = calloc (1, sizeof (*match));
if (match == NULL)
{
- ERROR ("curl plugin: malloc failed.");
+ ERROR ("curl plugin: calloc failed.");
return (-1);
}
- memset (match, 0, sizeof (*match));
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
match->dstype);
if (match->match == NULL)
{
- ERROR ("curl plugin: tail_match_add_match_simple failed.");
+ ERROR ("curl plugin: match_create_simple failed.");
cc_web_match_free (match);
return (-1);
}
if (wp->pass != NULL)
credentials_size += strlen (wp->pass);
- wp->credentials = (char *) malloc (credentials_size);
+ wp->credentials = malloc (credentials_size);
if (wp->credentials == NULL)
{
ERROR ("curl plugin: malloc failed.");
if (wp->timeout >= 0)
curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) wp->timeout);
else
- curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
{
web_page_t *page;
int status;
- int i;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
return (-1);
}
- page = (web_page_t *) malloc (sizeof (*page));
+ page = calloc (1, sizeof (*page));
if (page == NULL)
{
- ERROR ("curl plugin: malloc failed.");
+ ERROR ("curl plugin: calloc failed.");
return (-1);
}
- memset (page, 0, sizeof (*page));
page->url = NULL;
page->user = NULL;
page->pass = NULL;
page->response_time = 0;
page->response_code = 0;
page->timeout = -1;
+ page->stats = NULL;
page->instance = strdup (ci->values[0].value.string);
if (page->instance == NULL)
/* Process all children */
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
status = cf_util_get_string (child, &page->post_body);
else if (strcasecmp ("Timeout", child->key) == 0)
status = cf_util_get_int (child, &page->timeout);
+ else if (strcasecmp ("Statistics", child->key) == 0) {
+ page->stats = curl_stats_from_config (child);
+ if (page->stats == NULL)
+ status = -1;
+ }
else
{
WARNING ("curl plugin: Option `%s' not allowed here.", child->key);
status = -1;
}
- if (page->matches == NULL && !page->response_time && !page->response_code)
+ if (page->matches == NULL && page->stats == NULL
+ && !page->response_time && !page->response_code)
{
assert (page->instance != NULL);
WARNING ("curl plugin: No (valid) `Match' block "
- "or MeasureResponseTime or MeasureResponseCode within "
- "`Page' block `%s'.", page->instance);
+ "or Statistics or MeasureResponseTime or MeasureResponseCode "
+ "within `Page' block `%s'.", page->instance);
status = -1;
}
web_page_t *prev;
prev = pages_g;
- while ((prev != NULL) && (prev->next != NULL))
+ while (prev->next != NULL)
prev = prev->next;
prev->next = page;
}
int success;
int errors;
int status;
- int i;
success = 0;
errors = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static int cc_read_page (web_page_t *wp) /* {{{ */
{
- web_match_t *wm;
int status;
cdtime_t start = 0;
if (wp->response_time)
cc_submit_response_time (wp, cdtime() - start);
+ if (wp->stats != NULL)
+ curl_stats_dispatch (wp->stats, wp->curl, hostname_g, "curl", wp->instance);
if(wp->response_code)
{
}
}
- for (wm = wp->matches; wm != NULL; wm = wm->next)
+ for (web_match_t *wm = wp->matches; wm != NULL; wm = wm->next)
{
cu_match_value_t *mv;
static int cc_read (void) /* {{{ */
{
- web_page_t *wp;
-
- for (wp = pages_g; wp != NULL; wp = wp->next)
+ for (web_page_t *wp = pages_g; wp != NULL; wp = wp->next)
cc_read_page (wp);
return (0);
diff --git a/src/curl_json.c b/src/curl_json.c
index a547ddcd42a53ac9198475cb78387aed95f87c7b..7d1d8e9309c19dff2132e0deea6fac7559115152 100644 (file)
--- a/src/curl_json.c
+++ b/src/curl_json.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_avltree.h"
#include "utils_complain.h"
+#include "utils_curl_stats.h"
-#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
char *post_body;
cdtime_t interval;
int timeout;
+ curl_stats_t *stats;
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
len = size * nmemb;
- if (len <= 0)
+ if (len == 0)
return (len);
db = user_data;
sfree (db->cacert);
sfree (db->post_body);
curl_slist_free_all (db->headers);
+ curl_stats_destroy (db->stats);
sfree (db);
} /* }}} void cj_free */
{
cj_key_t *key;
int status;
- int i;
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_STRING))
return (-1);
}
- key = (cj_key_t *) malloc (sizeof (*key));
+ key = calloc (1, sizeof (*key));
if (key == NULL)
{
- ERROR ("curl_json plugin: malloc failed.");
+ ERROR ("curl_json plugin: calloc failed.");
return (-1);
}
- memset (key, 0, sizeof (*key));
key->magic = CJ_KEY_MAGIC;
if (strcasecmp ("Key", ci->key) == 0)
}
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (db->pass != NULL)
credentials_size += strlen (db->pass);
- db->credentials = (char *) malloc (credentials_size);
+ db->credentials = malloc (credentials_size);
if (db->credentials == NULL)
{
ERROR ("curl_json plugin: malloc failed.");
if (db->timeout >= 0)
curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
else if (db->interval > 0)
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(db->timeout));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(db->timeout));
else
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
{
cj_t *db;
int status = 0;
- int i;
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_STRING))
return (-1);
}
- db = (cj_t *) malloc (sizeof (*db));
+ db = calloc (1, sizeof (*db));
if (db == NULL)
{
- ERROR ("curl_json plugin: malloc failed.");
+ ERROR ("curl_json plugin: calloc failed.");
return (-1);
}
- memset (db, 0, sizeof (*db));
db->timeout = -1;
}
/* Fill the `cj_t' structure.. */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
status = cf_util_get_cdtime(child, &db->interval);
else if (strcasecmp ("Timeout", child->key) == 0)
status = cf_util_get_int (child, &db->timeout);
+ else if (strcasecmp ("Statistics", child->key) == 0)
+ {
+ db->stats = curl_stats_from_config (child);
+ if (db->stats == NULL)
+ status = -1;
+ }
else
{
WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
/* If all went well, register this database for reading */
if (status == 0)
{
- user_data_t ud;
char *cb_name;
- struct timespec interval = { 0, 0 };
-
- CDTIME_T_TO_TIMESPEC (db->interval, &interval);
if (db->instance == NULL)
db->instance = strdup("default");
DEBUG ("curl_json plugin: Registering new read callback: %s",
db->instance);
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) db;
- ud.free_func = cj_free;
-
cb_name = ssnprintf_alloc ("curl_json-%s-%s",
db->instance, db->url ? db->url : db->sock);
+ user_data_t ud = {
+ .data = db,
+ .free_func = cj_free
+ };
+
plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
- /* interval = */ (db->interval > 0) ? &interval : NULL,
+ /* interval = */ db->interval,
&ud);
sfree (cb_name);
}
int success;
int errors;
int status;
- int i;
success = 0;
errors = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
/* }}} End of configuration handling functions */
+static const char *cj_host (cj_t *db) /* {{{ */
+{
+ if ((db->host == NULL)
+ || (strcmp ("", db->host) == 0)
+ || (strcmp (CJ_DEFAULT_HOST, db->host) == 0))
+ return hostname_g;
+ return db->host;
+} /* }}} cj_host */
+
static void cj_submit (cj_t *db, cj_key_t *key, value_t *value) /* {{{ */
{
value_list_t vl = VALUE_LIST_INIT;
- char *host;
vl.values = value;
vl.values_len = 1;
- if ((db->host == NULL)
- || (strcmp ("", db->host) == 0)
- || (strcmp (CJ_DEFAULT_HOST, db->host) == 0))
- host = hostname_g;
- else
- host = db->host;
-
if (key->instance == NULL)
{
- int i, len = 0;
- for (i = 0; i < db->depth; i++)
+ int len = 0;
+ for (int i = 0; i < db->depth; i++)
len += ssnprintf(vl.type_instance+len, sizeof(vl.type_instance)-len,
i ? "-%s" : "%s", db->state[i+1].name);
}
else
sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
- sstrncpy (vl.host, host, sizeof (vl.host));
+ sstrncpy (vl.host, cj_host (db), sizeof (vl.host));
sstrncpy (vl.plugin, "curl_json", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
sstrncpy (vl.type, key->type, sizeof (vl.type));
static int cj_sock_perform (cj_t *db) /* {{{ */
{
char errbuf[1024];
- struct sockaddr_un sa_unix = {};
+ struct sockaddr_un sa_unix = { 0 };
sa_unix.sun_family = AF_UNIX;
sstrncpy (sa_unix.sun_path, db->sock, sizeof (sa_unix.sun_path));
status, db->curl_errbuf, url);
return (-1);
}
+ if (db->stats != NULL)
+ curl_stats_dispatch (db->stats, db->curl, cj_host (db), "curl_json", db->instance);
curl_easy_getinfo(db->curl, CURLINFO_EFFECTIVE_URL, &url);
curl_easy_getinfo(db->curl, CURLINFO_RESPONSE_CODE, &rc);
}
#if HAVE_YAJL_V2
- status = yajl_complete_parse(db->yajl);
+ status = yajl_complete_parse(db->yajl);
#else
- status = yajl_parse_complete(db->yajl);
+ status = yajl_parse_complete(db->yajl);
#endif
if (status != yajl_status_ok)
{
diff --git a/src/curl_xml.c b/src/curl_xml.c
index c33ec1f3ad091096ad4d3913078b80c0591f22cc..c8a1313cbec48769c882ab5cb034faae3da1cc07 100644 (file)
--- a/src/curl_xml.c
+++ b/src/curl_xml.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
+#include "utils_curl_stats.h"
#include "utils_llist.h"
#include <libxml/parser.h>
char *path;
char *type;
cx_values_t *values;
- int values_len;
+ size_t values_len;
char *instance_prefix;
char *instance;
int is_table;
char *post_body;
int timeout;
struct curl_slist *headers;
+ curl_stats_t *stats;
cx_namespace_t *namespaces;
size_t namespaces_num;
return (0);
}
- if (len <= 0)
+ if (len == 0)
return (len);
if ((db->buffer_fill + len) >= db->buffer_size)
{
char *temp;
- temp = (char *) realloc (db->buffer,
+ temp = realloc (db->buffer,
db->buffer_fill + len + 1);
if (temp == NULL)
{
}
llist_destroy (list);
- list = NULL;
} /* }}} void cx_list_free */
static void cx_free (void *arg) /* {{{ */
{
cx_t *db;
- size_t i;
DEBUG ("curl_xml plugin: cx_free (arg = %p);", arg);
sfree (db->cacert);
sfree (db->post_body);
curl_slist_free_all (db->headers);
+ curl_stats_destroy (db->stats);
- for (i = 0; i < db->namespaces_num; i++)
+ for (size_t i = 0; i < db->namespaces_num; i++)
{
sfree (db->namespaces[i].prefix);
sfree (db->namespaces[i].url);
sfree (db);
} /* }}} void cx_free */
+static const char *cx_host (cx_t *db) /* {{{ */
+{
+ if (db->host == NULL)
+ return hostname_g;
+ return db->host;
+} /* }}} cx_host */
+
static int cx_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
oconfig_item_t *ci)
{
if (ds->ds_num != xpath->values_len)
{
- WARNING ("curl_xml plugin: DataSet `%s' requires %i values, but config talks about %i",
+ WARNING ("curl_xml plugin: DataSet `%s' requires %zu values, but config talks about %zu",
xpath->type, ds->ds_num, xpath->values_len);
return (-1);
}
return (0);
} /* }}} cx_check_type */
-static xmlXPathObjectPtr cx_evaluate_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
+static xmlXPathObjectPtr cx_evaluate_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
xmlChar *expr)
{
xmlXPathObjectPtr xpath_obj;
@@ -318,7 +326,7 @@ static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
{
WARNING ("curl_xml plugin: "
"relative xpath expression \"%s\" is expected to return "
- "only text/attribute node which is not the case. Skipping...",
+ "only text/attribute node which is not the case. Skipping...",
xpath->values[index].path);
xmlXPathFreeObject (values_node_obj);
return (-1);
@@ -339,7 +347,7 @@ static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
vl->values[index].absolute = (absolute_t) strtoull (node_value,
/* endptr = */ NULL, /* base = */ 0);
break;
- case DS_TYPE_GAUGE:
+ case DS_TYPE_GAUGE:
vl->values[index].gauge = (gauge_t) strtod (node_value,
/* endptr = */ NULL);
}
@@ -359,14 +367,13 @@ static int cx_handle_all_value_xpaths (xmlXPathContextPtr xpath_ctx, /* {{{ */
{
value_t values[xpath->values_len];
int status;
- int i;
assert (xpath->values_len > 0);
assert (xpath->values_len == vl->values_len);
assert (xpath->values_len == ds->ds_num);
vl->values = values;
- for (i = 0; i < xpath->values_len; i++)
+ for (size_t i = 0; i < xpath->values_len; i++)
{
status = cx_handle_single_value_xpath (xpath_ctx, xpath, ds, vl, i);
if (status != 0)
static int cx_handle_base_xpath (char const *plugin_instance, /* {{{ */
char const *host,
- xmlXPathContextPtr xpath_ctx, const data_set_t *ds,
+ xmlXPathContextPtr xpath_ctx, const data_set_t *ds,
char *base_xpath, cx_xpath_t *xpath)
{
int total_nodes;
- int i;
xmlXPathObjectPtr base_node_obj = NULL;
xmlNodeSetPtr base_nodes = NULL;
value_list_t vl = VALUE_LIST_INIT;
- base_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST base_xpath);
+ base_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST base_xpath);
if (base_node_obj == NULL)
return -1; /* error is logged already */
}
/* If base_xpath returned multiple results, then */
- /* Instance in the xpath block is required */
+ /* Instance in the xpath block is required */
if (total_nodes > 1 && xpath->instance == NULL)
{
ERROR ("curl_xml plugin: "
vl.values_len = ds->ds_num;
sstrncpy (vl.type, xpath->type, sizeof (vl.type));
sstrncpy (vl.plugin, "curl_xml", sizeof (vl.plugin));
- sstrncpy (vl.host, (host != NULL) ? host : hostname_g, sizeof (vl.host));
+ sstrncpy (vl.host, host, sizeof (vl.host));
if (plugin_instance != NULL)
- sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- for (i = 0; i < total_nodes; i++)
+ for (int i = 0; i < total_nodes; i++)
{
int status;
} /* for (i = 0; i < total_nodes; i++) */
/* free up the allocated memory */
- xmlXPathFreeObject (base_node_obj);
+ xmlXPathFreeObject (base_node_obj);
- return (0);
+ return (0);
} /* }}} cx_handle_base_xpath */
-static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */
+static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */
xmlXPathContextPtr xpath_ctx, cx_t *db)
{
llentry_t *le;
const data_set_t *ds;
cx_xpath_t *xpath;
int status=-1;
-
+
le = llist_head (db->list);
while (le != NULL)
ds = plugin_get_ds (xpath->type);
if ( (cx_check_type(ds, xpath) == 0) &&
- (cx_handle_base_xpath(db->instance, db->host,
+ (cx_handle_base_xpath(db->instance, cx_host (db),
xpath_ctx, ds, le->key, xpath) == 0) )
status = 0; /* we got atleast one success */
int status;
xmlDocPtr doc;
xmlXPathContextPtr xpath_ctx;
- size_t i;
/* Load the XML */
doc = xmlParseDoc(xml);
return (-1);
}
- for (i = 0; i < db->namespaces_num; i++)
+ for (size_t i = 0; i < db->namespaces_num; i++)
{
cx_namespace_t const *ns = db->namespaces + i;
status = xmlXPathRegisterNs (xpath_ctx,
char *url;
url = db->url;
- db->buffer_fill = 0;
+ db->buffer_fill = 0;
status = curl_easy_perform (curl);
if (status != CURLE_OK)
{
status, db->curl_errbuf, url);
return (-1);
}
+ if (db->stats != NULL)
+ curl_stats_dispatch (db->stats, db->curl, cx_host (db), "curl_xml", db->instance);
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
static int cx_config_add_values (const char *name, cx_xpath_t *xpath, /* {{{ */
oconfig_item_t *ci)
{
- int i;
-
if (ci->values_num < 1)
{
WARNING ("curl_xml plugin: `ValuesFrom' needs at least one argument.");
return (-1);
}
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
if (ci->values[i].type != OCONFIG_TYPE_STRING)
{
WARNING ("curl_xml plugin: `ValuesFrom' needs only string argument.");
@@ -689,13 +694,13 @@ static int cx_config_add_values (const char *name, cx_xpath_t *xpath, /* {{{ */
sfree (xpath->values);
xpath->values_len = 0;
- xpath->values = (cx_values_t *) malloc (sizeof (cx_values_t) * ci->values_num);
+ xpath->values = malloc (sizeof (cx_values_t) * ci->values_num);
if (xpath->values == NULL)
return (-1);
- xpath->values_len = ci->values_num;
+ xpath->values_len = (size_t) ci->values_num;
/* populate cx_values_t structure */
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
xpath->values[i].path_len = sizeof (ci->values[i].value.string);
sstrncpy (xpath->values[i].path, ci->values[i].value.string, sizeof (xpath->values[i].path));
char *name;
llentry_t *le;
int status;
- int i;
- xpath = malloc (sizeof (*xpath));
+ xpath = calloc (1, sizeof (*xpath));
if (xpath == NULL)
{
- ERROR ("curl_xml plugin: malloc failed.");
+ ERROR ("curl_xml plugin: calloc failed.");
return (-1);
}
- memset (xpath, 0, sizeof (*xpath));
status = cf_util_get_string (ci, &xpath->path);
if (status != 0)
}
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (db->pass != NULL)
credentials_size += strlen (db->pass);
- db->credentials = (char *) malloc (credentials_size);
+ db->credentials = malloc (credentials_size);
if (db->credentials == NULL)
{
ERROR ("curl_xml plugin: malloc failed.");
if (db->timeout >= 0)
curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
else
- curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
#endif
return (0);
{
cx_t *db;
int status = 0;
- int i;
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_STRING))
return (-1);
}
- db = (cx_t *) malloc (sizeof (*db));
+ db = calloc (1, sizeof (*db));
if (db == NULL)
{
- ERROR ("curl_xml plugin: malloc failed.");
+ ERROR ("curl_xml plugin: calloc failed.");
return (-1);
}
- memset (db, 0, sizeof (*db));
db->timeout = -1;
}
/* Fill the `cx_t' structure.. */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
status = cx_config_add_namespace (db, child);
else if (strcasecmp ("Timeout", child->key) == 0)
status = cf_util_get_int (child, &db->timeout);
+ else if (strcasecmp ("Statistics", child->key) == 0)
+ {
+ db->stats = curl_stats_from_config (child);
+ if (db->stats == NULL)
+ status = -1;
+ }
else
{
WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);
/* If all went well, register this database for reading */
if (status == 0)
{
- user_data_t ud;
char *cb_name;
if (db->instance == NULL)
DEBUG ("curl_xml plugin: Registering new read callback: %s",
db->instance);
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) db;
- ud.free_func = cx_free;
-
cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url);
+
+ user_data_t ud = {
+ .data = db,
+ .free_func = cx_free
+ };
+
plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
sfree (cb_name);
}
else
int success;
int errors;
int status;
- int i;
success = 0;
errors = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 88fc7129598071150554b150d9a177b28265a242..cb62c645cd5216e2143c26323fc57e14f50ddb8c 100644 (file)
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
AM_CPPFLAGS = -I$(top_srcdir)/src
AM_CPPFLAGS += -DPREFIX='"${prefix}"'
AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
# Link to these libraries..
-COMMON_LIBS =
+COMMON_LIBS = $(PTHREAD_LIBS)
+if BUILD_WITH_CAPABILITY
+COMMON_LIBS += -lcap
+endif
if BUILD_WITH_LIBRT
COMMON_LIBS += -lrt
endif
if BUILD_WITH_LIBRESOLV
COMMON_LIBS += -lresolv
endif
-if BUILD_WITH_LIBPTHREAD
-COMMON_LIBS += -lpthread
-endif
if BUILD_WITH_LIBKSTAT
COMMON_LIBS += -lkstat
endif
COMMON_LIBS += -ldevinfo
endif
-AUTOMAKE_OPTIONS = subdir-objects
-
sbin_PROGRAMS = collectd
-noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libplugin_mock.la
+noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libmetadata.la libplugin_mock.la
libavltree_la_SOURCES = utils_avltree.c utils_avltree.h
libheap_la_SOURCES = utils_heap.c utils_heap.h
-libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
-libplugin_mock_la_LIBADD = $(COMMON_LIBS)
+libmetadata_la_SOURCES = meta_data.c meta_data.h
+
+libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c \
+ utils_time.c utils_time.h
+libplugin_mock_la_CPPFLAGS = $(AM_CPPFLAGS) -DMOCK_TIME
+libplugin_mock_la_LIBADD = $(COMMON_LIBS) libcommon.la
collectd_SOURCES = collectd.c collectd.h \
configfile.c configfile.h \
collectd_CFLAGS = $(AM_CFLAGS)
collectd_LDFLAGS = -export-dynamic
collectd_LDADD = libavltree.la libcommon.la libheap.la -lm $(COMMON_LIBS)
-collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la
+collectd_DEPENDENCIES = libavltree.la libcommon.la libheap.la libmetadata.la
# The daemon needs to call sg_init, so we need to link it against libstatgrab,
# too. -octo
collectd_LDADD += -loconfig
endif
-check_PROGRAMS = test_common test_utils_avltree test_utils_heap
-TESTS = test_common test_utils_avltree test_utils_heap
+LOG_COMPILER = env VALGRIND="@VALGRIND@" $(abs_top_srcdir)/testwrapper.sh
+
+check_PROGRAMS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
+TESTS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
test_common_SOURCES = common_test.c ../testing.h
-test_common_LDADD = libcommon.la libplugin_mock.la $(COMMON_LIBS)
+test_common_LDADD = libplugin_mock.la
+
+test_meta_data_SOURCES = meta_data_test.c ../testing.h
+test_meta_data_LDADD = libmetadata.la libplugin_mock.la
test_utils_avltree_SOURCES = utils_avltree_test.c ../testing.h
test_utils_avltree_LDADD = libavltree.la $(COMMON_LIBS)
test_utils_heap_SOURCES = utils_heap_test.c ../testing.h
test_utils_heap_LDADD = libheap.la $(COMMON_LIBS)
+
+test_utils_time_SOURCES = utils_time_test.c ../testing.h
+
+test_utils_subst_SOURCES = utils_subst_test.c ../testing.h \
+ utils_subst.c utils_subst.h
+test_utils_subst_LDADD = libplugin_mock.la
diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c
index 6e625bbb04cdc062f87335a45153523a6cf75c57..8573579166ab7e0aa13078d934ec92ffbf30324e 100644 (file)
--- a/src/daemon/collectd.c
+++ b/src/daemon/collectd.c
**/
#include "collectd.h"
-#include "common.h"
+#include "common.h"
#include "plugin.h"
#include "configfile.h"
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
-#include <pthread.h>
-
#if HAVE_LOCALE_H
# include <locale.h>
#endif
*/
char hostname_g[DATA_MAX_NAME_LEN];
cdtime_t interval_g;
-int pidfile_from_cli = 0;
int timeout_g;
#if HAVE_LIBKSTAT
kstat_ctl_t *kc;
{
const char *str;
- struct addrinfo ai_hints;
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
int status;
str = global_option_get ("Hostname");
if (IS_FALSE (str))
return (0);
- memset (&ai_hints, '\0', sizeof (ai_hints));
- ai_hints.ai_flags = AI_CANONNAME;
+ struct addrinfo ai_hints = {
+ .ai_flags = AI_CANONNAME
+ };
status = getaddrinfo (hostname_g, NULL, &ai_hints, &ai_list);
if (status != 0)
return (-1);
}
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
if (ai_ptr->ai_canonname == NULL)
continue;
while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
dir[--dirlen] = '\0';
- if (dirlen <= 0) {
+ if (dirlen == 0) {
free (dir);
return (-1);
}
/* TODO
* Remove all settings but `-f' and `-C'
*/
+__attribute__((noreturn))
static void exit_usage (int status)
{
printf ("Usage: "PACKAGE_NAME" [OPTIONS]\n\n"
}
#endif
- plugin_init_all ();
-
- return (0);
+ return plugin_init_all ();
} /* int do_init () */
static int do_shutdown (void)
{
- plugin_shutdown_all ();
- return (0);
+ return plugin_shutdown_all ();
} /* int do_shutdown */
#if COLLECT_DAEMON
#ifdef KERNEL_LINUX
static int notify_upstart (void)
{
- const char *upstart_job = getenv("UPSTART_JOB");
+ char const *upstart_job = getenv("UPSTART_JOB");
if (upstart_job == NULL)
return 0;
if (strcmp(upstart_job, "collectd") != 0)
+ {
+ WARNING ("Environment specifies unexpected UPSTART_JOB=\"%s\", expected \"collectd\". Ignoring the variable.", upstart_job);
return 0;
+ }
- WARNING ("supervised by upstart, will stop to signal readyness");
+ NOTICE("Upstart detected, stopping now to signal readyness.");
raise(SIGSTOP);
unsetenv("UPSTART_JOB");
static int notify_systemd (void)
{
- int fd = -1;
- const char *notifysocket = getenv("NOTIFY_SOCKET");
- struct sockaddr_un su;
- struct iovec iov;
- struct msghdr hdr;
+ int fd;
+ const char *notifysocket;
+ struct sockaddr_un su = { 0 };
+ size_t su_size;
+ char buffer[] = "READY=1\n";
+ notifysocket = getenv ("NOTIFY_SOCKET");
if (notifysocket == NULL)
return 0;
- if ((strchr("@/", notifysocket[0])) == NULL ||
- strlen(notifysocket) < 2)
+ if ((strlen (notifysocket) < 2)
+ || ((notifysocket[0] != '@') && (notifysocket[0] != '/')))
+ {
+ ERROR ("invalid notification socket NOTIFY_SOCKET=\"%s\": path must be absolute", notifysocket);
return 0;
+ }
+ NOTICE ("Systemd detected, trying to signal readyness.");
- WARNING ("supervised by systemd, will signal readyness");
- if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
- WARNING ("cannot contact systemd socket %s", notifysocket);
+ unsetenv ("NOTIFY_SOCKET");
+
+#if defined(SOCK_CLOEXEC)
+ fd = socket (AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, /* protocol = */ 0);
+#else
+ fd = socket (AF_UNIX, SOCK_DGRAM, /* protocol = */ 0);
+#endif
+ if (fd < 0) {
+ char errbuf[1024];
+ ERROR ("creating UNIX socket failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
return 0;
}
- bzero(&su, sizeof(su));
su.sun_family = AF_UNIX;
- sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
-
- if (notifysocket[0] == '@')
+ if (notifysocket[0] != '@')
+ {
+ /* regular UNIX socket */
+ sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path));
+ su_size = sizeof (su);
+ }
+ else
+ {
+ /* Linux abstract namespace socket: specify address as "\0foo", i.e.
+ * start with a null byte. Since null bytes have no special meaning in
+ * that case, we have to set su_size correctly to cover only the bytes
+ * that are part of the address. */
+ sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path));
su.sun_path[0] = 0;
+ su_size = sizeof (sa_family_t) + strlen (notifysocket);
+ if (su_size > sizeof (su))
+ su_size = sizeof (su);
+ }
- bzero(&iov, sizeof(iov));
- iov.iov_base = "READY=1";
- iov.iov_len = strlen("READY=1");
-
- bzero(&hdr, sizeof(hdr));
- hdr.msg_name = &su;
- hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
- strlen(notifysocket);
- hdr.msg_iov = &iov;
- hdr.msg_iovlen = 1;
-
- unsetenv("NOTIFY_SOCKET");
- if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
- WARNING ("cannot send notification to systemd");
+ if (sendto (fd, buffer, strlen (buffer), MSG_NOSIGNAL, (void *) &su, (socklen_t) su_size) < 0)
+ {
+ char errbuf[1024];
+ ERROR ("sendto(\"%s\") failed: %s", notifysocket,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
close(fd);
return 0;
}
+
+ unsetenv ("NOTIFY_SOCKET");
close(fd);
return 1;
}
int main (int argc, char **argv)
{
- struct sigaction sig_int_action;
- struct sigaction sig_term_action;
- struct sigaction sig_usr1_action;
- struct sigaction sig_pipe_action;
- char *configfile = CONFIGFILE;
+ const char *configfile = CONFIGFILE;
int test_config = 0;
int test_readall = 0;
const char *basedir;
#if COLLECT_DAEMON
- struct sigaction sig_chld_action;
pid_t pid;
int daemonize = 1;
#endif
break;
case 'T':
test_readall = 1;
- global_option_set ("ReadThreads", "-1");
+ global_option_set ("ReadThreads", "-1", 1);
#if COLLECT_DAEMON
daemonize = 0;
#endif /* COLLECT_DAEMON */
break;
#if COLLECT_DAEMON
case 'P':
- global_option_set ("PIDFile", optarg);
- pidfile_from_cli = 1;
+ global_option_set ("PIDFile", optarg, 1);
break;
case 'f':
daemonize = 0;
/*
* fork off child
*/
- memset (&sig_chld_action, '\0', sizeof (sig_chld_action));
- sig_chld_action.sa_handler = SIG_IGN;
+ struct sigaction sig_chld_action = {
+ .sa_handler = SIG_IGN
+ };
+
sigaction (SIGCHLD, &sig_chld_action, NULL);
/*
#endif
)
{
+ int status;
+
if ((pid = fork ()) == -1)
{
/* error */
close (1);
close (0);
- if (open ("/dev/null", O_RDWR) != 0)
+ status = open ("/dev/null", O_RDWR);
+ if (status != 0)
{
- ERROR ("Error: Could not connect `STDIN' to `/dev/null'");
+ ERROR ("Error: Could not connect `STDIN' to `/dev/null' (status %d)", status);
return (1);
}
- if (dup (0) != 1)
+
+ status = dup (0);
+ if (status != 1)
{
- ERROR ("Error: Could not connect `STDOUT' to `/dev/null'");
+ ERROR ("Error: Could not connect `STDOUT' to `/dev/null' (status %d)", status);
return (1);
}
- if (dup (0) != 2)
+
+ status = dup (0);
+ if (status != 2)
{
- ERROR ("Error: Could not connect `STDERR' to `/dev/null'");
+ ERROR ("Error: Could not connect `STDERR' to `/dev/null', (status %d)", status);
return (1);
}
} /* if (daemonize) */
#endif /* COLLECT_DAEMON */
- memset (&sig_pipe_action, '\0', sizeof (sig_pipe_action));
- sig_pipe_action.sa_handler = SIG_IGN;
+ struct sigaction sig_pipe_action = {
+ .sa_handler = SIG_IGN
+ };
+
sigaction (SIGPIPE, &sig_pipe_action, NULL);
/*
* install signal handlers
*/
- memset (&sig_int_action, '\0', sizeof (sig_int_action));
- sig_int_action.sa_handler = sig_int_handler;
+ struct sigaction sig_int_action = {
+ .sa_handler = sig_int_handler
+ };
+
if (0 != sigaction (SIGINT, &sig_int_action, NULL)) {
char errbuf[1024];
ERROR ("Error: Failed to install a signal handler for signal INT: %s",
return (1);
}
- memset (&sig_term_action, '\0', sizeof (sig_term_action));
- sig_term_action.sa_handler = sig_term_handler;
+ struct sigaction sig_term_action = {
+ .sa_handler = sig_term_handler
+ };
+
if (0 != sigaction (SIGTERM, &sig_term_action, NULL)) {
char errbuf[1024];
ERROR ("Error: Failed to install a signal handler for signal TERM: %s",
return (1);
}
- memset (&sig_usr1_action, '\0', sizeof (sig_usr1_action));
- sig_usr1_action.sa_handler = sig_usr1_handler;
+ struct sigaction sig_usr1_action = {
+ .sa_handler = sig_usr1_handler
+ };
+
if (0 != sigaction (SIGUSR1, &sig_usr1_action, NULL)) {
char errbuf[1024];
ERROR ("Error: Failed to install a signal handler for signal USR1: %s",
/*
* run the actual loops
*/
- do_init ();
+ if (do_init () != 0)
+ {
+ ERROR ("Error: one or more plugin init callbacks failed.");
+ exit_status = 1;
+ }
if (test_readall)
{
if (plugin_read_all_once () != 0)
+ {
+ ERROR ("Error: one or more plugin read callbacks failed.");
exit_status = 1;
+ }
}
else
{
/* close syslog */
INFO ("Exiting normally.");
- do_shutdown ();
+ if (do_shutdown () != 0)
+ {
+ ERROR ("Error: one or more plugin shutdown callbacks failed.");
+ exit_status = 1;
+ }
#if COLLECT_DAEMON
if (daemonize)
diff --git a/src/daemon/collectd.h b/src/daemon/collectd.h
index 80b753c8a83442b3e278858a8cb54528bf9868d1..3cb0c1bb62d340737a763841202655ebcb6f99c8 100644 (file)
--- a/src/daemon/collectd.h
+++ b/src/daemon/collectd.h
# include <time.h>
# endif
#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
#if HAVE_ASSERT_H
# include <assert.h>
#endif
#ifndef PACKAGE_NAME
-#define PACKAGE_NAME "collectd"
+# define PACKAGE_NAME "collectd"
#endif
#ifndef PREFIX
-#define PREFIX "/opt/" PACKAGE_NAME
+# define PREFIX "/opt/" PACKAGE_NAME
#endif
#ifndef SYSCONFDIR
-#define SYSCONFDIR PREFIX "/etc"
+# define SYSCONFDIR PREFIX "/etc"
#endif
#ifndef CONFIGFILE
-#define CONFIGFILE SYSCONFDIR"/collectd.conf"
+# define CONFIGFILE SYSCONFDIR"/collectd.conf"
#endif
#ifndef LOCALSTATEDIR
-#define LOCALSTATEDIR PREFIX "/var"
+# define LOCALSTATEDIR PREFIX "/var"
#endif
#ifndef PKGLOCALSTATEDIR
-#define PKGLOCALSTATEDIR PREFIX "/var/lib/" PACKAGE_NAME
+# define PKGLOCALSTATEDIR PREFIX "/var/lib/" PACKAGE_NAME
#endif
#ifndef PIDFILE
-#define PIDFILE PREFIX "/var/run/" PACKAGE_NAME ".pid"
+# define PIDFILE PREFIX "/var/run/" PACKAGE_NAME ".pid"
#endif
#ifndef PLUGINDIR
-#define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
+# define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
#endif
#ifndef PKGDATADIR
-#define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
+# define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
#endif
#ifndef COLLECTD_GRP_NAME
# define COLLECTD_DEFAULT_INTERVAL 10.0
#endif
- #ifndef COLLECTD_USERAGENT
- # define COLLECTD_USERAGENT PACKAGE_NAME"/"PACKAGE_VERSION
- #endif
+#ifndef COLLECTD_USERAGENT
+# define COLLECTD_USERAGENT PACKAGE_NAME "/" PACKAGE_VERSION
+#endif
/* Only enable __attribute__() for compilers known to support it. */
-#if defined(__clang__)
-# define clang_attr(x) __attribute__(x)
-# define gcc_attr(x) /**/
-#elif __GNUC__
-# define clang_attr(x) /**/
-# define gcc_attr(x) __attribute__(x)
-#else
-# define clang_attr(x) /**/
-# define gcc_attr(x) /**/
-# define __attribute__(x) /**/
+#if !defined(__clang__) && !defined(__GNUC__)
+# if !defined(__attribute__)
+# define __attribute__(x) /**/
+# endif
#endif
#if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
# pragma GCC poison strcpy strcat strtok
#endif
-/*
+/*
* Special hack for the perl plugin: Because the later included perl.h defines
* a macro which is never used, but contains `sprintf', we cannot poison that
* identifies just yet. The parl plugin will do that itself once perl.h is
extern char hostname_g[];
extern cdtime_t interval_g;
-extern int pidfile_from_cli;
extern int timeout_g;
#endif /* COLLECTD_H */
diff --git a/src/daemon/common.c b/src/daemon/common.c
index f54cb40d74a0737e8dc35e20224fe6086a50db1d..212d72c900b5d1c41b9df1e2a27bcb09e85f704b 100644 (file)
--- a/src/daemon/common.c
+++ b/src/daemon/common.c
#endif
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_cache.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
#ifdef HAVE_MATH_H
# include <math.h>
#endif
/* for getaddrinfo */
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
# include <netinet/in.h>
#endif
+#if HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+
/* for ntohl and htonl */
#if HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
+#if HAVE_CAPABILITY
+# include <sys/capability.h>
+#endif
+
#ifdef HAVE_LIBKSTAT
extern kstat_ctl_t *kc;
#endif
return (strdup (static_buffer));
/* Allocate a buffer large enough to hold the string. */
- alloc_buffer = malloc (alloc_buffer_size);
+ alloc_buffer = calloc (1, alloc_buffer_size);
if (alloc_buffer == NULL)
return (NULL);
- memset (alloc_buffer, 0, alloc_buffer_size);
/* Print again into this new buffer. */
va_start (ap, format);
/* Do not use `strdup' here, because it's not specified in POSIX. It's
* ``only'' an XSI extension. */
sz = strlen (s) + 1;
- r = (char *) malloc (sizeof (char) * sz);
+ r = malloc (sz);
if (r == NULL)
{
ERROR ("sstrdup: Out of memory.");
assert ((0 > status) || (nleft >= (size_t)status));
- nleft = nleft - status;
- ptr = ptr + status;
+ nleft = nleft - ((size_t) status);
+ ptr = ptr + ((size_t) status);
}
return (0);
ptr = (const char *) buf;
nleft = count;
+ if (fd < 0)
+ return (-1);
+
/* checking for closed peer connection */
pfd.fd = fd;
pfd.events = POLLIN | POLLHUP;
if (status < 0)
return (status);
- nleft = nleft - status;
- ptr = ptr + status;
+ nleft = nleft - ((size_t) status);
+ ptr = ptr + ((size_t) status);
}
return (0);
size_t avail;
char *ptr;
size_t sep_len;
- size_t i;
- if ((buffer_size < 1) || (fields_num <= 0))
+ if ((buffer_size < 1) || (fields_num == 0))
return (-1);
memset (buffer, 0, buffer_size);
if (sep != NULL)
sep_len = strlen (sep);
- for (i = 0; i < fields_num; i++)
+ for (size_t i = 0; i < fields_num; i++)
{
size_t field_len;
}
assert (buffer[buffer_size - 1] == 0);
- return (strlen (buffer));
+ return ((int) strlen (buffer));
}
-int strsubstitute (char *str, char c_from, char c_to)
-{
- int ret;
-
- if (str == NULL)
- return (-1);
-
- ret = 0;
- while (*str != '\0')
- {
- if (*str == c_from)
- {
- *str = c_to;
- ret++;
- }
- str++;
- }
-
- return (ret);
-} /* int strsubstitute */
-
int escape_string (char *buffer, size_t buffer_size)
{
char *temp;
- size_t i;
size_t j;
/* Check if we need to escape at all first */
if (buffer_size < 3)
return (EINVAL);
- temp = (char *) malloc (buffer_size);
+ temp = calloc (1, buffer_size);
if (temp == NULL)
return (ENOMEM);
- memset (temp, 0, buffer_size);
temp[0] = '"';
j = 1;
- for (i = 0; i < buffer_size; i++)
+ for (size_t i = 0; i < buffer_size; i++)
{
if (buffer[i] == 0)
{
int strunescape (char *buf, size_t buf_len)
{
- size_t i;
-
- for (i = 0; (i < buf_len) && (buf[i] != '\0'); ++i)
+ for (size_t i = 0; (i < buf_len) && (buf[i] != '\0'); ++i)
{
if (buf[i] != '\\')
continue;
int escape_slashes (char *buffer, size_t buffer_size)
{
- int i;
size_t buffer_len;
buffer_len = strlen (buffer);
buffer_len--;
}
- for (i = 0; i < buffer_len; i++)
+ for (size_t i = 0; i < buffer_len; i++)
{
if (buffer[i] == '/')
buffer[i] = '_';
void replace_special (char *buffer, size_t buffer_size)
{
- size_t i;
-
- for (i = 0; i < buffer_size; i++)
+ for (size_t i = 0; i < buffer_size; i++)
{
if (buffer[i] == 0)
return;
int last_is_file = 1;
int path_is_absolute = 0;
size_t len;
- int i;
/*
* Sanity checks first
/*
* For each component, do..
*/
- for (i = 0; i < (fields_num - last_is_file); i++)
+ for (int i = 0; i < (fields_num - last_is_file); i++)
{
/*
* Do not create directories that start with a dot. This
* Join the components together again
*/
dir[0] = '/';
- if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute,
- fields, i + 1, "/") < 0)
+ if (strjoin (dir + path_is_absolute, (size_t) (dir_len - path_is_absolute),
+ fields, (size_t) (i + 1), "/") < 0)
{
ERROR ("strjoin failed: `%s', component #%i", file_orig, i);
return (-1);
{
size_t offset = 0;
int status;
- int i;
gauge_t *rates = NULL;
assert (0 == strcmp (ds->type, vl->type));
BUFFER_ADD ("%.3f", CDTIME_T_TO_DOUBLE (vl->time));
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if (ds->ds[i].type == DS_TYPE_GAUGE)
BUFFER_ADD (":"GAUGE_FORMAT, vl->values[i].gauge);
int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
{
- int i;
+ size_t i;
char *dummy;
char *ptr;
char *saveptr;
if ((buffer == NULL) || (vl == NULL) || (ds == NULL))
return EINVAL;
- i = -1;
+ i = 0;
dummy = buffer;
saveptr = NULL;
+ vl->time = 0;
while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL)
{
dummy = NULL;
if (i >= vl->values_len)
{
/* Make sure i is invalid. */
- i = vl->values_len + 1;
+ i = 0;
break;
}
- if (i == -1)
+ if (vl->time == 0)
{
if (strcmp ("N", ptr) == 0)
vl->time = cdtime ();
vl->time = DOUBLE_TO_CDTIME_T (tmp);
}
+
+ continue;
}
- else
- {
- if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
- vl->values[i].gauge = NAN;
- else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
- return -1;
- }
+
+ if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
+ vl->values[i].gauge = NAN;
+ else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
+ return -1;
i++;
} /* while (strtok_r) */
- if ((ptr != NULL) || (i != vl->values_len))
+ if ((ptr != NULL) || (i == 0))
return (-1);
return (0);
} /* int parse_values */
if (old_value > new_value)
{
if (old_value <= 4294967295U)
- diff = (4294967295U - old_value) + new_value;
+ diff = (4294967295U - old_value) + new_value + 1;
else
- diff = (18446744073709551615ULL - old_value)
- + new_value;
+ diff = (18446744073709551615ULL - old_value) + new_value + 1;
}
else
{
return (0);
} /* }}} value_t rate_to_value */
-int value_to_rate (value_t *ret_rate, derive_t value, /* {{{ */
- value_to_rate_state_t *state,
- int ds_type, cdtime_t t)
+int value_to_rate (gauge_t *ret_rate, /* {{{ */
+ value_t value, int ds_type, cdtime_t t, value_to_rate_state_t *state)
{
- double interval;
+ gauge_t interval;
/* Another invalid state: The time is not increasing. */
if (t <= state->last_time)
interval = CDTIME_T_TO_DOUBLE(t - state->last_time);
/* Previous value is invalid. */
- if (state->last_time == 0) /* {{{ */
+ if (state->last_time == 0)
{
- if (ds_type == DS_TYPE_DERIVE)
- {
- state->last_value.derive = value;
- }
- else if (ds_type == DS_TYPE_COUNTER)
- {
- state->last_value.counter = (counter_t) value;
- }
- else if (ds_type == DS_TYPE_ABSOLUTE)
- {
- state->last_value.absolute = (absolute_t) value;
- }
- else
- {
- assert (23 == 42);
- }
-
+ state->last_value = value;
state->last_time = t;
return (EAGAIN);
- } /* }}} */
+ }
- if (ds_type == DS_TYPE_DERIVE)
- {
- ret_rate->gauge = (value - state->last_value.derive) / interval;
- state->last_value.derive = value;
+ switch (ds_type) {
+ case DS_TYPE_DERIVE: {
+ derive_t diff = value.derive - state->last_value.derive;
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
}
- else if (ds_type == DS_TYPE_COUNTER)
- {
- ret_rate->gauge = (((counter_t)value) - state->last_value.counter) / interval;
- state->last_value.counter = (counter_t) value;
+ case DS_TYPE_GAUGE: {
+ *ret_rate = value.gauge;
+ break;
}
- else if (ds_type == DS_TYPE_ABSOLUTE)
- {
- ret_rate->gauge = (((absolute_t)value) - state->last_value.absolute) / interval;
- state->last_value.absolute = (absolute_t) value;
+ case DS_TYPE_COUNTER: {
+ counter_t diff = counter_diff (state->last_value.counter, value.counter);
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
}
- else
- {
- assert (23 == 42);
+ case DS_TYPE_ABSOLUTE: {
+ absolute_t diff = value.absolute;
+ *ret_rate = ((gauge_t) diff) / ((gauge_t) interval);
+ break;
+ }
+ default:
+ return EINVAL;
}
- state->last_time = t;
+ state->last_value = value;
+ state->last_time = t;
return (0);
} /* }}} value_t rate_to_value */
int service_name_to_port_number (const char *service_name)
{
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
- struct addrinfo ai_hints;
int status;
int service_number;
if (service_name == NULL)
return (-1);
- ai_list = NULL;
- memset (&ai_hints, 0, sizeof (ai_hints));
- ai_hints.ai_family = AF_UNSPEC;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC
+ };
status = getaddrinfo (/* node = */ NULL, service_name,
&ai_hints, &ai_list);
}
service_number = -1;
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
if (ai_ptr->ai_family == AF_INET)
{
return (-1);
} /* int service_name_to_port_number */
+void set_sock_opts (int sockfd) /* {{{ */
+{
+ int status;
+ int socktype;
+
+ socklen_t socklen = sizeof (socklen_t);
+ int so_keepalive = 1;
+
+ status = getsockopt (sockfd, SOL_SOCKET, SO_TYPE, &socktype, &socklen);
+ if (status != 0)
+ {
+ WARNING ("set_sock_opts: failed to determine socket type");
+ return;
+ }
+
+ if (socktype == SOCK_STREAM)
+ {
+ status = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
+ &so_keepalive, sizeof (so_keepalive));
+ if (status != 0)
+ WARNING ("set_sock_opts: failed to set socket keepalive flag");
+
+#ifdef TCP_KEEPIDLE
+ int tcp_keepidle = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 100 + 1);
+ status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
+ &tcp_keepidle, sizeof (tcp_keepidle));
+ if (status != 0)
+ WARNING ("set_sock_opts: failed to set socket tcp keepalive time");
+#endif
+
+#ifdef TCP_KEEPINTVL
+ int tcp_keepintvl = ((CDTIME_T_TO_MS(plugin_get_interval()) - 1) / 1000 + 1);
+ status = setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
+ &tcp_keepintvl, sizeof (tcp_keepintvl));
+ if (status != 0)
+ WARNING ("set_sock_opts: failed to set socket tcp keepalive interval");
+#endif
+ }
+} /* }}} void set_sock_opts */
+
int strtoderive (const char *string, derive_t *ret_value) /* {{{ */
{
derive_t tmp;
@@ -1672,9 +1673,30 @@ int strarray_add (char ***ret_array, size_t *ret_array_len, char const *str) /*
void strarray_free (char **array, size_t array_len) /* {{{ */
{
- size_t i;
-
- for (i = 0; i < array_len; i++)
+ for (size_t i = 0; i < array_len; i++)
sfree (array[i]);
sfree (array);
} /* }}} void strarray_free */
+
+#if HAVE_CAPABILITY
+int check_capability (int arg) /* {{{ */
+{
+ cap_value_t cap = (cap_value_t) arg;
+
+ if (!CAP_IS_SUPPORTED (cap))
+ return (-1);
+
+ int have_cap = cap_get_bound (cap);
+ if (have_cap != 1)
+ return (-1);
+
+ return (0);
+} /* }}} int check_capability */
+#else
+int check_capability (__attribute__((unused)) int arg) /* {{{ */
+{
+ WARNING ("check_capability: unsupported capability implementation. "
+ "Some plugin(s) may require elevated privileges to work properly.");
+ return (0);
+} /* }}} int check_capability */
+#endif /* HAVE_CAPABILITY */
diff --git a/src/daemon/common.h b/src/daemon/common.h
index da21cad9a6f3a81f1120b466740a669ec009c231..720e5f1bc0a408f097fe1d586b5bbb26dda9bcce 100644 (file)
--- a/src/daemon/common.h
+++ b/src/daemon/common.h
#define COMMON_H
#include "collectd.h"
+
#include "plugin.h"
#if HAVE_PWD_H
#define sfree(ptr) \
do { \
- if((ptr) != NULL) { \
- free(ptr); \
- } \
+ free(ptr); \
(ptr) = NULL; \
} while (0)
*/
void replace_special (char *buffer, size_t buffer_size);
-int strsubstitute (char *str, char c_from, char c_to);
-
/*
* NAME
* strunescape
int rate_to_value (value_t *ret_value, gauge_t rate,
rate_to_value_state_t *state, int ds_type, cdtime_t t);
-int value_to_rate (value_t *ret_rate, derive_t value,
- value_to_rate_state_t *state, int ds_type, cdtime_t t);
+int value_to_rate (gauge_t *ret_rate, value_t value, int ds_type, cdtime_t t,
+ value_to_rate_state_t *state);
/* Converts a service name (a string) to a port number
* (in the range [1-65535]). Returns less than zero on error. */
int service_name_to_port_number (const char *service_name);
+/* Sets various, non-default, socket options */
+void set_sock_opts (int sockfd);
+
/** Parse a string to a derive_t value. Returns zero on success or non-zero on
* failure. If failure is returned, ret_value is not touched. */
int strtoderive (const char *string, derive_t *ret_value);
int strarray_add (char ***ret_array, size_t *ret_array_len, char const *str);
void strarray_free (char **array, size_t array_len);
+#ifdef HAVE_SYS_CAPABILITY_H
+/** Check if the current process benefits from the capability passed in
+ * argument. Returns zero if it does, less than zero if it doesn't or on error.
+ * See capabilities(7) for the list of possible capabilities.
+ * */
+int check_capability (int capability);
+#endif /* HAVE_SYS_CAPABILITY_H */
+
#endif /* COMMON_H */
index 39ea5774d6ab68ef0623bd2c6dfacd2104d877e0..202ddf6cd3ab82aa0af180edf40a44e794908376 100644 (file)
--- a/src/daemon/common_test.c
+++ b/src/daemon/common_test.c
* Florian octo Forster <octo at collectd.org>
*/
-#include "testing.h"
#include "common.h"
+#include "testing.h"
#if HAVE_LIBKSTAT
kstat_ctl_t *kc;
ret = sstrncpy (ptr, "foobar", 8);
OK(ret == ptr);
- STREQ ("foobar", ptr);
+ EXPECT_EQ_STR ("foobar", ptr);
OK(buffer[3] == buffer[12]);
ret = sstrncpy (ptr, "abc", 8);
OK(ret == ptr);
- STREQ ("abc", ptr);
+ EXPECT_EQ_STR ("abc", ptr);
OK(buffer[3] == buffer[12]);
ret = sstrncpy (ptr, "collectd", 8);
OK(ret == ptr);
OK(ptr[7] == 0);
- STREQ ("collect", ptr);
+ EXPECT_EQ_STR ("collect", ptr);
OK(buffer[3] == buffer[12]);
return (0);
status = ssnprintf (ptr, 8, "%i", 1337);
OK(status == 4);
- STREQ ("1337", ptr);
+ EXPECT_EQ_STR ("1337", ptr);
status = ssnprintf (ptr, 8, "%s", "collectd");
OK(status == 8);
OK(ptr[7] == 0);
- STREQ ("collect", ptr);
+ EXPECT_EQ_STR ("collect", ptr);
OK(buffer[3] == buffer[12]);
return (0);
ptr = sstrdup ("collectd");
OK(ptr != NULL);
- STREQ ("collectd", ptr);
+ EXPECT_EQ_STR ("collectd", ptr);
sfree(ptr);
- OK(ptr == NULL);
ptr = sstrdup (NULL);
OK(ptr == NULL);
strncpy (buffer, "foo bar", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("foo", fields[0]);
- STREQ ("bar", fields[1]);
+ EXPECT_EQ_STR ("foo", fields[0]);
+ EXPECT_EQ_STR ("bar", fields[1]);
strncpy (buffer, "foo \t bar", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("foo", fields[0]);
- STREQ ("bar", fields[1]);
+ EXPECT_EQ_STR ("foo", fields[0]);
+ EXPECT_EQ_STR ("bar", fields[1]);
strncpy (buffer, "one two\tthree\rfour\nfive", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 5);
- STREQ ("one", fields[0]);
- STREQ ("two", fields[1]);
- STREQ ("three", fields[2]);
- STREQ ("four", fields[3]);
- STREQ ("five", fields[4]);
+ EXPECT_EQ_STR ("one", fields[0]);
+ EXPECT_EQ_STR ("two", fields[1]);
+ EXPECT_EQ_STR ("three", fields[2]);
+ EXPECT_EQ_STR ("four", fields[3]);
+ EXPECT_EQ_STR ("five", fields[4]);
strncpy (buffer, "\twith trailing\n", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 2);
- STREQ ("with", fields[0]);
- STREQ ("trailing", fields[1]);
+ EXPECT_EQ_STR ("with", fields[0]);
+ EXPECT_EQ_STR ("trailing", fields[1]);
strncpy (buffer, "1 2 3 4 5 6 7 8 9 10 11 12 13", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 8);
- STREQ ("7", fields[6]);
- STREQ ("8", fields[7]);
+ EXPECT_EQ_STR ("7", fields[6]);
+ EXPECT_EQ_STR ("8", fields[7]);
strncpy (buffer, "single", sizeof (buffer));
status = strsplit (buffer, fields, 8);
OK(status == 1);
- STREQ ("single", fields[0]);
+ EXPECT_EQ_STR ("single", fields[0]);
strncpy (buffer, "", sizeof (buffer));
status = strsplit (buffer, fields, 8);
status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
OK(status == 7);
- STREQ ("foo!bar", buffer);
+ EXPECT_EQ_STR ("foo!bar", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
OK(status == 3);
- STREQ ("foo", buffer);
+ EXPECT_EQ_STR ("foo", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 0, "!");
OK(status < 0);
status = strjoin (buffer, sizeof (buffer), fields, 2, "rcht");
OK(status == 10);
- STREQ ("foorchtbar", buffer);
+ EXPECT_EQ_STR ("foorchtbar", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 4, "");
OK(status == 12);
- STREQ ("foobarbazqux", buffer);
+ EXPECT_EQ_STR ("foobarbazqux", buffer);
status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
OK(status == 15);
- STREQ ("foo!bar!baz!qux", buffer);
+ EXPECT_EQ_STR ("foo!bar!baz!qux", buffer);
fields[0] = "0123";
fields[1] = "4567";
return (0);
}
+DEF_TEST(escape_slashes)
+{
+ struct {
+ char *str;
+ char *want;
+ } cases[] = {
+ {"foo/bar/baz", "foo_bar_baz"},
+ {"/like/a/path", "like_a_path"},
+ {"trailing/slash/", "trailing_slash_"},
+ {"foo//bar", "foo__bar"},
+ };
+
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[32];
+
+ strncpy (buffer, cases[i].str, sizeof (buffer));
+ OK(escape_slashes (buffer, sizeof (buffer)) == 0);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+DEF_TEST(escape_string)
+{
+ struct {
+ char *str;
+ char *want;
+ } cases[] = {
+ {"foobar", "foobar"},
+ {"f00bar", "f00bar"},
+ {"foo bar", "\"foo bar\""},
+ {"foo \"bar\"", "\"foo \\\"bar\\\"\""},
+ {"012345678901234", "012345678901234"},
+ {"012345 78901234", "\"012345 789012\""},
+ {"012345 78901\"34", "\"012345 78901\""},
+ };
+
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16];
+
+ strncpy (buffer, cases[i].str, sizeof (buffer));
+ OK(escape_string (buffer, sizeof (buffer)) == 0);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
DEF_TEST(strunescape)
{
char buffer[16];
strncpy (buffer, "foo\\tbar", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("foo\tbar", buffer);
+ EXPECT_EQ_STR ("foo\tbar", buffer);
strncpy (buffer, "\\tfoo\\r\\n", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("\tfoo\r\n", buffer);
+ EXPECT_EQ_STR ("\tfoo\r\n", buffer);
strncpy (buffer, "With \\\"quotes\\\"", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status == 0);
- STREQ ("With \"quotes\"", buffer);
+ EXPECT_EQ_STR ("With \"quotes\"", buffer);
/* Backslash before null byte */
strncpy (buffer, "\\tbackslash end\\", sizeof (buffer));
status = strunescape (buffer, sizeof (buffer));
OK(status != 0);
- STREQ ("\tbackslash end", buffer);
+ EXPECT_EQ_STR ("\tbackslash end", buffer);
return (0);
/* Backslash at buffer end */
return (0);
}
+DEF_TEST(parse_values)
+{
+ struct {
+ char buffer[64];
+ int status;
+ gauge_t value;
+ } cases[] = {
+ {"1435044576:42", 0, 42.0},
+ {"1435044576:42:23", -1, NAN},
+ {"1435044576:U", 0, NAN},
+ {"N:12.3", 0, 12.3},
+ {"N:42.0:23", -1, NAN},
+ {"N:U", 0, NAN},
+ {"T:42.0", -1, NAN},
+ };
+
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ data_source_t dsrc = {
+ .name = "value",
+ .type = DS_TYPE_GAUGE,
+ .min = 0.0,
+ .max = NAN,
+ };
+ data_set_t ds = {
+ .type = "example",
+ .ds_num = 1,
+ .ds = &dsrc,
+ };
+
+ value_t v = {
+ .gauge = NAN,
+ };
+ value_list_t vl = {
+ .values = &v,
+ .values_len = 1,
+ .time = 0,
+ .interval = 0,
+ .host = "example.com",
+ .plugin = "common_test",
+ .type = "example",
+ .meta = NULL,
+ };
+
+ int status = parse_values (cases[i].buffer, &vl, &ds);
+ EXPECT_EQ_INT (cases[i].status, status);
+ if (status != 0)
+ continue;
+
+ EXPECT_EQ_DOUBLE (cases[i].value, vl.values[0].gauge);
+ }
+
+ return (0);
+}
+
+DEF_TEST(value_to_rate)
+{
+ struct {
+ time_t t0;
+ time_t t1;
+ int ds_type;
+ value_t v0;
+ value_t v1;
+ gauge_t want;
+ } cases[] = {
+ { 0, 10, DS_TYPE_DERIVE, {.derive = 0}, {.derive = 1000}, NAN},
+ {10, 20, DS_TYPE_DERIVE, {.derive = 1000}, {.derive = 2000}, 100.0},
+ {20, 30, DS_TYPE_DERIVE, {.derive = 2000}, {.derive = 1800}, -20.0},
+ { 0, 10, DS_TYPE_COUNTER, {.counter = 0}, {.counter = 1000}, NAN},
+ {10, 20, DS_TYPE_COUNTER, {.counter = 1000}, {.counter = 5000}, 400.0},
+ /* 32bit wrap-around. */
+ {20, 30, DS_TYPE_COUNTER, {.counter = 4294967238ULL}, {.counter = 42}, 10.0},
+ /* 64bit wrap-around. */
+ {30, 40, DS_TYPE_COUNTER, {.counter = 18446744073709551558ULL}, {.counter = 42}, 10.0},
+ };
+
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ value_to_rate_state_t state = { cases[i].v0, TIME_T_TO_CDTIME_T (cases[i].t0) };
+ gauge_t got;
+
+ if (cases[i].t0 == 0) {
+ OK(value_to_rate (&got, cases[i].v1, cases[i].ds_type, TIME_T_TO_CDTIME_T(cases[i].t1), &state) == EAGAIN);
+ continue;
+ }
+
+ OK(value_to_rate (&got, cases[i].v1, cases[i].ds_type, TIME_T_TO_CDTIME_T(cases[i].t1), &state) == 0);
+ EXPECT_EQ_DOUBLE(cases[i].want, got);
+ }
+
+ return 0;
+}
+
int main (void)
{
RUN_TEST(sstrncpy);
RUN_TEST(sstrdup);
RUN_TEST(strsplit);
RUN_TEST(strjoin);
+ RUN_TEST(escape_slashes);
+ RUN_TEST(escape_string);
RUN_TEST(strunescape);
+ RUN_TEST(parse_values);
+ RUN_TEST(value_to_rate);
END_TEST;
}
index 16e07247b3cf56d07937d677c1eddf861c5c2655..a31fb64d17781854d015236155c6a833eae8c186 100644 (file)
--- a/src/daemon/configfile.c
+++ b/src/daemon/configfile.c
typedef struct cf_value_map_s
{
- char *key;
+ const char *key;
int (*func) (oconfig_item_t *);
} cf_value_map_t;
typedef struct cf_global_option_s
{
- char *key;
+ const char *key;
char *value;
- char *def;
+ _Bool from_cli; /* value set from CLI */
+ const char *def;
} cf_global_option_t;
/*
static cf_global_option_t cf_global_options[] =
{
- {"BaseDir", NULL, PKGLOCALSTATEDIR},
- {"PIDFile", NULL, PIDFILE},
- {"Hostname", NULL, NULL},
- {"FQDNLookup", NULL, "true"},
- {"Interval", NULL, NULL},
- {"ReadThreads", NULL, "5"},
- {"WriteThreads", NULL, "5"},
- {"WriteQueueLimitHigh", NULL, NULL},
- {"WriteQueueLimitLow", NULL, NULL},
- {"Timeout", NULL, "2"},
- {"AutoLoadPlugin", NULL, "false"},
- {"CollectInternalStats", NULL, "false"},
- {"PreCacheChain", NULL, "PreCache"},
- {"PostCacheChain", NULL, "PostCache"},
- {"MaxReadInterval", NULL, "86400"}
+ {"BaseDir", NULL, 0, PKGLOCALSTATEDIR},
+ {"PIDFile", NULL, 0, PIDFILE},
+ {"Hostname", NULL, 0, NULL},
+ {"FQDNLookup", NULL, 0, "true"},
+ {"Interval", NULL, 0, NULL},
+ {"ReadThreads", NULL, 0, "5"},
+ {"WriteThreads", NULL, 0, "5"},
+ {"WriteQueueLimitHigh", NULL, 0, NULL},
+ {"WriteQueueLimitLow", NULL, 0, NULL},
+ {"Timeout", NULL, 0, "2"},
+ {"AutoLoadPlugin", NULL, 0, "false"},
+ {"CollectInternalStats", NULL, 0, "false"},
+ {"PreCacheChain", NULL, 0, "PreCache"},
+ {"PostCacheChain", NULL, 0, "PostCache"},
+ {"MaxReadInterval", NULL, 0, "86400"}
};
static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options);
char *key;
char *value;
int ret;
- int i;
+ int i = 0;
if (orig_key == NULL)
return (EINVAL);
if (ci->values_num != 1)
return (-1);
if (ci->values[0].type == OCONFIG_TYPE_STRING)
- return (global_option_set (ci->key, ci->values[0].value.string));
+ return (global_option_set (ci->key, ci->values[0].value.string, 0));
else if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
{
char tmp[128];
ssnprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number);
- return (global_option_set (ci->key, tmp));
+ return (global_option_set (ci->key, tmp, 0));
}
else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
{
if (ci->values[0].value.boolean)
- return (global_option_set (ci->key, "true"));
+ return (global_option_set (ci->key, "true", 0));
else
- return (global_option_set (ci->key, "false"));
+ return (global_option_set (ci->key, "false", 0));
}
return (-1);
static int dispatch_value_typesdb (oconfig_item_t *ci)
{
- int i = 0;
-
assert (strcasecmp (ci->key, "TypesDB") == 0);
cf_default_typesdb = 0;
return (-1);
}
- for (i = 0; i < ci->values_num; ++i)
+ for (int i = 0; i < ci->values_num; ++i)
{
if (OCONFIG_TYPE_STRING != ci->values[i].type) {
WARNING ("configfile: TypesDB: Skipping %i. argument which "
static int dispatch_value_plugindir (oconfig_item_t *ci)
{
assert (strcasecmp (ci->key, "PluginDir") == 0);
-
+
if (ci->values_num != 1)
return (-1);
if (ci->values[0].type != OCONFIG_TYPE_STRING)
static int dispatch_loadplugin (oconfig_item_t *ci)
{
- int i;
const char *name;
unsigned int flags = 0;
- plugin_ctx_t ctx;
+ plugin_ctx_t ctx = { 0 };
plugin_ctx_t old_ctx;
int ret_val;
name = "virt";
/* default to the global interval set before loading this plugin */
- memset (&ctx, 0, sizeof (ctx));
ctx.interval = cf_get_default_interval ();
+ ctx.flush_interval = 0;
+ ctx.flush_timeout = 0;
- for (i = 0; i < ci->children_num; ++i) {
- if (strcasecmp("Globals", ci->children[i].key) == 0)
- cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL);
- else if (strcasecmp ("Interval", ci->children[i].key) == 0) {
- if (cf_util_get_cdtime (ci->children + i, &ctx.interval) != 0) {
- /* cf_util_get_cdtime will log an error */
- continue;
- }
- }
+ for (int i = 0; i < ci->children_num; ++i)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp("Globals", child->key) == 0)
+ cf_util_get_flag (child, &flags, PLUGIN_FLAGS_GLOBAL);
+ else if (strcasecmp ("Interval", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.interval);
+ else if (strcasecmp ("FlushInterval", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.flush_interval);
+ else if (strcasecmp ("FlushTimeout", child->key) == 0)
+ cf_util_get_cdtime (child, &ctx.flush_timeout);
else {
WARNING("Ignoring unknown LoadPlugin option \"%s\" "
"for plugin \"%s\"",
- ci->children[i].key, ci->values[0].value.string);
+ child->key, ci->values[0].value.string);
}
}
char buffer[4096];
char *buffer_ptr;
int buffer_free;
- int i;
buffer_ptr = buffer;
buffer_free = sizeof (buffer);
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
int status = -1;
static int dispatch_value (oconfig_item_t *ci)
{
- int ret = -2;
- int i;
+ int ret = 0;
- for (i = 0; i < cf_value_map_num; i++)
+ for (int i = 0; i < cf_value_map_num; i++)
if (strcasecmp (cf_value_map[i].key, ci->key) == 0)
{
ret = cf_value_map[i].func (ci);
break;
}
- for (i = 0; i < cf_global_options_num; i++)
+ for (int i = 0; i < cf_global_options_num; i++)
if (strcasecmp (cf_global_options[i].key, ci->key) == 0)
{
ret = dispatch_global_option (ci);
static int dispatch_block_plugin (oconfig_item_t *ci)
{
- int i;
- char *name;
-
- cf_complex_callback_t *cb;
+ const char *name;
if (strcasecmp (ci->key, "Plugin") != 0)
return (-1);
if (IS_TRUE (global_option_get ("AutoLoadPlugin")))
{
- plugin_ctx_t ctx;
+ plugin_ctx_t ctx = { 0 };
plugin_ctx_t old_ctx;
int status;
/* default to the global interval set before loading this plugin */
- memset (&ctx, 0, sizeof (ctx));
ctx.interval = cf_get_default_interval ();
old_ctx = plugin_set_ctx (ctx);
}
/* Check for a complex callback first */
- for (cb = complex_callback_head; cb != NULL; cb = cb->next)
+ for (cf_complex_callback_t *cb = complex_callback_head; cb != NULL; cb = cb->next)
{
if (strcasecmp (name, cb->type) == 0)
{
}
/* Hm, no complex plugin found. Dispatch the values one by one */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
if (ci->children[i].children == NULL)
dispatch_value_plugin (name, ci->children + i);
int offset)
{
oconfig_item_t *temp;
- int i;
assert (offset >= 0);
assert (dst->children_num > offset);
/* Free the memory used by the replaced child. Usually that's the
* `Include "blah"' statement. */
temp = dst->children + offset;
- for (i = 0; i < temp->values_num; i++)
+ for (int i = 0; i < temp->values_num; i++)
{
if (temp->values[i].type == OCONFIG_TYPE_STRING)
{
return (0);
}
- temp = (oconfig_item_t *) realloc (dst->children,
+ temp = realloc (dst->children,
sizeof (oconfig_item_t)
* (dst->children_num + src->children_num - 1));
if (temp == NULL)
if ((src == NULL) || (src->children_num == 0))
return (0);
- temp = (oconfig_item_t *) realloc (dst->children,
+ temp = realloc (dst->children,
sizeof (oconfig_item_t)
* (dst->children_num + src->children_num));
if (temp == NULL)
static int cf_include_all (oconfig_item_t *root, int depth)
{
- int i;
-
- for (i = 0; i < root->children_num; i++)
+ for (int i = 0; i < root->children_num; i++)
{
oconfig_item_t *new;
oconfig_item_t *old;
char *pattern = NULL;
- int j;
-
if (strcasecmp (root->children[i].key, "Include") != 0)
continue;
continue;
}
- for (j = 0; j < old->children_num; ++j)
+ for (int j = 0; j < old->children_num; ++j)
{
oconfig_item_t *child = old->children + j;
char **filenames = NULL;
int filenames_num = 0;
int status;
- int i;
assert (depth < CF_MAX_DEPTH);
return (NULL);
}
- root = (oconfig_item_t *) malloc (sizeof (oconfig_item_t));
+ root = calloc (1, sizeof (*root));
if (root == NULL)
{
- ERROR ("configfile: malloc failed.");
+ ERROR ("configfile: calloc failed.");
closedir (dh);
return (NULL);
}
- memset (root, 0, sizeof (oconfig_item_t));
while ((de = readdir (dh)) != NULL)
{
" name is too long.",
dir, de->d_name);
closedir (dh);
- for (i = 0; i < filenames_num; ++i)
+ for (int i = 0; i < filenames_num; ++i)
free (filenames[i]);
free (filenames);
free (root);
}
++filenames_num;
- tmp = (char **) realloc (filenames,
+ tmp = realloc (filenames,
filenames_num * sizeof (*filenames));
if (tmp == NULL) {
ERROR ("configfile: realloc failed.");
closedir (dh);
- for (i = 0; i < filenames_num - 1; ++i)
+ for (int i = 0; i < filenames_num - 1; ++i)
free (filenames[i]);
free (filenames);
free (root);
qsort ((void *) filenames, filenames_num, sizeof (*filenames),
cf_compare_string);
- for (i = 0; i < filenames_num; ++i)
+ for (int i = 0; i < filenames_num; ++i)
{
oconfig_item_t *temp;
char *name = filenames[i];
*
* There are two versions of this function: If `wordexp' exists shell wildcards
* will be expanded and the function will include all matches found. If
- * `wordexp' (or, more precisely, it's header file) is not available the
+ * `wordexp' (or, more precisely, its header file) is not available the
* simpler function is used which does not do any such expansion.
*/
#if HAVE_WORDEXP_H
int status;
const char *path_ptr;
wordexp_t we;
- size_t i;
if (depth >= CF_MAX_DEPTH)
{
return (NULL);
}
- root = (oconfig_item_t *) malloc (sizeof (oconfig_item_t));
+ root = calloc (1, sizeof (*root));
if (root == NULL)
{
- ERROR ("configfile: malloc failed.");
+ ERROR ("configfile: calloc failed.");
return (NULL);
}
- memset (root, '\0', sizeof (oconfig_item_t));
/* wordexp() might return a sorted list already. That's not
* documented though, so let's make sure we get what we want. */
qsort ((void *) we.we_wordv, we.we_wordc, sizeof (*we.we_wordv),
cf_compare_string);
- for (i = 0; i < we.we_wordc; i++)
+ for (size_t i = 0; i < we.we_wordc; i++)
{
oconfig_item_t *temp;
struct stat statbuf;
} /* oconfig_item_t *cf_read_generic */
#endif /* !HAVE_WORDEXP_H */
-/*
+/*
* Public functions
*/
-int global_option_set (const char *option, const char *value)
+int global_option_set (const char *option, const char *value, _Bool from_cli)
{
int i;
-
DEBUG ("option = %s; value = %s;", option, value);
for (i = 0; i < cf_global_options_num; i++)
break;
if (i >= cf_global_options_num)
+ {
+ ERROR ("configfile: Cannot set unknown global option `%s'.", option);
return (-1);
+ }
- if (strcasecmp (option, "PIDFile") == 0 && pidfile_from_cli == 1)
+ if (cf_global_options[i].from_cli && (! from_cli))
{
- DEBUG ("Configfile: Ignoring `PIDFILE' option because "
- "command-line option `-P' take precedence.");
+ DEBUG ("configfile: Ignoring %s `%s' option because "
+ "it was overriden by a command-line option.",
+ option, value);
return (0);
}
else
cf_global_options[i].value = NULL;
+ cf_global_options[i].from_cli = from_cli;
+
return (0);
}
const char *global_option_get (const char *option)
{
int i;
-
for (i = 0; i < cf_global_options_num; i++)
if (strcasecmp (cf_global_options[i].key, option) == 0)
break;
if (i >= cf_global_options_num)
+ {
+ ERROR ("configfile: Cannot get unknown global option `%s'.", option);
return (NULL);
-
+ }
+
return ((cf_global_options[i].value != NULL)
? cf_global_options[i].value
: cf_global_options[i].def);
void cf_unregister (const char *type)
{
- cf_callback_t *this, *prev;
-
- for (prev = NULL, this = first_callback;
+ for (cf_callback_t *prev = NULL, *this = first_callback;
this != NULL;
prev = this, this = this->next)
if (strcasecmp (this->type, type) == 0)
void cf_unregister_complex (const char *type)
{
- cf_complex_callback_t *this, *prev;
-
- for (prev = NULL, this = complex_callback_head;
+ for (cf_complex_callback_t *prev = NULL, *this = complex_callback_head;
this != NULL;
prev = this, this = this->next)
if (strcasecmp (this->type, type) == 0)
cf_unregister (type);
/* This pointer will be free'd in `cf_unregister' */
- if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL)
+ if ((cf_cb = malloc (sizeof (*cf_cb))) == NULL)
return;
cf_cb->type = type;
@@ -1079,7 +1069,7 @@ int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *))
{
cf_complex_callback_t *new;
- new = (cf_complex_callback_t *) malloc (sizeof (cf_complex_callback_t));
+ new = malloc (sizeof (*new));
if (new == NULL)
return (-1);
@@ -1110,10 +1100,10 @@ int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *))
return (0);
} /* int cf_register_complex */
-int cf_read (char *filename)
+int cf_read (const char *filename)
{
oconfig_item_t *conf;
- int i;
+ int ret = 0;
conf = cf_read_generic (filename, /* pattern = */ NULL, /* depth = */ 0);
if (conf == NULL)
return (-1);
}
- for (i = 0; i < conf->children_num; i++)
+ for (int i = 0; i < conf->children_num; i++)
{
if (conf->children[i].children == NULL)
- dispatch_value (conf->children + i);
+ {
+ if (dispatch_value (conf->children + i) != 0)
+ ret = -1;
+ }
else
- dispatch_block (conf->children + i);
+ {
+ if (dispatch_block (conf->children + i) != 0)
+ ret = -1;
+ }
}
oconfig_free (conf);
/* Read the default types.db if no `TypesDB' option was given. */
if (cf_default_typesdb)
- read_types_list (PKGDATADIR"/types.db");
+ {
+ if (read_types_list (PKGDATADIR"/types.db") != 0)
+ ret = -1;
+ }
- return (0);
+ return ret;
} /* int cf_read */
/* Assures the config option is a string, duplicates it and returns the copy in
index 5bc9b305615ee3404d8d373dd5544de7e88e433d..a13bc09dff7b064f65059e7b8946610727988de7 100644 (file)
--- a/src/daemon/configfile.h
+++ b/src/daemon/configfile.h
#define CONFIGFILE_H
#include "collectd.h"
+
#include "utils_time.h"
#include "liboconfig/oconfig.h"
/*
* DESCRIPTION
* Remove a registered plugin from the internal data structures.
- *
+ *
* PARAMETERS
* `type' Name of the plugin (must be the same as passed to
* `plugin_register'
* Returns zero upon success and non-zero otherwise. A error-message will have
* been printed in this case.
*/
-int cf_read (char *filename);
+int cf_read (const char *filename);
-int global_option_set (const char *option, const char *value);
+int global_option_set (const char *option, const char *value, _Bool from_cli);
const char *global_option_get (const char *option);
long global_option_get_long (const char *option, long default_value);
-long global_option_get_long_in_range (const char *option, long default_value, long min, long max);
cdtime_t global_option_get_time (char const *option, cdtime_t default_value);
index ecc7f165a5a1f73064aedcdaa9b41e086f24abf1..cee479a832406988ecb8ccd155a7ff737a083e26 100644 (file)
**/
#include "collectd.h"
+
#include "configfile.h"
#include "plugin.h"
#include "utils_complain.h"
return (NULL);
sz = strlen (orig) + 1;
- dest = (char *) malloc (sz);
+ dest = malloc (sz);
if (dest == NULL)
return (NULL);
return (-1);
}
- m = (fc_match_t *) malloc (sizeof (*m));
+ m = calloc (1, sizeof (*m));
if (m == NULL)
{
- ERROR ("fc_config_add_match: malloc failed.");
+ ERROR ("fc_config_add_match: calloc failed.");
return (-1);
}
- memset (m, 0, sizeof (*m));
sstrncpy (m->name, ptr->name, sizeof (m->name));
memcpy (&m->proc, &ptr->proc, sizeof (m->proc));
return (-1);
}
- t = (fc_target_t *) malloc (sizeof (*t));
+ t = calloc (1, sizeof (*t));
if (t == NULL)
{
- ERROR ("fc_config_add_target: malloc failed.");
+ ERROR ("fc_config_add_target: calloc failed.");
return (-1);
}
- memset (t, 0, sizeof (*t));
sstrncpy (t->name, ptr->name, sizeof (t->name));
memcpy (&t->proc, &ptr->proc, sizeof (t->proc));
{
t->user_data = NULL;
}
-
+
if (*targets_head != NULL)
{
ptr = *targets_head;
fc_rule_t *rule;
char rule_name[2*DATA_MAX_NAME_LEN] = "Unnamed rule";
int status = 0;
- int i;
if (ci->values_num > 1)
{
return (-1);
}
- rule = (fc_rule_t *) malloc (sizeof (*rule));
+ rule = calloc (1, sizeof (*rule));
if (rule == NULL)
{
- ERROR ("fc_config_add_rule: malloc failed.");
+ ERROR ("fc_config_add_rule: calloc failed.");
return (-1);
}
- memset (rule, 0, sizeof (*rule));
- rule->next = NULL;
if (ci->values_num == 1)
{
ci->values[0].value.string);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
{
fc_chain_t *chain = NULL;
int status = 0;
- int i;
int new_chain = 1;
if ((ci->values_num != 1)
if (chain == NULL)
{
- chain = (fc_chain_t *) malloc (sizeof (*chain));
+ chain = calloc (1, sizeof (*chain));
if (chain == NULL)
{
- ERROR ("fc_config_add_chain: malloc failed.");
+ ERROR ("fc_config_add_chain: calloc failed.");
return (-1);
}
- memset (chain, 0, sizeof (*chain));
sstrncpy (chain->name, ci->values[0].value.string, sizeof (chain->name));
- chain->rules = NULL;
- chain->targets = NULL;
- chain->next = NULL;
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
@@ -632,16 +623,13 @@ static int fc_bit_return_invoke (const data_set_t __attribute__((unused)) *ds, /
static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
void **user_data)
{
- int i;
-
fc_writer_t *plugin_list = NULL;
size_t plugin_list_len = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
fc_writer_t *temp;
- int j;
if (strcasecmp ("Plugin", child->key) != 0)
{
continue;
}
- for (j = 0; j < child->values_num; j++)
+ for (int j = 0; j < child->values_num; j++)
{
char *plugin;
}
plugin = child->values[j].value.string;
- temp = (fc_writer_t *) realloc (plugin_list, (plugin_list_len + 2)
+ temp = realloc (plugin_list, (plugin_list_len + 2)
* (sizeof (*plugin_list)));
if (temp == NULL)
{
static int fc_bit_write_destroy (void **user_data) /* {{{ */
{
fc_writer_t *plugin_list;
- size_t i;
if ((user_data == NULL) || (*user_data == NULL))
return (0);
plugin_list = *user_data;
- for (i = 0; plugin_list[i].plugin != NULL; i++)
+ for (size_t i = 0; plugin_list[i].plugin != NULL; i++)
free (plugin_list[i].plugin);
free (plugin_list);
}
else
{
- size_t i;
-
- for (i = 0; plugin_list[i].plugin != NULL; i++)
+ for (size_t i = 0; plugin_list[i].plugin != NULL; i++)
{
status = plugin_write (plugin_list[i].plugin, ds, vl);
if (status != 0)
static int fc_init_once (void) /* {{{ */
{
static int done = 0;
- target_proc_t tproc;
+ target_proc_t tproc = { 0 };
if (done != 0)
return (0);
- memset (&tproc, 0, sizeof (tproc));
tproc.create = fc_bit_jump_create;
tproc.destroy = fc_bit_jump_destroy;
tproc.invoke = fc_bit_jump_invoke;
DEBUG ("fc_register_match (%s);", name);
- m = (fc_match_t *) malloc (sizeof (*m));
+ m = calloc (1, sizeof (*m));
if (m == NULL)
return (-ENOMEM);
- memset (m, 0, sizeof (*m));
sstrncpy (m->name, name, sizeof (m->name));
memcpy (&m->proc, &proc, sizeof (m->proc));
- m->next = NULL;
if (match_list_head == NULL)
{
DEBUG ("fc_register_target (%s);", name);
- t = (fc_target_t *) malloc (sizeof (*t));
+ t = calloc (1, sizeof (*t));
if (t == NULL)
return (-ENOMEM);
- memset (t, 0, sizeof (*t));
sstrncpy (t->name, name, sizeof (t->name));
memcpy (&t->proc, &proc, sizeof (t->proc));
- t->next = NULL;
if (target_list_head == NULL)
{
fc_chain_t *fc_chain_get_by_name (const char *chain_name) /* {{{ */
{
- fc_chain_t *chain;
-
if (chain_name == NULL)
return (NULL);
- for (chain = chain_list_head; chain != NULL; chain = chain->next)
+ for (fc_chain_t *chain = chain_list_head; chain != NULL; chain = chain->next)
if (strcasecmp (chain_name, chain->name) == 0)
return (chain);
int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
fc_chain_t *chain)
{
- fc_rule_t *rule;
fc_target_t *target;
int status = FC_TARGET_CONTINUE;
DEBUG ("fc_process_chain (chain = %s);", chain->name);
- for (rule = chain->rules; rule != NULL; rule = rule->next)
+ for (fc_rule_t *rule = chain->rules; rule != NULL; rule = rule->next)
{
fc_match_t *match;
status = FC_TARGET_CONTINUE;
index 2db90dbb6938f99eb83e280fc611834f13eeceae..2d280f89ec0e399e7e2855ee538ea99141071388 100644 (file)
#define FILTER_CHAIN_H 1
#include "collectd.h"
+
#include "plugin.h"
#define FC_MATCH_NO_MATCH 0
int fc_default_action (const data_set_t *ds, value_list_t *vl);
-/*
+/*
* Shortcut for global configuration
*/
int fc_configure (const oconfig_item_t *ci);
diff --git a/src/daemon/meta_data.c b/src/daemon/meta_data.c
index 29236e2f18563760279d9f3868b2a748e1e1a8a4..9e4fd07ecfdf99716a11e64532a8ccb6d5654041 100644 (file)
--- a/src/daemon/meta_data.c
+++ b/src/daemon/meta_data.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "meta_data.h"
-#include <pthread.h>
-
/*
* Data types
*/
return (NULL);
sz = strlen (orig) + 1;
- dest = (char *) malloc (sz);
+ dest = malloc (sz);
if (dest == NULL)
return (NULL);
{
meta_entry_t *e;
- e = (meta_entry_t *) malloc (sizeof (*e));
+ e = calloc (1, sizeof (*e));
if (e == NULL)
{
- ERROR ("md_entry_alloc: malloc failed.");
+ ERROR ("md_entry_alloc: calloc failed.");
return (NULL);
}
- memset (e, 0, sizeof (*e));
e->key = md_strdup (key);
if (e->key == NULL)
return (e);
} /* }}} meta_entry_t *md_entry_alloc */
-static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+/* XXX: The lock on md must be held while calling this function! */
+static meta_entry_t *md_entry_clone_contents (const meta_entry_t *orig) /* {{{ */
{
meta_entry_t *copy;
- if (orig == NULL)
- return (NULL);
+ /* WARNINGS :
+ * - we do not check that orig != NULL here. You should have done it before.
+ * - we do not set copy->next. DO NOT FORGET TO SET copy->next IN YOUR FUNCTION
+ */
copy = md_entry_alloc (orig->key);
if (copy == NULL)
else
copy->value = orig->value;
+ return (copy);
+} /* }}} meta_entry_t *md_entry_clone_contents */
+
+static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+{
+ meta_entry_t *copy;
+
+ if (orig == NULL)
+ return (NULL);
+
+ copy = md_entry_clone_contents(orig);
+
copy->next = md_entry_clone (orig->next);
return (copy);
} /* }}} meta_entry_t *md_entry_clone */
return (0);
} /* }}} int md_entry_insert */
+/* XXX: The lock on md must be held while calling this function! */
+static int md_entry_insert_clone (meta_data_t *md, meta_entry_t *orig) /* {{{ */
+{
+ meta_entry_t *e;
+ meta_entry_t *this;
+ meta_entry_t *prev;
+
+ /* WARNINGS :
+ * - we do not check that md and e != NULL here. You should have done it before.
+ * - we do not use the lock. You should have set it before.
+ */
+
+ e = md_entry_clone_contents(orig);
+
+ prev = NULL;
+ this = md->head;
+ while (this != NULL)
+ {
+ if (strcasecmp (e->key, this->key) == 0)
+ break;
+
+ prev = this;
+ this = this->next;
+ }
+
+ if (this == NULL)
+ {
+ /* This key does not exist yet. */
+ if (md->head == NULL)
+ md->head = e;
+ else
+ {
+ assert (prev != NULL);
+ prev->next = e;
+ }
+
+ e->next = NULL;
+ }
+ else /* (this != NULL) */
+ {
+ if (prev == NULL)
+ md->head = e;
+ else
+ prev->next = e;
+
+ e->next = this->next;
+ }
+
+ if (this != NULL)
+ {
+ this->next = NULL;
+ md_entry_free (this);
+ }
+
+ return (0);
+} /* }}} int md_entry_insert_clone */
+
/* XXX: The lock on md must be held while calling this function! */
static meta_entry_t *md_entry_lookup (meta_data_t *md, /* {{{ */
const char *key)
{
meta_data_t *md;
- md = (meta_data_t *) malloc (sizeof (*md));
+ md = calloc (1, sizeof (*md));
if (md == NULL)
{
- ERROR ("meta_data_create: malloc failed.");
+ ERROR ("meta_data_create: calloc failed.");
return (NULL);
}
- memset (md, 0, sizeof (*md));
- md->head = NULL;
pthread_mutex_init (&md->lock, /* attr = */ NULL);
return (md);
return (copy);
} /* }}} meta_data_t *meta_data_clone */
+int meta_data_clone_merge (meta_data_t **dest, meta_data_t *orig) /* {{{ */
+{
+ if (orig == NULL)
+ return (0);
+
+ if (*dest == NULL) {
+ *dest = meta_data_clone(orig);
+ return(0);
+ }
+
+ pthread_mutex_lock (&orig->lock);
+ for (meta_entry_t *e=orig->head; e != NULL; e = e->next)
+ {
+ md_entry_insert_clone((*dest), e);
+ }
+ pthread_mutex_unlock (&orig->lock);
+
+ return (0);
+} /* }}} int meta_data_clone_merge */
+
void meta_data_destroy (meta_data_t *md) /* {{{ */
{
if (md == NULL)
int meta_data_exists (meta_data_t *md, const char *key) /* {{{ */
{
- meta_entry_t *e;
-
if ((md == NULL) || (key == NULL))
return (-EINVAL);
pthread_mutex_lock (&md->lock);
- for (e = md->head; e != NULL; e = e->next)
+ for (meta_entry_t *e = md->head; e != NULL; e = e->next)
{
if (strcasecmp (key, e->key) == 0)
{
int meta_data_type (meta_data_t *md, const char *key) /* {{{ */
{
- meta_entry_t *e;
-
if ((md == NULL) || (key == NULL))
return -EINVAL;
pthread_mutex_lock (&md->lock);
- for (e = md->head; e != NULL; e = e->next)
+ for (meta_entry_t *e = md->head; e != NULL; e = e->next)
{
if (strcasecmp (key, e->key) == 0)
{
int meta_data_toc (meta_data_t *md, char ***toc) /* {{{ */
{
int i = 0, count = 0;
- meta_entry_t *e;
if ((md == NULL) || (toc == NULL))
return -EINVAL;
pthread_mutex_lock (&md->lock);
- for (e = md->head; e != NULL; e = e->next)
- ++count;
+ for (meta_entry_t *e = md->head; e != NULL; e = e->next)
+ ++count;
if (count == 0)
{
}
*toc = calloc(count, sizeof(**toc));
- for (e = md->head; e != NULL; e = e->next)
+ for (meta_entry_t *e = md->head; e != NULL; e = e->next)
(*toc)[i++] = strdup(e->key);
-
+
pthread_mutex_unlock (&md->lock);
return count;
} /* }}} int meta_data_toc */
ERROR ("meta_data_get_string: md_strdup failed.");
return (-ENOMEM);
}
-
+
pthread_mutex_unlock (&md->lock);
*value = temp;
diff --git a/src/daemon/meta_data.h b/src/daemon/meta_data.h
index fa48df326ebf90dc45ef4d237dcd7e889eefa124..0398c5460715fa9dd877d3f8209242a8d92cf2f1 100644 (file)
--- a/src/daemon/meta_data.h
+++ b/src/daemon/meta_data.h
#include "collectd.h"
+
/*
* Defines
*/
meta_data_t *meta_data_create (void);
meta_data_t *meta_data_clone (meta_data_t *orig);
+int meta_data_clone_merge (meta_data_t **dest, meta_data_t *orig);
void meta_data_destroy (meta_data_t *md);
int meta_data_exists (meta_data_t *md, const char *key);
diff --git a/src/daemon/meta_data_test.c b/src/daemon/meta_data_test.c
--- /dev/null
@@ -0,0 +1,120 @@
+/**
+ * collectd - src/daemon/meta_data_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
+#include "meta_data.h"
+
+DEF_TEST(base)
+{
+ meta_data_t *m;
+
+ char *s;
+ int64_t si;
+ uint64_t ui;
+ double d;
+ _Bool b;
+
+ CHECK_NOT_NULL (m = meta_data_create ());
+
+ /* all of these are absent */
+ OK(meta_data_get_string (m, "string", &s) != 0);
+ OK(meta_data_get_signed_int (m, "signed_int", &si) != 0);
+ OK(meta_data_get_unsigned_int (m, "unsigned_int", &ui) != 0);
+ OK(meta_data_get_double (m, "double", &d) != 0);
+ OK(meta_data_get_boolean (m, "boolean", &b) != 0);
+
+ /* populate structure */
+ CHECK_ZERO (meta_data_add_string (m, "string", "foobar"));
+ OK(meta_data_exists (m, "string"));
+ OK(meta_data_type (m, "string") == MD_TYPE_STRING);
+
+ CHECK_ZERO (meta_data_add_signed_int (m, "signed_int", -1));
+ OK(meta_data_exists (m, "signed_int"));
+ OK(meta_data_type (m, "signed_int") == MD_TYPE_SIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_unsigned_int (m, "unsigned_int", 1));
+ OK(meta_data_exists (m, "unsigned_int"));
+ OK(meta_data_type (m, "unsigned_int") == MD_TYPE_UNSIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_double (m, "double", 47.11));
+ OK(meta_data_exists (m, "double"));
+ OK(meta_data_type (m, "double") == MD_TYPE_DOUBLE);
+
+ CHECK_ZERO (meta_data_add_boolean (m, "boolean", 1));
+ OK(meta_data_exists (m, "boolean"));
+ OK(meta_data_type (m, "boolean") == MD_TYPE_BOOLEAN);
+
+ /* retrieve and check all values */
+ CHECK_ZERO (meta_data_get_string (m, "string", &s));
+ EXPECT_EQ_STR ("foobar", s);
+ sfree (s);
+
+ CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+ EXPECT_EQ_INT (-1, (int) si);
+
+ CHECK_ZERO (meta_data_get_unsigned_int (m, "unsigned_int", &ui));
+ EXPECT_EQ_INT (1, (int) ui);
+
+ CHECK_ZERO (meta_data_get_double (m, "double", &d));
+ EXPECT_EQ_DOUBLE (47.11, d);
+
+ CHECK_ZERO (meta_data_get_boolean (m, "boolean", &b));
+ OK1 (b, "b evaluates to true");
+
+ /* retrieving the wrong type always fails */
+ EXPECT_EQ_INT (-2, meta_data_get_boolean (m, "string", &b));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "signed_int", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "unsigned_int", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "double", &s));
+ EXPECT_EQ_INT (-2, meta_data_get_string (m, "boolean", &s));
+
+ /* replace existing keys */
+ CHECK_ZERO (meta_data_add_signed_int (m, "string", 666));
+ OK(meta_data_type (m, "string") == MD_TYPE_SIGNED_INT);
+
+ CHECK_ZERO (meta_data_add_signed_int (m, "signed_int", 666));
+ CHECK_ZERO (meta_data_get_signed_int (m, "signed_int", &si));
+ EXPECT_EQ_INT (666, (int) si);
+
+ /* deleting keys */
+ CHECK_ZERO (meta_data_delete (m, "signed_int"));
+ EXPECT_EQ_INT (-2, meta_data_delete (m, "doesnt exist"));
+
+ meta_data_destroy (m);
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(base);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c
index a8e6ca1312a61c92ff352740fe8f0873d287ecb5..1fbd77dfcadf6a22d8b2d484eb3c361352337e97 100644 (file)
--- a/src/daemon/plugin.c
+++ b/src/daemon/plugin.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "configfile.h"
write_queue_t *next;
};
+struct flush_callback_s {
+ char *name;
+ cdtime_t timeout;
+};
+typedef struct flush_callback_s flush_callback_t;
+
/*
* Private variables
*/
{
ERROR ("plugin: register_callback: "
"llentry_create failed.");
- free (key);
+ sfree (key);
destroy_callback (cf);
return (-1);
}
{
char *str;
int len;
- llentry_t *le;
int i;
+ llentry_t *le;
int n;
char **keys;
*str = '\0';
strjoin(str, len, keys, n, "', '");
INFO("%s ['%s']", comment, str);
- free(str);
+ sfree (str);
}
- free(keys);
+ sfree (keys);
} /* }}} void log_list_callbacks */
static int create_register_callback (llist_t **list, /* {{{ */
- const char *name, void *callback, user_data_t *ud)
+ const char *name, void *callback, user_data_t const *ud)
{
callback_func_t *cf;
- cf = (callback_func_t *) malloc (sizeof (*cf));
+ cf = calloc (1, sizeof (*cf));
if (cf == NULL)
{
- ERROR ("plugin: create_register_callback: malloc failed.");
+ ERROR ("plugin: create_register_callback: calloc failed.");
return (-1);
}
- memset (cf, 0, sizeof (*cf));
cf->cf_callback = callback;
if (ud == NULL)
{
read_func_t *rf;
plugin_ctx_t old_ctx;
+ cdtime_t start;
cdtime_t now;
+ cdtime_t elapsed;
int status;
int rf_type;
int rc;
DEBUG ("plugin_read_thread: Handling `%s'.", rf->rf_name);
+ start = cdtime ();
+
old_ctx = plugin_set_ctx (rf->rf_ctx);
if (rf_type == RF_SIMPLE)
/* update the ``next read due'' field */
now = cdtime ();
+ /* calculate the time spent in the read function */
+ elapsed = (now - start);
+
+ if (elapsed > rf->rf_effective_interval)
+ WARNING ("plugin_read_thread: read-function of the `%s' plugin took %.3f "
+ "seconds, which is above its read interval (%.3f seconds). You might "
+ "want to adjust the `Interval' or `ReadThreads' settings.",
+ rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed),
+ CDTIME_T_TO_DOUBLE(rf->rf_effective_interval));
+
+ DEBUG ("plugin_read_thread: read-function of the `%s' plugin took "
+ "%.6f seconds.",
+ rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed));
+
DEBUG ("plugin_read_thread: Effective interval of the "
- "%s plugin is %.3f seconds.",
+ "`%s' plugin is %.3f seconds.",
rf->rf_name,
CDTIME_T_TO_DOUBLE (rf->rf_effective_interval));
rf->rf_next_read = now;
}
- DEBUG ("plugin_read_thread: Next read of the %s plugin at %.3f.",
+ DEBUG ("plugin_read_thread: Next read of the `%s' plugin at %.3f.",
rf->rf_name,
CDTIME_T_TO_DOUBLE (rf->rf_next_read));
static void start_read_threads (int num)
{
- int i;
-
if (read_threads != NULL)
return;
}
read_threads_num = 0;
- for (i = 0; i < num; i++)
+ for (int i = 0; i < num; i++)
{
if (pthread_create (read_threads + read_threads_num, NULL,
plugin_read_thread, NULL) == 0)
static void stop_read_threads (void)
{
- int i;
-
if (read_threads == NULL)
return;
pthread_cond_broadcast (&read_cond);
pthread_mutex_unlock (&read_lock);
- for (i = 0; i < read_threads_num; i++)
+ for (int i = 0; i < read_threads_num; i++)
{
if (pthread_join (read_threads[i], NULL) != 0)
{
static void start_write_threads (size_t num) /* {{{ */
{
- size_t i;
-
if (write_threads != NULL)
return;
}
write_threads_num = 0;
- for (i = 0; i < num; i++)
+ for (size_t i = 0; i < num; i++)
{
int status;
static void stop_write_threads (void) /* {{{ */
{
write_queue_t *q;
- int i;
+ size_t i;
if (write_threads == NULL)
return;
if (i > 0)
{
- WARNING ("plugin: %i value list%s left after shutting down "
+ WARNING ("plugin: %zu value list%s left after shutting down "
"the write threads.",
i, (i == 1) ? " was" : "s were");
}
*/
void plugin_set_dir (const char *dir)
{
- if (plugindir != NULL)
- free (plugindir);
+ sfree (plugindir);
if (dir == NULL)
- plugindir = NULL;
- else if ((plugindir = strdup (dir)) == NULL)
{
- char errbuf[1024];
- ERROR ("strdup failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
+ plugindir = NULL;
+ return;
}
+
+ plugindir = strdup (dir);
+ if (plugindir == NULL)
+ ERROR ("plugin_set_dir: strdup(\"%s\") failed", dir);
}
static _Bool plugin_is_loaded (char const *name)
int status;
if (plugins_loaded == NULL)
- plugins_loaded = c_avl_create ((void *) strcasecmp);
+ plugins_loaded = c_avl_create ((int (*) (const void *, const void *)) strcasecmp);
assert (plugins_loaded != NULL);
status = c_avl_get (plugins_loaded, name, /* ret_value = */ NULL);
/* success */
plugin_mark_loaded (plugin_name);
ret = 0;
+ INFO ("plugin_load: plugin \"%s\" successfully loaded.", plugin_name);
break;
}
else
read_func_t *rf;
int status;
- rf = malloc (sizeof (*rf));
+ rf = calloc (1, sizeof (*rf));
if (rf == NULL)
{
- ERROR ("plugin_register_read: malloc failed.");
+ ERROR ("plugin_register_read: calloc failed.");
return (ENOMEM);
}
- memset (rf, 0, sizeof (read_func_t));
rf->rf_callback = (void *) callback;
rf->rf_udata.data = NULL;
rf->rf_udata.free_func = NULL;
int plugin_register_complex_read (const char *group, const char *name,
plugin_read_cb callback,
- const struct timespec *interval,
- user_data_t *user_data)
+ cdtime_t interval,
+ user_data_t const *user_data)
{
read_func_t *rf;
int status;
- rf = malloc (sizeof (*rf));
+ rf = calloc (1,sizeof (*rf));
if (rf == NULL)
{
- ERROR ("plugin_register_complex_read: malloc failed.");
+ ERROR ("plugin_register_complex_read: calloc failed.");
return (ENOMEM);
}
- memset (rf, 0, sizeof (read_func_t));
rf->rf_callback = (void *) callback;
if (group != NULL)
sstrncpy (rf->rf_group, group, sizeof (rf->rf_group));
rf->rf_group[0] = '\0';
rf->rf_name = strdup (name);
rf->rf_type = RF_COMPLEX;
- if (interval != NULL)
- rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval);
- else
- rf->rf_interval = plugin_get_interval ();
+ rf->rf_interval = (interval != 0) ? interval : plugin_get_interval ();
/* Set user data */
if (user_data == NULL)
} /* int plugin_register_complex_read */
int plugin_register_write (const char *name,
- plugin_write_cb callback, user_data_t *ud)
+ plugin_write_cb callback, user_data_t const *ud)
{
return (create_register_callback (&list_write, name,
(void *) callback, ud));
} /* int plugin_register_write */
+static int plugin_flush_timeout_callback (user_data_t *ud)
+{
+ flush_callback_t *cb = ud->data;
+
+ return plugin_flush (cb->name, cb->timeout, /* identifier = */ NULL);
+} /* static int plugin_flush_callback */
+
+static void plugin_flush_timeout_callback_free (void *data)
+{
+ flush_callback_t *cb = data;
+
+ if (cb == NULL) return;
+
+ sfree (cb->name);
+ sfree (cb);
+} /* static void plugin_flush_callback_free */
+
+static char *plugin_flush_callback_name (const char *name)
+{
+ const char *flush_prefix = "flush/";
+ size_t prefix_size;
+ char *flush_name;
+ size_t name_size;
+
+ prefix_size = strlen(flush_prefix);
+ name_size = strlen(name);
+
+ flush_name = malloc (name_size + prefix_size + 1);
+ if (flush_name == NULL)
+ {
+ ERROR ("plugin_flush_callback_name: malloc failed.");
+ return (NULL);
+ }
+
+ sstrncpy (flush_name, flush_prefix, prefix_size + 1);
+ sstrncpy (flush_name + prefix_size, name, name_size + 1);
+
+ return flush_name;
+} /* static char *plugin_flush_callback_name */
+
int plugin_register_flush (const char *name,
- plugin_flush_cb callback, user_data_t *ud)
+ plugin_flush_cb callback, user_data_t const *ud)
{
- return (create_register_callback (&list_flush, name,
- (void *) callback, ud));
+ int status;
+ plugin_ctx_t ctx = plugin_get_ctx ();
+
+ status = create_register_callback (&list_flush, name,
+ (void *) callback, ud);
+ if (status != 0)
+ return status;
+
+ if (ctx.flush_interval != 0)
+ {
+ char *flush_name;
+ flush_callback_t *cb;
+
+ flush_name = plugin_flush_callback_name (name);
+ if (flush_name == NULL)
+ return (-1);
+
+ cb = malloc(sizeof (*cb));
+ if (cb == NULL)
+ {
+ ERROR ("plugin_register_flush: malloc failed.");
+ sfree (flush_name);
+ return (-1);
+ }
+
+ cb->name = strdup (name);
+ if (cb->name == NULL)
+ {
+ ERROR ("plugin_register_flush: strdup failed.");
+ sfree (cb);
+ sfree (flush_name);
+ return (-1);
+ }
+ cb->timeout = ctx.flush_timeout;
+
+ status = plugin_register_complex_read (
+ /* group = */ "flush",
+ /* name = */ flush_name,
+ /* callback = */ plugin_flush_timeout_callback,
+ /* interval = */ ctx.flush_interval,
+ /* user data = */ &(user_data_t) {
+ .data = cb,
+ .free_func = plugin_flush_timeout_callback_free,
+ });
+
+ sfree (flush_name);
+ if (status != 0)
+ {
+ sfree (cb->name);
+ sfree (cb);
+ return status;
+ }
+ }
+
+ return 0;
} /* int plugin_register_flush */
int plugin_register_missing (const char *name,
- plugin_missing_cb callback, user_data_t *ud)
+ plugin_missing_cb callback, user_data_t const *ud)
{
return (create_register_callback (&list_missing, name,
(void *) callback, ud));
int plugin_register_data_set (const data_set_t *ds)
{
data_set_t *ds_copy;
- int i;
if ((data_sets != NULL)
&& (c_avl_get (data_sets, ds->type, NULL) == 0))
return (-1);
}
- ds_copy = (data_set_t *) malloc (sizeof (data_set_t));
+ ds_copy = malloc (sizeof (*ds_copy));
if (ds_copy == NULL)
return (-1);
memcpy(ds_copy, ds, sizeof (data_set_t));
- ds_copy->ds = (data_source_t *) malloc (sizeof (data_source_t)
+ ds_copy->ds = malloc (sizeof (*ds_copy->ds)
* ds->ds_num);
if (ds_copy->ds == NULL)
{
- free (ds_copy);
+ sfree (ds_copy);
return (-1);
}
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
memcpy (ds_copy->ds + i, ds->ds + i, sizeof (data_source_t));
return (c_avl_insert (data_sets, (void *) ds_copy->type, (void *) ds_copy));
} /* int plugin_register_data_set */
int plugin_register_log (const char *name,
- plugin_log_cb callback, user_data_t *ud)
+ plugin_log_cb callback, user_data_t const *ud)
{
return (create_register_callback (&list_log, name,
(void *) callback, ud));
} /* int plugin_register_log */
int plugin_register_notification (const char *name,
- plugin_notification_cb callback, user_data_t *ud)
+ plugin_notification_cb callback, user_data_t const *ud)
{
return (create_register_callback (&list_notification, name,
(void *) callback, ud));
int plugin_unregister_flush (const char *name)
{
- return (plugin_unregister (list_flush, name));
+ plugin_ctx_t ctx = plugin_get_ctx ();
+
+ if (ctx.flush_interval != 0)
+ {
+ char *flush_name;
+
+ flush_name = plugin_flush_callback_name (name);
+ if (flush_name != NULL)
+ {
+ plugin_unregister_read(flush_name);
+ sfree (flush_name);
+ }
+ }
+
+ return plugin_unregister (list_flush, name);
}
int plugin_unregister_missing (const char *name)
return (plugin_unregister (list_notification, name));
}
-void plugin_init_all (void)
+int plugin_init_all (void)
{
char const *chain_name;
llentry_t *le;
int status;
+ int ret = 0;
/* Init the value cache */
uc_init ();
}
if ((list_init == NULL) && (read_heap == NULL))
- return;
+ return ret;
/* Calling all init callbacks before checking if read callbacks
* are available allows the init callbacks to register the read
* handling themselves. */
/* FIXME: Unload _all_ functions */
plugin_unregister_read (le->key);
+ ret = -1;
}
le = le->next;
if (num != -1)
start_read_threads ((num > 0) ? num : 5);
}
+ return ret;
} /* void plugin_init_all */
/* TODO: Rename this function. */
@@ -1846,9 +1969,10 @@ int plugin_flush (const char *plugin, cdtime_t timeout, const char *identifier)
return (0);
} /* int plugin_flush */
-void plugin_shutdown_all (void)
+int plugin_shutdown_all (void)
{
llentry_t *le;
+ int ret = 0; // Assume success.
destroy_all_callbacks (&list_init);
* after callback returns. */
le = le->next;
- (*callback) ();
+ if ((*callback) () != 0)
+ ret = -1;
plugin_set_ctx (old_ctx);
}
plugin_free_loaded ();
plugin_free_data_sets ();
+ return (ret);
} /* void plugin_shutdown_all */
int plugin_dispatch_missing (const value_list_t *vl) /* {{{ */
int free_meta_data = 0;
- if ((vl == NULL) || (vl->type[0] == 0)
- || (vl->values == NULL) || (vl->values_len < 1))
+ assert(vl);
+ assert(vl->plugin);
+
+ if (vl->type[0] == 0 || vl->values == NULL || vl->values_len < 1)
{
ERROR ("plugin_dispatch_values: Invalid value list "
"from plugin %s.", vl->plugin);
if (ds->ds_num != vl->values_len)
{
ERROR ("plugin_dispatch_values: ds->type = %s: "
- "(ds->ds_num = %i) != "
- "(vl->values_len = %i)",
+ "(ds->ds_num = %zu) != "
+ "(vl->values_len = %zu)",
ds->type, ds->ds_num, vl->values_len);
return (-1);
}
* don't get confused.. */
if (saved_values != NULL)
{
- free (vl->values);
+ sfree (vl->values);
vl->values = saved_values;
vl->values_len = saved_values_len;
}
* confused.. */
if (saved_values != NULL)
{
- free (vl->values);
+ sfree (vl->values);
vl->values = saved_values;
vl->values_len = saved_values_len;
}
assert (template->values_len == 1);
- /* Calculate sum for Gauge to calculate percent if needed */
+ /* Calculate sum for Gauge to calculate percent if needed */
if (DS_TYPE_GAUGE == store_type) {
va_start (ap, store_type);
while (42)
return (-1);
}
- meta = (notification_meta_t *) malloc (sizeof (notification_meta_t));
+ meta = calloc (1, sizeof (*meta));
if (meta == NULL)
{
- ERROR ("plugin_notification_meta_add: malloc failed.");
+ ERROR ("plugin_notification_meta_add: calloc failed.");
return (-1);
}
- memset (meta, 0, sizeof (notification_meta_t));
sstrncpy (meta->name, name, sizeof (meta->name));
meta->type = type;
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)
+ for (notification_meta_t *meta = src->meta; meta != NULL; meta = meta->next)
{
if (meta->type == NM_TYPE_STRING)
plugin_notification_meta_add_string (dst, meta->name,
if (this->type == NM_TYPE_STRING)
{
- free ((char *)this->nm_value.nm_string);
+ /* Assign to a temporary variable to work around nm_string's const
+ * modifier. */
+ void *tmp = (void *) this->nm_value.nm_string;
+
+ sfree (tmp);
this->nm_value.nm_string = NULL;
}
sfree (this);
plugin_set_ctx (plugin_thread->ctx);
- free (plugin_thread);
+ sfree (plugin_thread);
return start_routine (plugin_arg);
} /* void *plugin_thread_start */
diff --git a/src/daemon/plugin.h b/src/daemon/plugin.h
index cba298cfc4355a3783ac918b9589c8bb94ee6f52..d3038a395ea5f1c6ec52ce9eff27d3667e8a53b4 100644 (file)
--- a/src/daemon/plugin.h
+++ b/src/daemon/plugin.h
/**
- * collectd - src/plugin.h
+ * collectd - src/daemon/plugin.h
* Copyright (C) 2005-2014 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
#define PLUGIN_H
#include "collectd.h"
+
#include "configfile.h"
#include "meta_data.h"
#include "utils_time.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
+#include <pthread.h>
#define PLUGIN_FLAGS_GLOBAL 0x0001
-#define DATA_MAX_NAME_LEN 64
+#ifndef DATA_MAX_NAME_LEN
+# define DATA_MAX_NAME_LEN 128
+#endif
#define DS_TYPE_COUNTER 0
#define DS_TYPE_GAUGE 1
struct value_list_s
{
value_t *values;
- int values_len;
+ size_t values_len;
cdtime_t time;
cdtime_t interval;
char host[DATA_MAX_NAME_LEN];
struct data_set_s
{
char type[DATA_MAX_NAME_LEN];
- int ds_num;
+ size_t ds_num;
data_source_t *ds;
};
typedef struct data_set_s data_set_t;
struct plugin_ctx_s
{
cdtime_t interval;
+ cdtime_t flush_interval;
+ cdtime_t flush_timeout;
};
typedef struct plugin_ctx_s plugin_ctx_t;
typedef int (*plugin_shutdown_cb) (void);
typedef int (*plugin_notification_cb) (const notification_t *,
user_data_t *);
-
/*
* NAME
* plugin_set_dir
*/
int plugin_load (const char *name, uint32_t flags);
-void plugin_init_all (void);
+int plugin_init_all (void);
void plugin_read_all (void);
int plugin_read_all_once (void);
-void plugin_shutdown_all (void);
+int plugin_shutdown_all (void);
/*
* NAME
* "plugin_register_complex_read" returns an error (non-zero). */
int plugin_register_complex_read (const char *group, const char *name,
plugin_read_cb callback,
- const struct timespec *interval,
- user_data_t *user_data);
+ cdtime_t interval,
+ user_data_t const *user_data);
int plugin_register_write (const char *name,
- plugin_write_cb callback, user_data_t *user_data);
+ plugin_write_cb callback, user_data_t const *user_data);
int plugin_register_flush (const char *name,
- plugin_flush_cb callback, user_data_t *user_data);
+ plugin_flush_cb callback, user_data_t const *user_data);
int plugin_register_missing (const char *name,
- plugin_missing_cb callback, user_data_t *user_data);
+ plugin_missing_cb callback, user_data_t const *user_data);
int plugin_register_shutdown (const char *name,
plugin_shutdown_cb callback);
int plugin_register_data_set (const data_set_t *ds);
int plugin_register_log (const char *name,
- plugin_log_cb callback, user_data_t *user_data);
+ plugin_log_cb callback, user_data_t const *user_data);
int plugin_register_notification (const char *name,
- plugin_notification_cb callback, user_data_t *user_data);
+ plugin_notification_cb callback, user_data_t const *user_data);
int plugin_unregister_config (const char *name);
int plugin_unregister_complex_config (const char *name);
index 4023a8f609759920d18bcdb4503c295a7f70be57..34c222c7870dab6f0bb0a96bd3714910435fdae2 100644 (file)
--- a/src/daemon/types_list.c
+++ b/src/daemon/types_list.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
char *fields[64];
size_t fields_num;
data_set_t *ds;
- int i;
fields_num = strsplit (buf, fields, 64);
if (fields_num < 2)
if (fields[0][0] == '#')
return;
- ds = (data_set_t *) malloc (sizeof (data_set_t));
+ ds = calloc (1, sizeof (*ds));
if (ds == NULL)
return;
- memset (ds, '\0', sizeof (data_set_t));
-
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));
if (ds->ds == NULL)
+ {
+ sfree (ds);
return;
+ }
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
if (parse_ds (ds->ds + i, fields[i + 1], strlen (fields[i + 1])) != 0)
{
- sfree (ds->ds);
- ERROR ("types_list: parse_line: Cannot parse data source #%i "
+ ERROR ("types_list: parse_line: Cannot parse data source #%zu "
"of data set %s", i, ds->type);
+ sfree (ds->ds);
+ sfree (ds);
return;
}
index fcfbb9453c74e641d5d6c2909fdb430914884de5..e1c41ecf8fb95c122c9fb2a20c6746a5271e8e5d 100644 (file)
* Florian octo Forster <octo at collectd.org>
**/
-#include "config.h"
-
#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
#include <assert.h>
#include "utils_avltree.h"
if (compare == NULL)
return (NULL);
- if ((t = (c_avl_tree_t *) malloc (sizeof (c_avl_tree_t))) == NULL)
+ if ((t = malloc (sizeof (*t))) == NULL)
return (NULL);
t->root = NULL;
c_avl_node_t *nptr;
int cmp;
- if ((new = (c_avl_node_t *) malloc (sizeof (c_avl_node_t))) == NULL)
+ if ((new = malloc (sizeof (*new))) == NULL)
return (-1);
new->key = key;
if (t == NULL)
return (NULL);
- iter = (c_avl_iterator_t *) malloc (sizeof (c_avl_iterator_t));
+ iter = calloc (1, sizeof (*iter));
if (iter == NULL)
return (NULL);
- memset (iter, '\0', sizeof (c_avl_iterator_t));
iter->tree = t;
return (iter);
index 1e0f271fc187ce4e35f8bb015dbedc4bbe947448..43e94cfb64dd359dddb5db258dcdeb379e28a060 100644 (file)
*
* PARAMETERS
* `compare' The function-pointer `compare' is used to compare two keys. It
- * has to return less than zero if it's first argument is smaller
+ * has to return less than zero if its first argument is smaller
* then the second argument, more than zero if the first argument
* is bigger than the second argument and zero if they are equal.
* If your keys are char-pointers, you can use the `strcmp'
* c_avl_pick
*
* DESCRIPTION
- * Remove a (pseudo-)random element from the tree and return it's `key' and
+ * Remove a (pseudo-)random element from the tree and return its `key' and
* `value'. Entries are not returned in any particular order. This function
* is intended for cache-flushes that don't care about the order but simply
* want to remove all elements, one at a time.
index 2a8244c9f3e6cd1008649091de98b595ebf386f6..150dd1b5b8a8476c98a6fefdc01e9c5761ca02b7 100644 (file)
* Florian octo Forster <octo at collectd.org>
*/
-#include "testing.h"
+#include "common.h" /* STATIC_ARRAY_SIZE */
#include "collectd.h"
+
+#include "testing.h"
#include "utils_avltree.h"
static int compare_total_count = 0;
DEF_TEST(success)
{
+ struct {
+ char *key;
+ char *value;
+ } cases[] = {
+ {"Eeph7chu", "vai1reiV"},
+ {"igh3Paiz", "teegh1Ee"},
+ {"caip6Uu8", "ooteQu8n"},
+ {"Aech6vah", "AijeeT0l"},
+ {"Xah0et2L", "gah8Taep"},
+ {"BocaeB8n", "oGaig8io"},
+ {"thai8AhM", "ohjeFo3f"},
+ {"ohth6ieC", "hoo8ieWo"},
+ {"aej7Woow", "phahuC2s"},
+ {"Hai8ier2", "Yie6eimi"},
+ {"phuXi3Li", "JaiF7ieb"},
+ {"Shaig5ef", "aihi5Zai"},
+ {"voh6Aith", "Oozaeto0"},
+ {"zaiP5kie", "seep5veM"},
+ {"pae7ba7D", "chie8Ojo"},
+ {"Gou2ril3", "ouVoo0ha"},
+ {"lo3Thee3", "ahDu4Zuj"},
+ {"Rah8kohv", "ieShoc7E"},
+ {"ieN5engi", "Aevou1ah"},
+ {"ooTe4OhP", "aingai5Y"},
+ };
+
c_avl_tree_t *t;
- char key_orig[] = "foo";
- char value_orig[] = "bar";
- char *key_ret = NULL;
- char *value_ret = NULL;
RESET_COUNTS ();
- t = c_avl_create (compare_callback);
- OK (t != NULL);
+ CHECK_NOT_NULL (t = c_avl_create (compare_callback));
+
+ /* insert */
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *key;
+ char *value;
- OK (c_avl_insert (t, key_orig, value_orig) == 0);
- OK (c_avl_size (t) == 1);
+ CHECK_NOT_NULL (key = strdup (cases[i].key));
+ CHECK_NOT_NULL (value = strdup (cases[i].value));
+
+ CHECK_ZERO (c_avl_insert (t, key, value));
+ EXPECT_EQ_INT ((int) (i + 1), c_avl_size (t));
+ }
/* Key already exists. */
- OK (c_avl_insert (t, "foo", "qux") > 0);
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ EXPECT_EQ_INT (1, c_avl_insert (t, cases[i].key, cases[i].value));
+
+ /* get */
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *value_ret = NULL;
+
+ CHECK_ZERO (c_avl_get (t, cases[i].key, (void *) &value_ret));
+ EXPECT_EQ_STR (cases[i].value, value_ret);
+ }
+
+ /* remove half */
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases) / 2; i++)
+ {
+ char *key = NULL;
+ char *value = NULL;
+
+ int expected_size = (int) (STATIC_ARRAY_SIZE (cases) - (i + 1));
+
+ CHECK_ZERO (c_avl_remove (t, cases[i].key, (void *) &key, (void *) &value));
+
+ EXPECT_EQ_STR (cases[i].key, key);
+ EXPECT_EQ_STR (cases[i].value, value);
+
+ free (key);
+ free (value);
+
+ EXPECT_EQ_INT (expected_size, c_avl_size (t));
+ }
+
+ /* pick the other half */
+ for (size_t i = STATIC_ARRAY_SIZE (cases) / 2; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *key = NULL;
+ char *value = NULL;
+
+ int expected_size = (int) (STATIC_ARRAY_SIZE (cases) - (i + 1));
+
+ EXPECT_EQ_INT (expected_size + 1, c_avl_size (t));
+ EXPECT_EQ_INT (0, c_avl_pick (t, (void *) &key, (void *) &value));
- OK (c_avl_get (t, "foo", (void *) &value_ret) == 0);
- OK (value_ret == &value_orig[0]);
+ free (key);
+ free (value);
- key_ret = value_ret = NULL;
- OK (c_avl_remove (t, "foo", (void *) &key_ret, (void *) &value_ret) == 0);
- OK (key_ret == &key_orig[0]);
- OK (value_ret == &value_orig[0]);
- OK (c_avl_size (t) == 0);
+ EXPECT_EQ_INT (expected_size, c_avl_size (t));
+ }
c_avl_destroy (t);
index c4cef28b204978dd34f24af6aadad64d363b826f..7c1fa41e42638593b322368442810c6a96574690 100644 (file)
--- a/src/daemon/utils_cache.c
+++ b/src/daemon/utils_cache.c
/**
* collectd - src/utils_cache.c
* Copyright (C) 2007-2010 Florian octo Forster
+ * Copyright (C) 2016 Sebastian tokkee Harl
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*
* Authors:
* Florian octo Forster <octo at collectd.org>
+ * Sebastian tokkee Harl <sh at tokkee.org>
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_avltree.h"
#include "meta_data.h"
#include <assert.h>
-#include <pthread.h>
typedef struct cache_entry_s
{
char name[6 * DATA_MAX_NAME_LEN];
- int values_num;
+ size_t values_num;
gauge_t *values_gauge;
value_t *values_raw;
/* Time contained in the package
* (for purging old entries) */
cdtime_t last_update;
/* Interval in which the data is collected
- * (for purding old entries) */
+ * (for purging old entries) */
cdtime_t interval;
int state;
int hits;
meta_data_t *meta;
} cache_entry_t;
+struct uc_iter_s {
+ c_avl_iterator_t *iter;
+
+ char *name;
+ cache_entry_t *entry;
+};
+
static c_avl_tree_t *cache_tree = NULL;
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
return (strcmp (a->name, b->name));
} /* int cache_compare */
-static cache_entry_t *cache_alloc (int values_num)
+static cache_entry_t *cache_alloc (size_t values_num)
{
cache_entry_t *ce;
- ce = (cache_entry_t *) malloc (sizeof (cache_entry_t));
+ ce = calloc (1, sizeof (*ce));
if (ce == NULL)
{
- ERROR ("utils_cache: cache_alloc: malloc failed.");
+ ERROR ("utils_cache: cache_alloc: calloc failed.");
return (NULL);
}
- memset (ce, '\0', sizeof (cache_entry_t));
ce->values_num = values_num;
ce->values_gauge = calloc (values_num, sizeof (*ce->values_gauge));
static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
{
- int i;
-
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if (isnan (ce->values_gauge[i]))
continue;
static int uc_insert (const data_set_t *ds, const value_list_t *vl,
const char *key)
{
- int i;
char *key_copy;
cache_entry_t *ce;
if (ce == NULL)
{
sfree (key_copy);
- ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
+ ERROR ("uc_insert: cache_alloc (%zu) failed.", ds->ds_num);
return (-1);
}
sstrncpy (ce->name, key, sizeof (ce->name));
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
switch (ds->ds[i].type)
{
c_avl_iterator_t *iter;
int status;
- int i;
-
+
pthread_mutex_lock (&cache_lock);
now = cdtime ();
continue;
/* If entry has not been updated, add to `keys' array */
- tmp = (char **) realloc ((void *) keys,
+ tmp = realloc ((void *) keys,
(keys_len + 1) * sizeof (char *));
if (tmp == NULL)
{
* including plugin specific meta data, rates, history, …. This must be done
* without holding the lock, otherwise we will run into a deadlock if a
* plugin calls the cache interface. */
- for (i = 0; i < keys_len; i++)
+ for (int i = 0; i < keys_len; i++)
{
value_list_t vl = VALUE_LIST_INIT;
* the timestamp again, so in theory it is possible we remove a value after
* it is updated here. */
pthread_mutex_lock (&cache_lock);
- for (i = 0; i < keys_len; i++)
+ for (int i = 0; i < keys_len; i++)
{
key = NULL;
ce = NULL;
char name[6 * DATA_MAX_NAME_LEN];
cache_entry_t *ce = NULL;
int status;
- int i;
if (FORMAT_VL (name, sizeof (name), vl) != 0)
{
return (-1);
}
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
switch (ds->ds[i].type)
{
case DS_TYPE_COUNTER:
{
- counter_t diff;
-
- /* check if the counter has wrapped around */
- if (vl->values[i].counter < ce->values_raw[i].counter)
- {
- if (ce->values_raw[i].counter <= 4294967295U)
- diff = (4294967295U - ce->values_raw[i].counter)
- + vl->values[i].counter;
- else
- diff = (18446744073709551615ULL - ce->values_raw[i].counter)
- + vl->values[i].counter;
- }
- else /* counter has NOT wrapped around */
- {
- diff = vl->values[i].counter - ce->values_raw[i].counter;
- }
-
+ counter_t diff = counter_diff (ce->values_raw[i].counter, vl->values[i].counter);
ce->values_gauge[i] = ((double) diff)
/ (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
ce->values_raw[i].counter = vl->values[i].counter;
case DS_TYPE_DERIVE:
{
- derive_t diff;
-
- diff = vl->values[i].derive - ce->values_raw[i].derive;
+ derive_t diff = vl->values[i].derive - ce->values_raw[i].derive;
ce->values_gauge[i] = ((double) diff)
/ (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
return (-1);
} /* switch (ds->ds[i].type) */
- DEBUG ("uc_update: %s: ds[%i] = %lf", name, i, ce->values_gauge[i]);
+ DEBUG ("uc_update: %s: ds[%zu] = %lf", name, i, ce->values_gauge[i]);
} /* for (i) */
/* Update the history if it exists. */
if (ce->history != NULL)
{
assert (ce->history_index < ce->history_length);
- for (i = 0; i < ce->values_num; i++)
+ for (size_t i = 0; i < ce->values_num; i++)
{
size_t hist_idx = (ce->values_num * ce->history_index) + i;
ce->history[hist_idx] = ce->values_gauge[i];
@@ -517,7 +502,7 @@ int uc_get_rate_by_name (const char *name, gauge_t **ret_values, size_t *ret_val
else
{
ret_num = ce->values_num;
- ret = (gauge_t *) malloc (ret_num * sizeof (gauge_t));
+ ret = malloc (ret_num * sizeof (*ret));
if (ret == NULL)
{
ERROR ("utils_cache: uc_get_rate_by_name: malloc failed.");
* values are returned. */
if (ret_num != (size_t) ds->ds_num)
{
- ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
+ ERROR ("utils_cache: uc_get_rate: ds[%s] has %zu values, "
"but uc_get_rate_by_name returned %zu.",
ds->type, ds->ds_num, ret_num);
sfree (ret);
if (status != 0)
{
- size_t i;
-
- for (i = 0; i < number; i++)
+ for (size_t i = 0; i < number; i++)
{
sfree (names[i]);
}
gauge_t *ret_history, size_t num_steps, size_t num_ds)
{
cache_entry_t *ce = NULL;
- size_t i;
int status = 0;
pthread_mutex_lock (&cache_lock);
return (-ENOMEM);
}
- for (i = ce->history_length * ce->values_num;
+ for (size_t i = ce->history_length * ce->values_num;
i < (num_steps * ce->values_num);
i++)
tmp[i] = NAN;
} /* if (ce->history_length < num_steps) */
/* Copy the values to the output buffer. */
- for (i = 0; i < num_steps; i++)
+ for (size_t i = 0; i < num_steps; i++)
{
size_t src_index;
size_t dst_index;
return (ret);
} /* int uc_inc_hits */
+/*
+ * Iterator interface
+ */
+uc_iter_t *uc_get_iterator (void)
+{
+ uc_iter_t *iter;
+
+ iter = (uc_iter_t *) calloc(1, sizeof (*iter));
+ if (iter == NULL)
+ return (NULL);
+
+ pthread_mutex_lock (&cache_lock);
+
+ iter->iter = c_avl_get_iterator (cache_tree);
+ if (iter->iter == NULL)
+ {
+ free (iter);
+ return (NULL);
+ }
+
+ return (iter);
+} /* uc_iter_t *uc_get_iterator */
+
+int uc_iterator_next (uc_iter_t *iter, char **ret_name)
+{
+ int status;
+
+ if (iter == NULL)
+ return (-1);
+
+ while ((status = c_avl_iterator_next (iter->iter,
+ (void *) &iter->name, (void *) &iter->entry)) == 0)
+ {
+ if (iter->entry->state == STATE_MISSING)
+ continue;
+
+ break;
+ }
+ if (status != 0) {
+ iter->name = NULL;
+ iter->entry = NULL;
+ return (-1);
+ }
+
+ if (ret_name != NULL)
+ *ret_name = iter->name;
+
+ return (0);
+} /* int uc_iterator_next */
+
+void uc_iterator_destroy (uc_iter_t *iter)
+{
+ if (iter == NULL)
+ return;
+
+ c_avl_iterator_destroy (iter->iter);
+ pthread_mutex_unlock (&cache_lock);
+
+ free (iter);
+} /* void uc_iterator_destroy */
+
+int uc_iterator_get_time (uc_iter_t *iter, cdtime_t *ret_time)
+{
+ if ((iter == NULL) || (iter->entry == NULL) || (ret_time == NULL))
+ return (-1);
+
+ *ret_time = iter->entry->last_time;
+ return (0);
+} /* int uc_iterator_get_name */
+
+int uc_iterator_get_values (uc_iter_t *iter, value_t **ret_values, size_t *ret_num)
+{
+ if ((iter == NULL) || (iter->entry == NULL)
+ || (ret_values == NULL) || (ret_num == NULL))
+ return (-1);
+
+ *ret_values = calloc (iter->entry->values_num, sizeof(*iter->entry->values_raw));
+ if (*ret_values == NULL)
+ return (-1);
+ for (size_t i = 0; i < iter->entry->values_num; ++i)
+ *ret_values[i] = iter->entry->values_raw[i];
+
+ *ret_num = iter->entry->values_num;
+
+ return (0);
+} /* int uc_iterator_get_values */
+
+int uc_iterator_get_interval (uc_iter_t *iter, cdtime_t *ret_interval)
+{
+ if ((iter == NULL) || (iter->entry == NULL) || (ret_interval == NULL))
+ return (-1);
+
+ *ret_interval = iter->entry->interval;
+ return (0);
+} /* int uc_iterator_get_name */
+
/*
* Meta data interface
*/
index 75bfc425a38c7c4624b89e8edf813a2433ca73fc..93c2519469f6f9436468719db5da0a49fc0fbdf1 100644 (file)
--- a/src/daemon/utils_cache.h
+++ b/src/daemon/utils_cache.h
/**
- * collectd - src/utils_cache.h
+ * collectd - utils_cache.h
* Copyright (C) 2007 Florian octo Forster
+ * Copyright (C) 2016 Sebastian tokkee Harl
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*
* Authors:
* Florian octo Forster <octo at collectd.org>
+ * Sebastian tokkee Harl <sh at tokkee.org>
**/
#ifndef UTILS_CACHE_H
int uc_get_history_by_name (const char *name,
gauge_t *ret_history, size_t num_steps, size_t num_ds);
+/*
+ * Iterator interface
+ */
+struct uc_iter_s;
+typedef struct uc_iter_s uc_iter_t;
+
+/*
+ * NAME
+ * uc_get_iterator
+ *
+ * DESCRIPTION
+ * Create an iterator for the cache. It will hold the cache lock until it's
+ * destroyed.
+ *
+ * RETURN VALUE
+ * An iterator object on success or NULL else.
+ */
+uc_iter_t *uc_get_iterator (void);
+
+/*
+ * NAME
+ * uc_iterator_next
+ *
+ * DESCRIPTION
+ * Advance the iterator to the next positiion and (optionally) returns the
+ * name of the entry.
+ *
+ * PARAMETERS
+ * `iter' The iterator object to advance.
+ * `ret_name' Pointer to a string where to store the name. The returned
+ * value is a copy of the value and has to be freed by the
+ * caller.
+ *
+ * RETURN VALUE
+ * Zero upon success or non-zero if the iterator ie NULL or no further
+ * values are available.
+ */
+int uc_iterator_next (uc_iter_t *iter, char **ret_name);
+void uc_iterator_destroy (uc_iter_t *iter);
+
+/* Return the timestamp of the value at the current position. */
+int uc_iterator_get_time (uc_iter_t *iter, cdtime_t *ret_time);
+/* Return the (raw) value at the current position. */
+int uc_iterator_get_values (uc_iter_t *iter, value_t **ret_values, size_t *ret_num);
+/* Return the interval of the value at the current position. */
+int uc_iterator_get_interval (uc_iter_t *iter, cdtime_t *ret_interval);
+
/*
* Meta data interface
*/
index 6c78d64dc86c01bc731ff5a09ed6688fd94a5587..1080c806b8697a170c46eb3d834fa226e52481af 100644 (file)
#include "utils_cache.h"
-gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
+gauge_t *uc_get_rate (__attribute__((unused)) data_set_t const *ds,
+ __attribute__((unused)) value_list_t const *vl)
{
return (NULL);
}
index 6193614940e34570265cff661c9517f38b349318..69909bb6710b22d6a8a120d11189ee1a6033e7ac 100644 (file)
**/
#include "collectd.h"
+
#include "utils_complain.h"
#include "plugin.h"
/* vcomplain returns 0 if it did not report, 1 else */
+__attribute__ ((format (printf, 3, 0)))
static int vcomplain (int level, c_complain_t *c,
const char *format, va_list ap)
{
} /* c_release */
/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
-
index 390f961626c969b61d7887a03e510ffe3aebaa73..9d96d35d4d5acca4197aa18e01c481b708775aaa 100644 (file)
* `c' Identifier for the complaint.
* `format' Message format - see the documentation of printf(3).
*/
+__attribute__ ((format(printf,3,4)))
void c_complain (int level, c_complain_t *c, const char *format, ...);
/*
*
* See `c_complain' for further details and a description of the parameters.
*/
+__attribute__ ((format(printf,3,4)))
void c_complain_once (int level, c_complain_t *c, const char *format, ...);
/*
*
* See `c_complain' for a description of the parameters.
*/
+__attribute__ ((format(printf,3,4)))
void c_do_release (int level, c_complain_t *c, const char *format, ...);
#define c_release(level, c, ...) \
do { \
index 1b5dca736ba59da0cf05a81ecf4a336dd378bbca..8637581149c890f45577cabb1e902099f52fb82b 100644 (file)
--- a/src/daemon/utils_heap.c
+++ b/src/daemon/utils_heap.c
**/
#include <stdlib.h>
-#include <string.h>
#include <errno.h>
#include <assert.h>
#include <pthread.h>
if (compare == NULL)
return (NULL);
- h = malloc (sizeof (*h));
+ h = calloc (1, sizeof (*h));
if (h == NULL)
return (NULL);
- memset (h, 0, sizeof (*h));
pthread_mutex_init (&h->lock, /* attr = */ NULL);
h->compare = compare;
-
+
h->list = NULL;
h->list_len = 0;
h->list_size = 0;
/* Reorganize the heap from bottom up. */
reheap (h, /* parent of this node = */ (index - 1) / 2, DIR_UP);
-
+
pthread_mutex_unlock (&h->lock);
return (0);
} /* int c_heap_insert */
index 6d71c43a13feb371af92033ee949a826e4cba67e..243554c63dba8afba2da304c1f09ec1bf2a00143 100644 (file)
--- a/src/daemon/utils_heap.h
+++ b/src/daemon/utils_heap.h
*
* PARAMETERS
* `compare' The function-pointer `compare' is used to compare two keys. It
- * has to return less than zero if it's first argument is smaller
+ * has to return less than zero if its first argument is smaller
* then the second argument, more than zero if the first argument
* is bigger than the second argument and zero if they are equal.
* If your keys are char-pointers, you can use the `strcmp'
index 53d0fba863f3b7cb6a117e5224107d9dc98cfb8c..54a9613abecac1bd5da1f2a3f8de9e7d777bb3cd 100644 (file)
* Florian octo Forster <octo at collectd.org>
*/
-#include "testing.h"
#include "collectd.h"
+
+#include "testing.h"
#include "utils_heap.h"
static int compare (void const *v0, void const *v1)
DEF_TEST(simple)
{
int values[] = { 9, 5, 6, 1, 3, 4, 0, 8, 2, 7 };
- int i;
c_heap_t *h;
CHECK_NOT_NULL(h = c_heap_create (compare));
- for (i = 0; i < 10; i++)
+ for (int i = 0; i < 10; i++)
CHECK_ZERO(c_heap_insert (h, &values[i]));
- for (i = 0; i < 5; i++)
+ for (int i = 0; i < 5; i++)
{
int *ret = NULL;
CHECK_NOT_NULL(ret = c_heap_get_root(h));
CHECK_ZERO(c_heap_insert (h, &values[4] /* = 3 */));
CHECK_ZERO(c_heap_insert (h, &values[5] /* = 4 */));
- for (i = 0; i < 10; i++)
+ for (int i = 0; i < 10; i++)
{
int *ret = NULL;
CHECK_NOT_NULL(ret = c_heap_get_root(h));
index 692a1e51bc12c9698025674c8f034d4cd05ba851..ff73ad74a4b3ed2cfb9690710fe917902778bd3c 100644 (file)
**/
/**
* Usage:
- *
+ *
* Define plugin's global pointer variable of type ignorelist_t:
* ignorelist_t *myconfig_ignore;
* If you know the state of the global ignore (IgnoreSelected),
@@ -88,50 +88,43 @@ static inline void ignorelist_append (ignorelist_t *il, ignorelist_item_t *item)
}
#if HAVE_REGEX_H
-static int ignorelist_append_regex(ignorelist_t *il, const char *entry)
+static int ignorelist_append_regex(ignorelist_t *il, const char *re_str)
{
regex_t *re;
- ignorelist_item_t *item;
+ ignorelist_item_t *entry;
int status;
- /* create buffer */
- re = malloc (sizeof (*re));
+ re = calloc (1, sizeof (*re));
if (re == NULL)
{
- ERROR ("ignorelist_append_regex: malloc failed.");
- return ENOMEM;
+ ERROR ("ignorelist_append_regex: calloc failed.");
+ return (ENOMEM);
}
- memset (re, 0, sizeof (*re));
- /* compile regex */
- status = regcomp (re, entry, REG_EXTENDED);
+ status = regcomp (re, re_str, REG_EXTENDED);
if (status != 0)
{
char errbuf[1024];
-
(void) regerror (status, re, errbuf, sizeof (errbuf));
- ERROR ("ignorelist_append_regex: Compiling regular expression \"%s\" failed: %s", entry, errbuf);
+ ERROR ("utils_ignorelist: regcomp failed: %s", errbuf);
+ ERROR ("ignorelist_append_regex: Compiling regular expression \"%s\" failed: %s", re_str, errbuf);
sfree (re);
- return status;
+ return (status);
}
- /* create new entry */
- item = malloc (sizeof (*item));
- if (item == NULL)
+ entry = calloc (1, sizeof (*entry));
+ if (entry == NULL)
{
- ERROR ("ignorelist_append_regex: malloc failed.");
+ ERROR ("ignorelist_append_regex: calloc failed.");
regfree (re);
sfree (re);
- return ENOMEM;
+ return (ENOMEM);
}
- memset (item, 0, sizeof (*item));
- item->rmatch = re;
-
- /* append new entry */
- ignorelist_append (il, item);
+ entry->rmatch = re;
+ ignorelist_append (il, entry);
return (0);
-} /* int ignorelist_append_regex(ignorelist_t *il, const char *entry) */
+} /* int ignorelist_append_regex */
#endif
static int ignorelist_append_string(ignorelist_t *il, const char *entry)
ignorelist_item_t *new;
/* create new entry */
- if ((new = malloc(sizeof(ignorelist_item_t))) == NULL )
+ if ((new = calloc(1, sizeof (*new))) == NULL )
{
ERROR ("cannot allocate new entry");
return (1);
}
- memset (new, '\0', sizeof(ignorelist_item_t));
new->smatch = sstrdup(entry);
/* append new entry */
{
ignorelist_t *il;
- il = malloc (sizeof (*il));
+ il = calloc (1, sizeof (*il));
if (il == NULL)
return NULL;
- memset (il, 0, sizeof (*il));
/*
* ->ignore == 0 => collect
}
sfree (il);
- il = NULL;
} /* void ignorelist_destroy (ignorelist_t *il) */
/*
/*
* append entry into ignorelist_t
- * return 1 for success
+ * return 0 for success
*/
int ignorelist_add (ignorelist_t *il, const char *entry)
{
*/
int ignorelist_match (ignorelist_t *il, const char *entry)
{
- ignorelist_item_t *traverse;
-
/* if no entries, collect all */
if ((il == NULL) || (il->head == NULL))
return (0);
return (0);
/* traverse list and check entries */
- for (traverse = il->head; traverse != NULL; traverse = traverse->next)
+ for (ignorelist_item_t *traverse = il->head; traverse != NULL; traverse = traverse->next)
{
#if HAVE_REGEX_H
if (traverse->rmatch != NULL)
index 4265286bdaf899dcb2bba34e97a712876d5455b0..60273382dec81950cfa61a2273d3103f79a8f664 100644 (file)
--- a/src/daemon/utils_llist.c
+++ b/src/daemon/utils_llist.c
* Florian Forster <octo at collectd.org>
*/
-#include "config.h"
-
#include <stdlib.h>
#include <string.h>
{
llist_t *ret;
- ret = (llist_t *) malloc (sizeof (llist_t));
+ ret = calloc (1, sizeof (*ret));
if (ret == NULL)
return (NULL);
- memset (ret, '\0', sizeof (llist_t));
-
return (ret);
}
{
llentry_t *e;
- e = (llentry_t *) malloc (sizeof (llentry_t));
+ e = malloc (sizeof (*e));
if (e)
{
e->key = key;
index 38472848a24c7fce26719fa1ae45b2ff74a27794..914b6e278c746c1dd04e44a603894377f3991c0c 100644 (file)
--- a/src/daemon/utils_match.c
+++ b/src/daemon/utils_match.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
}
ret_len = end - begin;
- ret = (char *) malloc (sizeof (char) * (ret_len + 1));
+ ret = malloc (ret_len + 1);
if (ret == NULL)
{
ERROR ("utils_match: match_substr: malloc failed.");
@@ -238,10 +239,9 @@ cu_match_t *match_create_callback (const char *regex, const char *excluderegex,
DEBUG ("utils_match: match_create_callback: regex = %s, excluderegex = %s",
regex, excluderegex);
- obj = (cu_match_t *) malloc (sizeof (cu_match_t));
+ obj = calloc (1, sizeof (*obj));
if (obj == NULL)
return (NULL);
- memset (obj, '\0', sizeof (cu_match_t));
status = regcomp (&obj->regex, regex, REG_EXTENDED | REG_NEWLINE);
if (status != 0)
cu_match_value_t *user_data;
cu_match_t *obj;
- user_data = (cu_match_value_t *) malloc (sizeof (cu_match_value_t));
+ user_data = calloc (1, sizeof (*user_data));
if (user_data == NULL)
return (NULL);
- memset (user_data, '\0', sizeof (cu_match_value_t));
user_data->ds_type = match_ds_type;
obj = match_create_callback (regex, excluderegex,
{
int status;
regmatch_t re_match[32];
- char *matches[32];
+ char *matches[32] = { 0 };
size_t matches_num;
- size_t i;
if ((obj == NULL) || (str == NULL))
return (-1);
if (status != 0)
return (0);
- memset (matches, '\0', sizeof (matches));
for (matches_num = 0; matches_num < STATIC_ARRAY_SIZE (matches); matches_num++)
{
if ((re_match[matches_num].rm_so < 0)
}
}
- for (i = 0; i < matches_num; i++)
+ for (size_t i = 0; i < matches_num; i++)
{
sfree (matches[i]);
}
index fee08717a7d464c809be8f23685117654d6bdab0..0488f913644a69ff26887a2a85073b0facd7ccf9 100644 (file)
**/
#include "collectd.h"
+
#include "utils_time.h"
#include "utils_random.h"
index 3e554973c7698dc54bd6d32c0d612e11270a1223..1bc28f724ea22e927e6981b09d28fd0d8de2bf8c 100644 (file)
--- a/src/daemon/utils_subst.c
+++ b/src/daemon/utils_subst.c
*/
#include "collectd.h"
+
#include "common.h"
#include "utils_subst.h"
-char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+char *subst (char *buf, size_t buflen, const char *string, size_t off1, size_t off2,
const char *replacement)
{
- char *buf_ptr = buf;
- size_t len = buflen;
+ char *out = buf;
+
+ char const *front;
+ char const *back;
+ size_t front_len;
+ size_t replacement_len;
+ size_t back_len;
+
+ if ((NULL == buf) || (0 == buflen) || (NULL == string) || (NULL == replacement))
+ return NULL;
- if ((NULL == buf) || (0 >= buflen) || (NULL == string)
- || (0 > off1) || (0 > off2) || (off1 > off2)
- || (NULL == replacement))
+ size_t string_len = strlen (string);
+ if ((off1 > string_len) || (off2 > string_len) || (off1 > off2))
return NULL;
- sstrncpy (buf_ptr, string,
- ((size_t)off1 + 1 > buflen) ? buflen : (size_t)off1 + 1);
- buf_ptr += off1;
- len -= off1;
+ front = string;
+ back = string + off2;
+ front_len = off1;
+ replacement_len = strlen (replacement);
+ back_len = strlen (back);
+
+ if (front_len >= buflen) {
+ front_len = buflen - 1;
+ replacement_len = 0;
+ back_len = 0;
+ } else if ((front_len + replacement_len) >= buflen) {
+ replacement_len = buflen - (front_len + 1);
+ back_len = 0;
+ } else if ((front_len + replacement_len + back_len) >= buflen) {
+ back_len = buflen - (front_len + replacement_len + 1);
+ } else {
+ buflen = front_len + replacement_len + back_len + 1;
+ }
+ assert ((front_len + replacement_len + back_len) == (buflen - 1));
- if (0 >= len)
- return buf;
+ if (front_len != 0) {
+ sstrncpy (out, front, front_len + 1);
+ out += front_len;
+ }
- sstrncpy (buf_ptr, replacement, len);
- buf_ptr += strlen (replacement);
- len -= strlen (replacement);
+ if (replacement_len != 0) {
+ sstrncpy (out, replacement, replacement_len + 1);
+ out += replacement_len;
+ }
- if (0 >= len)
- return buf;
+ if (back_len != 0) {
+ sstrncpy (out, back, back_len + 1);
+ out += back_len;
+ }
- sstrncpy (buf_ptr, string + off2, len);
+ out[0] = 0;
return buf;
} /* subst */
len = off1 + strlen (replacement) + strlen (string) - off2 + 1;
- buf = (char *)malloc (len);
+ buf = malloc (len);
if (NULL == buf)
return NULL;
char *subst_string (char *buf, size_t buflen, const char *string,
const char *needle, const char *replacement)
{
- char *temp;
size_t needle_len;
size_t i;
|| (needle == NULL) || (replacement == NULL))
return (NULL);
- temp = (char *) malloc (buflen);
- if (temp == NULL)
- {
- ERROR ("subst_string: malloc failed.");
- return (NULL);
- }
-
needle_len = strlen (needle);
- strncpy (buf, string, buflen);
+ sstrncpy (buf, string, buflen);
/* Limit the loop to prevent endless loops. */
for (i = 0; i < buflen; i++)
{
+ char temp[buflen];
char *begin_ptr;
size_t begin;
i, string, needle, replacement);
}
- sfree (temp);
return (buf);
} /* char *subst_string */
index 9085286a474c79da17428467e0865ae02bcb07f6..50df9c7ba0404a377e2b3a0967f58adfe931b039 100644 (file)
--- a/src/daemon/utils_subst.h
+++ b/src/daemon/utils_subst.h
*
* The function returns 'buf' on success, NULL else.
*/
-char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+char *subst (char *buf, size_t buflen, const char *string, size_t off1, size_t off2,
const char *replacement);
/*
diff --git a/src/daemon/utils_subst_test.c b/src/daemon/utils_subst_test.c
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+ * collectd - src/daemon/utils_subst_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
+#include "utils_subst.h"
+
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
+DEF_TEST(subst)
+{
+ struct {
+ const char *str;
+ int off1;
+ int off2;
+ const char *rplmt;
+ const char *want;
+ } cases[] = {
+ {"foo_____bar", 3, 8, " - ", "foo - bar"}, /* documentation example */
+ {"foo bar", 0, 2, "m", "mo bar"}, /* beginning, shorten */
+ {"foo bar", 0, 1, "m", "moo bar"}, /* beginning, same length */
+ {"foo bar", 0, 3, "milk", "milk bar"}, /* beginning, extend */
+ {"foo bar", 3, 6, "de", "fooder"}, /* center, shorten */
+ {"foo bar", 2, 6, "rste", "forster"}, /* center, same length */
+ {"foo bar", 1, 3, "ish", "fish bar"}, /* center, extend */
+ {"foo bar", 2, 7, "ul", "foul"}, /* end, shorten */
+ {"foo bar", 3, 7, "lish", "foolish"}, /* end, same length */
+ {"foo bar", 3, 7, "dwear", "foodwear"}, /* end, extend */
+ /* truncation (buffer is 16 chars) */
+ {"01234567890123", 8, 8, "", "01234567890123"},
+ {"01234567890123", 8, 8, "*", "01234567*890123"},
+ {"01234567890123", 8, 8, "**", "01234567**89012"},
+ /* input > buffer */
+ {"012345678901234----", 0, 0, "", "012345678901234"},
+ {"012345678901234----", 17, 18, "", "012345678901234"},
+ {"012345678901234----", 0, 3, "", "345678901234---"},
+ {"012345678901234----", 0, 4, "", "45678901234----"},
+ {"012345678901234----", 0, 5, "", "5678901234----"},
+ {"012345678901234----", 8, 8, "#", "01234567#890123"},
+ {"012345678901234----", 12, 12, "##", "012345678901##2"},
+ {"012345678901234----", 13, 13, "##", "0123456789012##"},
+ {"012345678901234----", 14, 14, "##", "01234567890123#"},
+ {"012345678901234----", 15, 15, "##", "012345678901234"},
+ {"012345678901234----", 16, 16, "##", "012345678901234"},
+ /* error cases */
+ {NULL, 3, 4, "_", NULL}, /* no input */
+ {"foo bar", 3, 10, "_", NULL}, /* offset exceeds input */
+ {"foo bar", 10, 13, "_", NULL}, /* offset exceeds input */
+ {"foo bar", 4, 3, "_", NULL}, /* off1 > off2 */
+ {"foo bar", 3, 4, NULL, NULL}, /* no replacement */
+ };
+
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16] = "!!!!!!!!!!!!!!!";
+
+ if (cases[i].want == NULL) {
+ OK(subst (buffer, sizeof (buffer), cases[i].str, cases[i].off1, cases[i].off2, cases[i].rplmt) == NULL);
+ continue;
+ }
+
+ OK(subst (buffer, sizeof (buffer), cases[i].str, cases[i].off1, cases[i].off2, cases[i].rplmt) == &buffer[0]);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+DEF_TEST(subst_string)
+{
+ struct {
+ const char *str;
+ const char *srch;
+ const char *rplmt;
+ const char *want;
+ } cases[] = {
+ {"Hello %{name}", "%{name}", "world", "Hello world"},
+ {"abcccccc", "abc", "cab", "ccccccab"},
+ {"(((()(())))())", "()", "", ""},
+ {"food booth", "oo", "ee", "feed beeth"},
+ {"foo bar", "baz", "qux", "foo bar"},
+ {"foo bar", "oo", "oo", "foo bar"},
+ {"sixteen chars", "chars", "characters", "sixteen charact"},
+ };
+
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ char buffer[16];
+
+ if (cases[i].want == NULL) {
+ OK(subst_string (buffer, sizeof (buffer), cases[i].str, cases[i].srch, cases[i].rplmt) == NULL);
+ continue;
+ }
+
+ OK(subst_string (buffer, sizeof (buffer), cases[i].str, cases[i].srch, cases[i].rplmt) == buffer);
+ EXPECT_EQ_STR(cases[i].want, buffer);
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(subst);
+ RUN_TEST(subst_string);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
index fe5dca89b891ef3b8c874b2ee7cb8d414e172409..0d8ed7c177fcb2aa12e1c7cf9d9dc3fb88108a50 100644 (file)
--- a/src/daemon/utils_tail.c
+++ b/src/daemon/utils_tail.c
**/
#include "collectd.h"
+
#include "common.h"
#include "utils_tail.h"
{
int seek_end = 0;
FILE *fh;
- struct stat stat_buf;
+ struct stat stat_buf = { 0 };
int status;
- memset (&stat_buf, 0, sizeof (stat_buf));
status = stat (obj->file, &stat_buf);
if (status != 0)
{
{
cu_tail_t *obj;
- obj = (cu_tail_t *) malloc (sizeof (cu_tail_t));
+ obj = calloc (1, sizeof (*obj));
if (obj == NULL)
return (NULL);
- memset (obj, '\0', sizeof (cu_tail_t));
obj->file = strdup (file);
if (obj->file == NULL)
index 8776ad11f3731f6596f5f7ee078c78c97cec53d6..ffcaa90a118a131e7d727c46e68844670227f2e3 100644 (file)
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_match.h"
int __attribute__((unused)) buflen)
{
cu_tail_match_t *obj = (cu_tail_match_t *) data;
- size_t i;
- for (i = 0; i < obj->matches_num; i++)
+ for (size_t i = 0; i < obj->matches_num; i++)
match_apply (obj->matches[i].match, buf);
return (0);
{
cu_tail_match_t *obj;
- obj = (cu_tail_match_t *) malloc (sizeof (cu_tail_match_t));
+ obj = calloc (1, sizeof (*obj));
if (obj == NULL)
return (NULL);
- memset (obj, '\0', sizeof (cu_tail_match_t));
obj->tail = cu_tail_create (filename);
if (obj->tail == NULL)
void tail_match_destroy (cu_tail_match_t *obj)
{
- size_t i;
-
if (obj == NULL)
return;
obj->tail = NULL;
}
- for (i = 0; i < obj->matches_num; i++)
+ for (size_t i = 0; i < obj->matches_num; i++)
{
cu_tail_match_match_t *match = obj->matches + i;
if (match->match != NULL)
{
cu_tail_match_match_t *temp;
- temp = (cu_tail_match_match_t *) realloc (obj->matches,
+ temp = realloc (obj->matches,
sizeof (cu_tail_match_match_t) * (obj->matches_num + 1));
if (temp == NULL)
return (-1);
if (match == NULL)
return (-1);
- user_data = (cu_tail_match_simple_t *) malloc (sizeof (cu_tail_match_simple_t));
+ user_data = calloc (1, sizeof (*user_data));
if (user_data == NULL)
{
match_destroy (match);
return (-1);
}
- memset (user_data, '\0', sizeof (cu_tail_match_simple_t));
sstrncpy (user_data->plugin, plugin, sizeof (user_data->plugin));
if (plugin_instance != NULL)
{
char buffer[4096];
int status;
- size_t i;
status = cu_tail_read (obj->tail, buffer, sizeof (buffer), tail_callback,
(void *) obj);
return (status);
}
- for (i = 0; i < obj->matches_num; i++)
+ for (size_t i = 0; i < obj->matches_num; i++)
{
cu_tail_match_match_t *lt_match = obj->matches + i;
index 4a8df89d69e70c147e1fa8820c7884d1931b427c..784e109484a2725d82b3660b8abc996fa7ffe856 100644 (file)
**/
#include "collectd.h"
+
#include "common.h"
#include "utils_avltree.h"
#include "utils_threshold.h"
if (vl == NULL)
return (EINVAL);
- /* Is this lock really necessary? */
- pthread_mutex_lock (&threshold_lock);
+ /* Is this lock really necessary? */
+ pthread_mutex_lock (&threshold_lock);
t = threshold_search (vl);
if (t == NULL) {
- pthread_mutex_unlock (&threshold_lock);
+ pthread_mutex_unlock (&threshold_lock);
return (ENOENT);
- }
+ }
memcpy (ret_threshold, t, sizeof (*ret_threshold));
- pthread_mutex_unlock (&threshold_lock);
+ pthread_mutex_unlock (&threshold_lock);
ret_threshold->next = NULL;
index bf097fae0f2ef62bae851f1ef1b4e16298b29d54..a5c3373723efc23e0254425397bcdda4cc0fe246 100644 (file)
threshold_t *threshold_search (const value_list_t *vl);
-int ut_search_threshold (const value_list_t *vl,
+int ut_search_threshold (const value_list_t *vl,
threshold_t *ret_threshold);
#endif /* UTILS_THRESHOLD_H */
index 6603c15e89f161afc832a5e2cd8ef08b335564ea..86476ea63b4cd95728cfd843a48b52d26859d979 100644 (file)
--- a/src/daemon/utils_time.c
+++ b/src/daemon/utils_time.c
/**
* collectd - src/utils_time.c
- * Copyright (C) 2010 Florian octo Forster
+ * Copyright (C) 2010-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Florian octo Forster <ff at octo.it>
+ * Florian octo Forster <octo at collectd.org>
**/
#include "collectd.h"
+
#include "utils_time.h"
#include "plugin.h"
#include "common.h"
-#if HAVE_CLOCK_GETTIME
+#ifndef DEFAULT_MOCK_TIME
+# define DEFAULT_MOCK_TIME 1542455354518929408ULL
+#endif
+
+#ifdef MOCK_TIME
+cdtime_t cdtime_mock = (cdtime_t) MOCK_TIME;
+
+cdtime_t cdtime (void)
+{
+ return cdtime_mock;
+}
+#else /* !MOCK_TIME */
+# if HAVE_CLOCK_GETTIME
cdtime_t cdtime (void) /* {{{ */
{
int status;
return (TIMESPEC_TO_CDTIME_T (&ts));
} /* }}} cdtime_t cdtime */
-#else
+# else /* !HAVE_CLOCK_GETTIME */
/* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
cdtime_t cdtime (void) /* {{{ */
{
return (TIMEVAL_TO_CDTIME_T (&tv));
} /* }}} cdtime_t cdtime */
+# endif
#endif
-size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t) /* {{{ */
+/* format_zone reads time zone information from "extern long timezone", exported
+ * by <time.h>, and formats it according to RFC 3339. This differs from
+ * strftime()'s "%z" format by including a colon between hour and minute. */
+static int format_zone (char *buffer, size_t buffer_size, struct tm const *tm) /* {{{ */
+{
+ char tmp[7];
+ size_t sz;
+
+ if ((buffer == NULL) || (buffer_size < 7))
+ return EINVAL;
+
+ sz = strftime (tmp, sizeof (tmp), "%z", tm);
+ if (sz == 0)
+ return ENOMEM;
+ if (sz != 5)
+ {
+ DEBUG ("format_zone: strftime(\"%%z\") = \"%s\", want \"+hhmm\"", tmp);
+ sstrncpy (buffer, tmp, buffer_size);
+ return 0;
+ }
+
+ buffer[0] = tmp[0];
+ buffer[1] = tmp[1];
+ buffer[2] = tmp[2];
+ buffer[3] = ':';
+ buffer[4] = tmp[3];
+ buffer[5] = tmp[4];
+ buffer[6] = 0;
+
+ return 0;
+} /* }}} int format_zone */
+
+static int format_rfc3339 (char *buffer, size_t buffer_size, cdtime_t t, _Bool print_nano) /* {{{ */
{
struct timespec t_spec;
struct tm t_tm;
-
+ char base[20]; /* 2006-01-02T15:04:05 */
+ char nano[11]; /* .999999999 */
+ char zone[7]; /* +00:00 */
+ char *fields[] = {base, nano, zone};
size_t len;
+ int status;
CDTIME_T_TO_TIMESPEC (t, &t_spec);
NORMALIZE_TIMESPEC (t_spec);
- if (localtime_r ((time_t *)&t_spec.tv_sec, &t_tm) == NULL) {
+ if (localtime_r (&t_spec.tv_sec, &t_tm) == NULL) {
char errbuf[1024];
- ERROR ("cdtime_to_iso8601: localtime_r failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (0);
+ status = errno;
+ ERROR ("format_rfc3339: localtime_r failed: %s",
+ sstrerror (status, errbuf, sizeof (errbuf)));
+ return (status);
}
- len = strftime (s, max, "%Y-%m-%dT%H:%M:%S", &t_tm);
+ len = strftime (base, sizeof (base), "%Y-%m-%dT%H:%M:%S", &t_tm);
if (len == 0)
- return 0;
+ return ENOMEM;
- if (max - len > 2) {
- int n = snprintf (s + len, max - len, ".%09i", (int)t_spec.tv_nsec);
- len += (n < max - len) ? n : max - len;
- }
+ if (print_nano)
+ ssnprintf (nano, sizeof (nano), ".%09ld", (long) t_spec.tv_nsec);
+ else
+ sstrncpy (nano, "", sizeof (nano));
- if (max - len > 3) {
- int n = strftime (s + len, max - len, "%z", &t_tm);
- len += (n < max - len) ? n : max - len;
- }
+ status = format_zone (zone, sizeof (zone), &t_tm);
+ if (status != 0)
+ return status;
+
+ if (strjoin (buffer, buffer_size, fields, STATIC_ARRAY_SIZE (fields), "") < 0)
+ return ENOMEM;
+ return 0;
+} /* }}} int format_rfc3339 */
+
+int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */
+{
+ if (buffer_size < RFC3339_SIZE)
+ return ENOMEM;
+
+ return format_rfc3339 (buffer, buffer_size, t, 0);
+} /* }}} size_t cdtime_to_rfc3339 */
+
+int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */
+{
+ if (buffer_size < RFC3339NANO_SIZE)
+ return ENOMEM;
- s[max - 1] = '\0';
- return len;
-} /* }}} size_t cdtime_to_iso8601 */
+ return format_rfc3339 (buffer, buffer_size, t, 1);
+} /* }}} size_t cdtime_to_rfc3339nano */
/* vim: set sw=2 sts=2 et fdm=marker : */
index 9b08e8e4de68f011d24b4dc947c9d23922506544..4d88dccb6684ec3f4c823f3429ce5a9455d35e1a 100644 (file)
--- a/src/daemon/utils_time.h
+++ b/src/daemon/utils_time.h
/**
- * collectd - src/utils_time.h
- * Copyright (C) 2010 Florian octo Forster
+ * collectd - src/daemon/utils_time.h
+ * Copyright (C) 2010-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Florian octo Forster <ff at octo.it>
+ * Florian octo Forster <octo at collectd.org>
**/
#ifndef UTILS_TIME_H
#include "collectd.h"
+#ifdef TESTING_H
+/* cdtime_mock is the time returned by cdtime() when build with
+ * -DMOCK_TIME */
+extern cdtime_t cdtime_mock;
+#endif
+
/*
* "cdtime_t" is a 64bit unsigned integer. The time is stored at a 2^-30 second
* resolution, i.e. the most significant 34 bit are used to store the time in
* manner is that comparing times and calculating differences is as simple as
* it is with "time_t", i.e. a simple integer comparison / subtraction works.
*/
-/*
+/*
* cdtime_t is defined in "collectd.h" */
/* typedef uint64_t cdtime_t; */
/* 2^30 = 1073741824 */
-#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) * 1073741824)
-#define CDTIME_T_TO_TIME_T(t) ((time_t) ((t) / 1073741824))
+#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) << 30)
+
+#define MS_TO_CDTIME_T(ms) (((((cdtime_t) (ms)) / 1000) << 30) | \
+ ((((((cdtime_t) (ms)) % 1000) << 30) + 500) / 1000))
+#define US_TO_CDTIME_T(us) (((((cdtime_t) (us)) / 1000000) << 30) | \
+ ((((((cdtime_t) (us)) % 1000000) << 30) + 500000) / 1000000))
+#define NS_TO_CDTIME_T(ns) (((((cdtime_t) (ns)) / 1000000000) << 30) | \
+ ((((((cdtime_t) (ns)) % 1000000000) << 30) + 500000000) / 1000000000))
+
+#define CDTIME_T_TO_TIME_T(t) ((time_t) (((t) + (1 << 29)) >> 30))
+#define CDTIME_T_TO_MS(t) ((uint64_t) ((((t) >> 30) * 1000) + \
+ ((((t) & 0x3fffffff) * 1000 + (1 << 29)) >> 30)))
+#define CDTIME_T_TO_US(t) ((uint64_t) ((((t) >> 30) * 1000000) + \
+ ((((t) & 0x3fffffff) * 1000000 + (1 << 29)) >> 30)))
+#define CDTIME_T_TO_NS(t) ((uint64_t) ((((t) >> 30) * 1000000000) + \
+ ((((t) & 0x3fffffff) * 1000000000 + (1 << 29)) >> 30)))
#define CDTIME_T_TO_DOUBLE(t) (((double) (t)) / 1073741824.0)
#define DOUBLE_TO_CDTIME_T(d) ((cdtime_t) ((d) * 1073741824.0))
-#define MS_TO_CDTIME_T(ms) ((cdtime_t) (((double) (ms)) * 1073741.824))
-#define CDTIME_T_TO_MS(t) ((long) (((double) (t)) / 1073741.824))
-#define US_TO_CDTIME_T(us) ((cdtime_t) (((double) (us)) * 1073.741824))
-#define CDTIME_T_TO_US(t) ((suseconds_t) (((double) (t)) / 1073.741824))
-#define NS_TO_CDTIME_T(ns) ((cdtime_t) (((double) (ns)) * 1.073741824))
-#define CDTIME_T_TO_NS(t) ((long) (((double) (t)) / 1.073741824))
-
-#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do { \
- (tvp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \
- (tvp)->tv_usec = CDTIME_T_TO_US ((cdt) % 1073741824); \
+#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do { \
+ (tvp)->tv_sec = (time_t) ((cdt) >> 30); \
+ (tvp)->tv_usec = (suseconds_t) ((((cdt) & 0x3fffffff) * 1000000 + (1 << 29)) >> 30); \
} while (0)
-#define TIMEVAL_TO_CDTIME_T(tv) (TIME_T_TO_CDTIME_T ((tv)->tv_sec) \
- + US_TO_CDTIME_T ((tv)->tv_usec))
+#define TIMEVAL_TO_CDTIME_T(tv) US_TO_CDTIME_T(1000000 * (tv)->tv_sec + (tv)->tv_usec)
-#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do { \
- (tsp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \
- (tsp)->tv_nsec = CDTIME_T_TO_NS ((cdt) % 1073741824); \
+#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do { \
+ (tsp)->tv_sec = (time_t) ((cdt) >> 30); \
+ (tsp)->tv_nsec = (long) ((((cdt) & 0x3fffffff) * 1000000000 + (1 << 29)) >> 30); \
} while (0)
-#define TIMESPEC_TO_CDTIME_T(ts) (TIME_T_TO_CDTIME_T ((ts)->tv_sec) \
- + NS_TO_CDTIME_T ((ts)->tv_nsec))
+#define TIMESPEC_TO_CDTIME_T(ts) NS_TO_CDTIME_T(1000000000ULL * (ts)->tv_sec + (ts)->tv_nsec)
cdtime_t cdtime (void);
-/* format a cdtime_t value in ISO 8601 format:
- * returns the number of characters written to the string (not including the
- * terminating null byte or 0 on error; the function ensures that the string
- * is null terminated */
-size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t);
+#define RFC3339_SIZE 26
+#define RFC3339NANO_SIZE 36
+
+/* rfc3339 formats a cdtime_t time in RFC 3339 format with second precision. */
+int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t);
+
+/* rfc3339nano formats a cdtime_t time in RFC 3339 format with nanosecond
+ * precision. */
+int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t);
#endif /* UTILS_TIME_H */
/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/utils_time_mock.c b/src/daemon/utils_time_mock.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * collectd - src/tests/mock/utils_time.c
- * Copyright (C) 2013 Florian octo Forster
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- * Florian octo Forster <octo at collectd.org>
- */
-
-#include "utils_time.h"
-
-cdtime_t cdtime (void)
-{
- return (0);
-}
-
diff --git a/src/daemon/utils_time_test.c b/src/daemon/utils_time_test.c
--- /dev/null
@@ -0,0 +1,126 @@
+/**
+ * collectd - src/daemon/utils_time_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#define DBL_PRECISION 1e-3
+
+#include "collectd.h"
+
+#include "testing.h"
+#include "utils_time.h"
+
+DEF_TEST(conversion)
+{
+ struct {
+ cdtime_t t;
+ double d;
+ time_t tt;
+ uint64_t ms;
+ struct timeval tv;
+ struct timespec ts;
+ } cases[] = {
+ /* cdtime double time_t milliseconds timeval timespec */
+ { 0, 0.0 , 0, 0, { 0, 0}, { 0, 0}},
+ { 10737418240ULL, 10.0 , 10, 10000, { 10, 0}, { 10, 0}},
+ {1542908534771941376ULL, 1436945549.0 , 1436945549, 1436945549000ULL, {1436945549, 0}, {1436945549, 0}},
+ {1542908535540740522ULL, 1436945549.716, 1436945550, 1436945549716ULL, {1436945549, 716000}, {1436945549, 716000000}},
+ // 1426076671.123 * 2^30 = 1531238166015458148.352
+ {1531238166015458148ULL, 1426076671.123, 1426076671, 1426076671123ULL, {1426076671, 123000}, {1426076671, 123000000}},
+ // 1426076681.234 * 2^30 = 1531238176872061730.816
+ {1531238176872061731ULL, 1426076681.234, 1426076681, 1426076681234ULL, {1426076681, 234000}, {1426076681, 234000000}},
+ // 1426083986.314 * 2^30 = 1531246020641985396.736
+ {1531246020641985397ULL, 1426083986.314, 1426083986, 1426083986314ULL, {1426083986, 314000}, {1426083986, 314000000}},
+ // 1426083986.494142531 * 2^30 = 1531246020835411966.5
+ {1531246020835411967ULL, 1426083986.494, 1426083986, 1426083986494ULL, {1426083986, 494143}, {1426083986, 494142531}},
+ // 1426083986.987410814 * 2^30 = 1531246021365054752.4
+ {1531246021365054752ULL, 1426083986.987, 1426083987, 1426083986987ULL, {1426083986, 987411}, {1426083986, 987410814}},
+
+ /* These cases test the cdtime_t -> ns conversion rounds correctly. */
+ // 1546167635576736987 / 2^30 = 1439980823.1524536265...
+ {1546167635576736987ULL, 1439980823.152, 1439980823, 1439980823152ULL, {1439980823, 152454}, {1439980823, 152453627}},
+ // 1546167831554815222 / 2^30 = 1439981005.6712620165...
+ {1546167831554815222ULL, 1439981005.671, 1439981006, 1439981005671ULL, {1439981005, 671262}, {1439981005, 671262017}},
+ // 1546167986577716567 / 2^30 = 1439981150.0475896215...
+ {1546167986577716567ULL, 1439981150.048, 1439981150, 1439981150048ULL, {1439981150, 47590}, {1439981150, 47589622}},
+ };
+
+ for (size_t i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+ struct timeval tv;
+ struct timespec ts;
+
+ // cdtime -> s
+ EXPECT_EQ_UINT64 (cases[i].tt, CDTIME_T_TO_TIME_T (cases[i].t));
+
+ // cdtime -> ms
+ EXPECT_EQ_UINT64(cases[i].ms, CDTIME_T_TO_MS (cases[i].t));
+
+ // cdtime -> us
+ CDTIME_T_TO_TIMEVAL (cases[i].t, &tv);
+ EXPECT_EQ_UINT64 (cases[i].tv.tv_sec, tv.tv_sec);
+ EXPECT_EQ_UINT64 (cases[i].tv.tv_usec, tv.tv_usec);
+
+ // cdtime -> ns
+ CDTIME_T_TO_TIMESPEC (cases[i].t, &ts);
+ EXPECT_EQ_UINT64 (cases[i].ts.tv_sec, ts.tv_sec);
+ EXPECT_EQ_UINT64 (cases[i].ts.tv_nsec, ts.tv_nsec);
+
+ // cdtime -> double
+ EXPECT_EQ_DOUBLE (cases[i].d, CDTIME_T_TO_DOUBLE (cases[i].t));
+ }
+
+ return 0;
+}
+
+/* These cases test the ns -> cdtime_t conversion rounds correctly. */
+DEF_TEST(ns_to_cdtime)
+{
+ struct {
+ uint64_t ns;
+ cdtime_t want;
+ } cases[] = {
+ // 1439981652801860766 * 2^30 / 10^9 = 1546168526406004689.4
+ {1439981652801860766ULL, 1546168526406004689ULL},
+ // 1439981836985281914 * 2^30 / 10^9 = 1546168724171447263.4
+ {1439981836985281914ULL, 1546168724171447263ULL},
+ // 1439981880053705608 * 2^30 / 10^9 = 1546168770415815077.4
+ {1439981880053705608ULL, 1546168770415815077ULL},
+ };
+
+ for (size_t i = 0; i < (sizeof (cases) / sizeof (cases[0])); i++) {
+ EXPECT_EQ_UINT64 (cases[i].want, NS_TO_CDTIME_T (cases[i].ns));
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(conversion);
+ RUN_TEST(ns_to_cdtime);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/dbi.c b/src/dbi.c
index a7963ea223371f5d70a4ef63f2d0a3a6263db22a..068bf4d2f014c0643c02240dcebe4abdd3336b34 100644 (file)
--- a/src/dbi.c
+++ b/src/dbi.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_db_query.h"
#include <dbi/dbi.h>
char *name;
char *select_db;
+ cdtime_t interval;
+
char *driver;
char *host;
cdbi_driver_option_t *driver_options;
else if (src_type == DBI_TYPE_STRING)
{
const char *value;
-
+
value = dbi_result_get_string_idx (res, index);
if (value == NULL)
sstrncpy (buffer, "", buffer_size);
static void cdbi_database_free (cdbi_database_t *db) /* {{{ */
{
- size_t i;
-
if (db == NULL)
return;
sfree (db->name);
sfree (db->driver);
- for (i = 0; i < db->driver_options_num; i++)
+ for (size_t i = 0; i < db->driver_options_num; i++)
{
sfree (db->driver_options[i].key);
if (!db->driver_options[i].is_numeric)
sfree (db->driver_options);
if (db->q_prep_areas)
- for (i = 0; i < db->queries_num; ++i)
+ for (size_t i = 0; i < db->queries_num; ++i)
udb_query_delete_preparation_area (db->q_prep_areas[i]);
free (db->q_prep_areas);
* </Result>
* ...
* </Query>
- *
+ *
* <Database "plugin_instance1">
* Driver "mysql"
+ * Interval 120
* DriverOption "hostname" "localhost"
* ...
* Query "plugin_instance0"
@@ -237,7 +238,7 @@ static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ *
return (-1);
}
- option = (cdbi_driver_option_t *) realloc (db->driver_options,
+ option = realloc (db->driver_options,
sizeof (*option) * (db->driver_options_num + 1));
if (option == NULL)
{
{
cdbi_database_t *db;
int status;
- int i;
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_STRING))
return (-1);
}
- db = (cdbi_database_t *) malloc (sizeof (*db));
+ db = calloc (1, sizeof (*db));
if (db == NULL)
{
- ERROR ("dbi plugin: malloc failed.");
+ ERROR ("dbi plugin: calloc failed.");
return (-1);
}
- memset (db, 0, sizeof (*db));
status = cf_util_get_string (ci, &db->name);
if (status != 0)
}
/* Fill the `cdbi_database_t' structure.. */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
&db->queries, &db->queries_num);
else if (strcasecmp ("Host", child->key) == 0)
status = cf_util_get_string (child, &db->host);
+ else if (strcasecmp ("Interval", child->key) == 0)
+ status = cf_util_get_cdtime(child, &db->interval);
else
{
WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
while ((status == 0) && (db->queries_num > 0))
{
- db->q_prep_areas = (udb_query_preparation_area_t **) calloc (
- db->queries_num, sizeof (*db->q_prep_areas));
-
+ db->q_prep_areas = calloc (db->queries_num, sizeof (*db->q_prep_areas));
if (db->q_prep_areas == NULL)
{
- WARNING ("dbi plugin: malloc failed");
+ WARNING ("dbi plugin: calloc failed");
status = -1;
break;
}
- for (i = 0; i < db->queries_num; ++i)
+ for (size_t i = 0; i < db->queries_num; ++i)
{
db->q_prep_areas[i]
= udb_query_allocate_preparation_area (db->queries[i]);
{
cdbi_database_t **temp;
- temp = (cdbi_database_t **) realloc (databases,
+ temp = realloc (databases,
sizeof (*databases) * (databases_num + 1));
if (temp == NULL)
{
}
else
{
- user_data_t ud;
char *name = NULL;
databases = temp;
databases[databases_num] = db;
databases_num++;
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) db;
- ud.free_func = NULL;
name = ssnprintf_alloc("dbi:%s", db->name);
+ user_data_t ud = {
+ .data = db
+ };
+
plugin_register_complex_read (/* group = */ NULL,
/* name = */ name ? name : db->name,
/* callback = */ cdbi_read_database,
- /* interval = */ NULL,
+ /* interval = */ (db->interval > 0) ? db->interval : 0,
/* user_data = */ &ud);
free (name);
}
static int cdbi_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("Query", child->key) == 0)
char **column_names;
char **column_values;
int status;
- size_t i;
/* Macro that cleans up dynamically allocated memory and returns the
* specified status. */
column_names = NULL;
column_values = NULL;
- res = NULL;
statement = udb_query_get_statement (q);
assert (statement != NULL);
}
/* Allocate `column_names' and `column_values'. {{{ */
- column_names = (char **) calloc (column_num, sizeof (char *));
+ column_names = calloc (column_num, sizeof (*column_names));
if (column_names == NULL)
{
- ERROR ("dbi plugin: malloc failed.");
+ ERROR ("dbi plugin: calloc failed.");
BAIL_OUT (-1);
}
- column_names[0] = (char *) calloc (column_num,
- DATA_MAX_NAME_LEN * sizeof (char));
+ column_names[0] = calloc (column_num, DATA_MAX_NAME_LEN);
if (column_names[0] == NULL)
{
- ERROR ("dbi plugin: malloc failed.");
+ ERROR ("dbi plugin: calloc failed.");
BAIL_OUT (-1);
}
- for (i = 1; i < column_num; i++)
+ for (size_t i = 1; i < column_num; i++)
column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;
- column_values = (char **) calloc (column_num, sizeof (char *));
+ column_values = calloc (column_num, sizeof (*column_values));
if (column_values == NULL)
{
- ERROR ("dbi plugin: malloc failed.");
+ ERROR ("dbi plugin: calloc failed.");
BAIL_OUT (-1);
}
- column_values[0] = (char *) calloc (column_num,
- DATA_MAX_NAME_LEN * sizeof (char));
+ column_values[0] = calloc (column_num, DATA_MAX_NAME_LEN);
if (column_values[0] == NULL)
{
- ERROR ("dbi plugin: malloc failed.");
+ ERROR ("dbi plugin: calloc failed.");
BAIL_OUT (-1);
}
- for (i = 1; i < column_num; i++)
+ for (size_t i = 1; i < column_num; i++)
column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
/* }}} */
/* Copy the field names to `column_names' */
- for (i = 0; i < column_num; i++) /* {{{ */
+ for (size_t i = 0; i < column_num; i++) /* {{{ */
{
const char *column_name;
udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g),
/* plugin = */ "dbi", db->name,
- column_names, column_num, /* interval = */ 0);
+ column_names, column_num, /* interval = */ (db->interval > 0) ? db->interval : 0);
/* 0 = error; 1 = success; */
status = dbi_result_first_row (res); /* {{{ */
{
status = 0;
/* Copy the value of the columns to `column_values' */
- for (i = 0; i < column_num; i++) /* {{{ */
+ for (size_t i = 0; i < column_num; i++) /* {{{ */
{
status = cdbi_result_get_field (res, (unsigned int) (i + 1),
column_values[i], DATA_MAX_NAME_LEN);
{
dbi_driver driver;
dbi_conn connection;
- size_t i;
int status;
if (db->connection != NULL)
* encountered, it will get a list of options understood by the driver and
* report that as `INFO'. This way, users hopefully don't have too much
* trouble finding out how to configure the plugin correctly.. */
- for (i = 0; i < db->driver_options_num; i++)
+ for (size_t i = 0; i < db->driver_options_num; i++)
{
if (db->driver_options[i].is_numeric)
{
if (status != 0)
{
- char const *opt;
-
INFO ("dbi plugin: This is a list of all options understood "
"by the `%s' driver:", db->driver);
- for (opt = dbi_conn_get_option_list (connection, NULL);
+ for (const char *opt = dbi_conn_get_option_list (connection, NULL);
opt != NULL;
opt = dbi_conn_get_option_list (connection, opt))
{
static int cdbi_read_database (user_data_t *ud) /* {{{ */
{
cdbi_database_t *db = (cdbi_database_t *) ud->data;
- size_t i;
int success;
int status;
/* TODO: Complain if `db_version == 0' */
success = 0;
- for (i = 0; i < db->queries_num; i++)
+ for (size_t i = 0; i < db->queries_num; i++)
{
/* Check if we know the database's version and if so, if this query applies
* to that version. */
static int cdbi_shutdown (void) /* {{{ */
{
- size_t i;
-
- for (i = 0; i < databases_num; i++)
+ for (size_t i = 0; i < databases_num; i++)
{
if (databases[i]->connection != NULL)
{
diff --git a/src/df.c b/src/df.c
index ff701725f42dc80b3084754503966eb0ca5613ab..4a86799c2e5d7ec7a3bbb6b3003bca8879eede0b 100644 (file)
--- a/src/df.c
+++ b/src/df.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_mount.h"
#include "utils_ignorelist.h"
#endif
/* struct STATANYFS statbuf; */
cu_mount_t *mnt_list;
- cu_mount_t *mnt_ptr;
mnt_list = NULL;
if (cu_mount_getlist (&mnt_list) == NULL)
return (-1);
}
- for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
+ for (cu_mount_t *mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
{
unsigned long long blocksize;
char disk_name[256];
sstrncpy (disk_name, "root", sizeof (disk_name));
else
{
- int i, len;
+ int len;
sstrncpy (disk_name, mnt_ptr->dir + 1, sizeof (disk_name));
len = strlen (disk_name);
- for (i = 0; i < len; i++)
+ for (int i = 0; i < len; i++)
if (disk_name[i] == '/')
disk_name[i] = '-';
}
diff --git a/src/disk.c b/src/disk.c
index 1c3dd98d7d2a93318e8ce0318fbd8acbbd15e016..d7eb0a5c407011c9789ee2fe43e4d46f938e2414 100644 (file)
--- a/src/disk.c
+++ b/src/disk.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_ignorelist.h"
#if HAVE_IOKIT_IOBSD_H
# include <IOKit/IOBSD.h>
#endif
+#if KERNEL_FREEBSD
+#include <devstat.h>
+#include <libgeom.h>
+#endif
#if HAVE_LIMITS_H
# include <limits.h>
derive_t avg_read_time;
derive_t avg_write_time;
+ _Bool has_merged;
+ _Bool has_in_progress;
+ _Bool has_io_time;
+
struct diskstats *next;
} diskstats_t;
static diskstats_t *disklist;
/* #endif KERNEL_LINUX */
+#elif KERNEL_FREEBSD
+static struct gmesh geom_tree;
+/* #endif KERNEL_FREEBSD */
#elif HAVE_LIBKSTAT
#define MAX_NUMDISK 1024
/* #endif HAVE_IOKIT_IOKITLIB_H */
#elif KERNEL_LINUX
- /* do nothing */
+#if HAVE_LIBUDEV
+ if (conf_udev_name_attr != NULL)
+ {
+ handle_udev = udev_new();
+ if (handle_udev == NULL) {
+ ERROR ("disk plugin: udev_new() failed!");
+ return (-1);
+ }
+ }
+#endif /* HAVE_LIBUDEV */
/* #endif KERNEL_LINUX */
+#elif KERNEL_FREEBSD
+ int rv;
+
+ rv = geom_gettree(&geom_tree);
+ if (rv != 0) {
+ ERROR ("geom_gettree() failed, returned %d", rv);
+ return (-1);
+ }
+ rv = geom_stats_open();
+ if (rv != 0) {
+ ERROR ("geom_stats_open() failed, returned %d", rv);
+ return (-1);
+ }
+/* #endif KERNEL_FREEBSD */
+
#elif HAVE_LIBKSTAT
kstat_t *ksp_chain;
return (0);
} /* int disk_init */
+static int disk_shutdown (void)
+{
+#if KERNEL_LINUX
+#if HAVE_LIBUDEV
+ if (handle_udev != NULL)
+ udev_unref(handle_udev);
+#endif /* HAVE_LIBUDEV */
+#endif /* KERNEL_LINUX */
+ return (0);
+} /* int disk_shutdown */
+
static void disk_submit (const char *plugin_instance,
const char *type,
derive_t read, derive_t write)
value_t values[2];
value_list_t vl = VALUE_LIST_INIT;
- /* Both `ignorelist' and `plugin_instance' may be NULL. */
- if (ignorelist_match (ignorelist, plugin_instance) != 0)
- return;
-
values[0].derive = read;
values[1].derive = write;
plugin_dispatch_values (&vl);
} /* void disk_submit */
-#if KERNEL_LINUX
-static void submit_in_progress (char const *disk_name, gauge_t in_progress)
+#if KERNEL_FREEBSD || KERNEL_LINUX
+static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time)
{
- value_t v;
+ value_t values[2];
value_list_t vl = VALUE_LIST_INIT;
- if (ignorelist_match (ignorelist, disk_name) != 0)
- return;
-
- v.gauge = in_progress;
+ values[0].derive = io_time;
+ values[1].derive = weighted_time;
- vl.values = &v;
- vl.values_len = 1;
+ vl.values = values;
+ vl.values_len = 2;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
- sstrncpy (vl.plugin_instance, disk_name, sizeof (vl.plugin_instance));
- sstrncpy (vl.type, "pending_operations", sizeof (vl.type));
+ sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "disk_io_time", sizeof (vl.type));
plugin_dispatch_values (&vl);
-}
+} /* void submit_io_time */
+#endif /* KERNEL_FREEBSD || KERNEL_LINUX */
-static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time)
+#if KERNEL_LINUX
+static void submit_in_progress (char const *disk_name, gauge_t in_progress)
{
- value_t values[2];
+ value_t v;
value_list_t vl = VALUE_LIST_INIT;
- if (ignorelist_match (ignorelist, plugin_instance) != 0)
- return;
-
- values[0].derive = io_time;
- values[1].derive = weighted_time;
+ v.gauge = in_progress;
- vl.values = values;
- vl.values_len = 2;
+ vl.values = &v;
+ vl.values_len = 1;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
- sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- sstrncpy (vl.type, "disk_io_time", sizeof (vl.type));
+ sstrncpy (vl.plugin_instance, disk_name, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "pending_operations", sizeof (vl.type));
plugin_dispatch_values (&vl);
}
DEBUG ("CFStringCreateWithCString (%s) failed.", key);
return (-1LL);
}
-
+
/* get => we don't need to release (== free) the object */
val_obj = (CFNumberRef) CFDictionaryGetValue (dict, key_obj);
else
ssnprintf (disk_name, sizeof (disk_name), "%i-%i", disk_major, disk_minor);
+ DEBUG ("disk plugin: disk_name = \"%s\"", disk_name);
+
+ /* check the name against ignore list */
+ if (ignorelist_match (ignorelist, disk_name) != 0) {
+ CFRelease (props_dict);
+ IOObjectRelease (disk);
+ continue;
+ }
+
/* extract the stats */
read_ops = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsReadsKey);
read_byt = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsBytesReadKey);
IOObjectRelease (disk);
/* and submit */
- DEBUG ("disk plugin: disk_name = \"%s\"", disk_name);
if ((read_byt != -1LL) || (write_byt != -1LL))
disk_submit (disk_name, "disk_octets", read_byt, write_byt);
if ((read_ops != -1LL) || (write_ops != -1LL))
IOObjectRelease (disk_list);
/* #endif HAVE_IOKIT_IOKITLIB_H */
+#elif KERNEL_FREEBSD
+ int retry, dirty;
+
+ void *snap = NULL;
+ struct devstat *snap_iter;
+
+ struct gident *geom_id;
+
+ const char *disk_name;
+ long double read_time, write_time, busy_time, total_duration;
+
+ for (retry = 0, dirty = 1; retry < 5 && dirty == 1; retry++) {
+ if (snap != NULL)
+ geom_stats_snapshot_free(snap);
+
+ /* Get a fresh copy of stats snapshot */
+ snap = geom_stats_snapshot_get();
+ if (snap == NULL) {
+ ERROR("disk plugin: geom_stats_snapshot_get() failed.");
+ return (-1);
+ }
+
+ /* Check if we have dirty read from this snapshot */
+ dirty = 0;
+ geom_stats_snapshot_reset(snap);
+ while ((snap_iter = geom_stats_snapshot_next(snap)) != NULL) {
+ if (snap_iter->id == NULL)
+ continue;
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+
+ /* New device? refresh GEOM tree */
+ if (geom_id == NULL) {
+ geom_deletetree(&geom_tree);
+ if (geom_gettree(&geom_tree) != 0) {
+ ERROR("disk plugin: geom_gettree() failed");
+ geom_stats_snapshot_free(snap);
+ return (-1);
+ }
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+ }
+ /*
+ * This should be rare: the device come right before we take the
+ * snapshot and went away right after it. We will handle this
+ * case later, so don't mark dirty but silently ignore it.
+ */
+ if (geom_id == NULL)
+ continue;
+
+ /* Only collect PROVIDER data */
+ if (geom_id->lg_what != ISPROVIDER)
+ continue;
+
+ /* Only collect data when rank is 1 (physical devices) */
+ if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1)
+ continue;
+
+ /* Check if this is a dirty read quit for another try */
+ if (snap_iter->sequence0 != snap_iter->sequence1) {
+ dirty = 1;
+ break;
+ }
+ }
+ }
+
+ /* Reset iterator */
+ geom_stats_snapshot_reset(snap);
+ for (;;) {
+ snap_iter = geom_stats_snapshot_next(snap);
+ if (snap_iter == NULL)
+ break;
+
+ if (snap_iter->id == NULL)
+ continue;
+ geom_id = geom_lookupid(&geom_tree, snap_iter->id);
+ if (geom_id == NULL)
+ continue;
+ if (geom_id->lg_what != ISPROVIDER)
+ continue;
+ if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1)
+ continue;
+ /* Skip dirty reads, if present */
+ if (dirty && (snap_iter->sequence0 != snap_iter->sequence1))
+ continue;
+
+ disk_name = ((struct gprovider *)geom_id->lg_ptr)->lg_name;
+
+ if (ignorelist_match (ignorelist, disk_name) != 0)
+ continue;
+
+ if ((snap_iter->bytes[DEVSTAT_READ] != 0) || (snap_iter->bytes[DEVSTAT_WRITE] != 0)) {
+ disk_submit(disk_name, "disk_octets",
+ (derive_t)snap_iter->bytes[DEVSTAT_READ],
+ (derive_t)snap_iter->bytes[DEVSTAT_WRITE]);
+ }
+
+ if ((snap_iter->operations[DEVSTAT_READ] != 0) || (snap_iter->operations[DEVSTAT_WRITE] != 0)) {
+ disk_submit(disk_name, "disk_ops",
+ (derive_t)snap_iter->operations[DEVSTAT_READ],
+ (derive_t)snap_iter->operations[DEVSTAT_WRITE]);
+ }
+
+ read_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_READ], NULL);
+ write_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_WRITE], NULL);
+ if ((read_time != 0) || (write_time != 0)) {
+ disk_submit (disk_name, "disk_time",
+ (derive_t)(read_time*1000), (derive_t)(write_time*1000));
+ }
+ if (devstat_compute_statistics(snap_iter, NULL, 1.0,
+ DSM_TOTAL_BUSY_TIME, &busy_time,
+ DSM_TOTAL_DURATION, &total_duration,
+ DSM_NONE) != 0) {
+ WARNING("%s", devstat_errbuf);
+ }
+ else
+ {
+ submit_io_time(disk_name, busy_time, total_duration);
+ }
+ }
+ geom_stats_snapshot_free(snap);
+
#elif KERNEL_LINUX
FILE *fh;
char buffer[1024];
-
+
char *fields[32];
int numfields;
int fieldshift = 0;
fieldshift = 1;
}
-#if HAVE_LIBUDEV
- handle_udev = udev_new();
-#endif
-
while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
char *disk_name;
char *output_name;
- char *alt_name;
numfields = strsplit (buffer, fields, 32);
ds->read_time = read_time;
ds->write_ops = write_ops;
ds->write_time = write_time;
+
+ if (read_merged || write_merged)
+ ds->has_merged = 1;
+
+ if (in_progress)
+ ds->has_in_progress = 1;
+
+ if (io_time)
+ ds->has_io_time = 1;
+
} /* if (is_disk) */
/* Don't write to the RRDs if we've just started.. */
output_name = disk_name;
#if HAVE_LIBUDEV
- alt_name = disk_udev_attr_name (handle_udev, disk_name,
- conf_udev_name_attr);
-#else
- alt_name = NULL;
+ char *alt_name = NULL;
+ if (conf_udev_name_attr != NULL)
+ {
+ alt_name = disk_udev_attr_name (handle_udev, disk_name, conf_udev_name_attr);
+ if (alt_name != NULL)
+ output_name = alt_name;
+ }
#endif
- if (alt_name != NULL)
- output_name = alt_name;
+
+ if (ignorelist_match (ignorelist, output_name) != 0)
+ {
+#if HAVE_LIBUDEV
+ /* release udev-based alternate name, if allocated */
+ sfree (alt_name);
+#endif
+ continue;
+ }
if ((ds->read_bytes != 0) || (ds->write_bytes != 0))
disk_submit (output_name, "disk_octets",
if (is_disk)
{
- disk_submit (output_name, "disk_merged",
+ if (ds->has_merged)
+ disk_submit (output_name, "disk_merged",
read_merged, write_merged);
- submit_in_progress (output_name, in_progress);
- submit_io_time (output_name, io_time, weighted_time);
+ if (ds->has_in_progress)
+ submit_in_progress (output_name, in_progress);
+ if (ds->has_io_time)
+ submit_io_time (output_name, io_time, weighted_time);
} /* if (is_disk) */
+#if HAVE_LIBUDEV
/* release udev-based alternate name, if allocated */
- free(alt_name);
+ sfree (alt_name);
+#endif
} /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
-#if HAVE_LIBUDEV
- udev_unref(handle_udev);
-#endif
fclose (fh);
/* #endif defined(KERNEL_LINUX) */
# error "kstat_io_t does not have the required members"
# endif
static kstat_io_t kio;
- int i;
if (kc == NULL)
return (-1);
- for (i = 0; i < numdisk; i++)
+ for (int i = 0; i < numdisk; i++)
{
if (kstat_read (kc, ksp[i], &kio) == -1)
continue;
if (strncmp (ksp[i]->ks_class, "disk", 4) == 0)
{
+ if (ignorelist_match (ignorelist, ksp[i]->ks_name) != 0)
+ continue;
+
disk_submit (ksp[i]->ks_name, "disk_octets",
kio.KIO_ROCTETS, kio.KIO_WOCTETS);
disk_submit (ksp[i]->ks_name, "disk_ops",
}
else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0)
{
+ if (ignorelist_match (ignorelist, ksp[i]->ks_name) != 0)
+ continue;
+
disk_submit (ksp[i]->ks_name, "disk_octets",
kio.KIO_ROCTETS, kio.KIO_WOCTETS);
disk_submit (ksp[i]->ks_name, "disk_ops",
# else
int disks;
#endif
- int counter;
char name[DATA_MAX_NAME_LEN];
-
+
if ((ds = sg_get_disk_io_stats(&disks)) == NULL)
return (0);
-
- for (counter=0; counter < disks; counter++) {
+
+ for (int counter = 0; counter < disks; counter++) {
strncpy(name, ds->disk_name, sizeof(name));
name[sizeof(name)-1] = '\0'; /* strncpy doesn't terminate longer strings */
+
+ if (ignorelist_match (ignorelist, name) != 0) {
+ ds++;
+ continue;
+ }
+
disk_submit (name, "disk_octets", ds->read_bytes, ds->write_bytes);
ds++;
}
derive_t write_ops;
perfstat_id_t firstpath;
int rnumdisk;
- int i;
- if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0)
+ if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0)
{
char errbuf[1024];
WARNING ("disk plugin: perfstat_disk: %s",
}
if (numdisk != pnumdisk || stat_disk==NULL) {
- if (stat_disk!=NULL)
+ if (stat_disk!=NULL)
free(stat_disk);
stat_disk = (perfstat_disk_t *)calloc(numdisk, sizeof(perfstat_disk_t));
- }
+ }
pnumdisk = numdisk;
firstpath.name[0]='\0';
- if ((rnumdisk = perfstat_disk(&firstpath, stat_disk, sizeof(perfstat_disk_t), numdisk)) < 0)
+ if ((rnumdisk = perfstat_disk(&firstpath, stat_disk, sizeof(perfstat_disk_t), numdisk)) < 0)
{
char errbuf[1024];
WARNING ("disk plugin: perfstat_disk : %s",
return (-1);
}
- for (i = 0; i < rnumdisk; i++)
+ for (int i = 0; i < rnumdisk; i++)
{
+ if (ignorelist_match (ignorelist, stat_disk[i].name) != 0)
+ continue;
+
read_sectors = stat_disk[i].rblks*stat_disk[i].bsize;
write_sectors = stat_disk[i].wblks*stat_disk[i].bsize;
disk_submit (stat_disk[i].name, "disk_octets", read_sectors, write_sectors);
plugin_register_config ("disk", disk_config,
config_keys, config_keys_num);
plugin_register_init ("disk", disk_init);
+ plugin_register_shutdown ("disk", disk_shutdown);
plugin_register_read ("disk", disk_read);
} /* void module_register */
diff --git a/src/dns.c b/src/dns.c
index 3421c475d7e6fc49c2419332dbcd8e5d3dd09f06..0494b4baeb20494f3a00fdb629eb2d738b637077 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
#define _BSD_SOURCE
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_dns.h"
-#include <pthread.h>
#include <poll.h>
#include <pcap.h>
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
/*
* Private data types
*/
{
counter_list_t *entry;
- entry = (counter_list_t *) malloc (sizeof (counter_list_t));
+ entry = calloc (1, sizeof (*entry));
if (entry == NULL)
return (NULL);
- memset (entry, 0, sizeof (counter_list_t));
entry->key = key;
entry->value = value;
{
pcap_t *pcap_obj;
char pcap_error[PCAP_ERRBUF_SIZE];
- struct bpf_program fp;
+ struct bpf_program fp = { 0 };
int status;
return (PCAP_ERROR);
}
- memset (&fp, 0, sizeof (fp));
status = pcap_compile (pcap_obj, &fp, "udp port 53", 1, 0);
if (status < 0)
{
listen_thread_init = 1;
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_RAW)
+ if (check_capability (CAP_NET_RAW) != 0)
+ {
+ if (getuid () == 0)
+ WARNING ("dns plugin: Running collectd as root, but the CAP_NET_RAW "
+ "capability is missing. The plugin's read function will probably "
+ "fail. Is your init system dropping capabilities?");
+ else
+ WARNING ("dns plugin: collectd doesn't have the CAP_NET_RAW capability. "
+ "If you don't want to run collectd as root, try running \"setcap "
+ "cap_net_raw=ep\" on the collectd binary.");
+ }
+#endif
+
return (0);
} /* int dns_init */
unsigned int keys[T_MAX];
unsigned int values[T_MAX];
int len;
- int i;
counter_list_t *ptr;
}
pthread_mutex_unlock (&qtype_mutex);
- for (i = 0; i < len; i++)
+ for (int i = 0; i < len; i++)
{
DEBUG ("dns plugin: qtype = %u; counter = %u;", keys[i], values[i]);
submit_derive ("dns_qtype", qtype_str (keys[i]), values[i]);
}
pthread_mutex_unlock (&opcode_mutex);
- for (i = 0; i < len; i++)
+ for (int i = 0; i < len; i++)
{
DEBUG ("dns plugin: opcode = %u; counter = %u;", keys[i], values[i]);
submit_derive ("dns_opcode", opcode_str (keys[i]), values[i]);
}
pthread_mutex_unlock (&rcode_mutex);
- for (i = 0; i < len; i++)
+ for (int i = 0; i < len; i++)
{
DEBUG ("dns plugin: rcode = %u; counter = %u;", keys[i], values[i]);
submit_derive ("dns_rcode", rcode_str (keys[i]), values[i]);
diff --git a/src/drbd.c b/src/drbd.c
index d46bb020ed5cc89d821c1ea5caa71d665f169ec8..70f03cab280ce8426cbaaa99ea8c2f20d244fa4b 100644 (file)
--- a/src/drbd.c
+++ b/src/drbd.c
See: http://www.drbd.org/users-guide/ch-admin.html#s-performance-indicators
version: 8.3.11 (api:88/proto:86-96)
- srcversion: 71955441799F513ACA6DA60
+ srcversion: 71955441799F513ACA6DA60
0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate B r-----
ns:64363752 nr:0 dw:357799284 dr:846902273 al:34987022 bm:18062 lo:0 \
pe:0 ua:0 ap:0 ep:1 wo:f oos:0
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
char plugin_instance[DATA_MAX_NAME_LEN];
value_t values[fields_num];
value_list_t vl = VALUE_LIST_INIT;
- size_t i;
if (resource < 0)
{
ssnprintf (plugin_instance, sizeof (plugin_instance), "r%ld",
resource);
- for (i = 0; i < drbd_names_num; i++)
+ for (size_t i = 0; i < drbd_names_num; i++)
{
char *data;
/* skip non numeric wo */
sizeof (vl.plugin_instance));
sstrncpy (vl.type, "drbd_resource", sizeof (vl.type));
- for (i = 0; i < fields_num; i++)
+ for (size_t i = 0; i < fields_num; i++)
{
if (drbd_names[i] == NULL)
continue;
diff --git a/src/email.c b/src/email.c
index 6a0c0a45718e7b167a5e179f028b40a6eb1cce06..2662da9e3590f83832c321355e353d016afa59d1 100644 (file)
--- a/src/email.c
+++ b/src/email.c
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
-
#include <stddef.h>
-#if HAVE_LIBPTHREAD
-# include <pthread.h>
-#endif
-
-#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
static void type_list_incr (type_list_t *list, char *name, int incr)
{
if (NULL == list->head) {
- list->head = (type_t *)smalloc (sizeof (type_t));
+ list->head = smalloc (sizeof (*list->head));
list->head->name = sstrdup (name);
list->head->value = incr;
}
if (NULL == ptr) {
- list->tail->next = (type_t *)smalloc (sizeof (type_t));
+ list->tail->next = smalloc (sizeof (*list->tail->next));
list->tail = list->tail->next;
list->tail->name = sstrdup (name);
{
struct sockaddr_un addr;
- char *path = (NULL == sock_file) ? SOCK_PATH : sock_file;
- char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
+ const char *path = (NULL == sock_file) ? SOCK_PATH : sock_file;
+ const char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
/* create UNIX socket */
errno = 0;
}
{ /* initialize collector threads */
- int i = 0;
- int err = 0;
-
pthread_attr_t ptattr;
conns.head = NULL;
available_collectors = max_conns;
collectors =
- (collector_t **)smalloc (max_conns * sizeof (collector_t *));
+ smalloc (max_conns * sizeof (*collectors));
- for (i = 0; i < max_conns; ++i) {
- collectors[i] = (collector_t *)smalloc (sizeof (collector_t));
+ for (int i = 0; i < max_conns; ++i) {
+ collectors[i] = smalloc (sizeof (*collectors[i]));
collectors[i]->socket = NULL;
- if (0 != (err = plugin_thread_create (&collectors[i]->thread,
- &ptattr, collect, collectors[i]))) {
+ if (plugin_thread_create (&collectors[i]->thread,
+ &ptattr, collect, collectors[i]) != 0) {
char errbuf[1024];
- log_err ("pthread_create() failed: %s",
+ log_err ("plugin_thread_create() failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
collectors[i]->thread = (pthread_t) 0;
}
break;
}
- connection = malloc (sizeof (*connection));
+ connection = calloc (1, sizeof (*connection));
if (connection == NULL)
{
close (remote);
continue;
}
- memset (connection, 0, sizeof (*connection));
connection->socket = fdopen (remote, "r");
connection->next = NULL;
static int email_init (void)
{
- int err = 0;
-
- if (0 != (err = plugin_thread_create (&connector, NULL,
- open_connection, NULL))) {
+ if (plugin_thread_create (&connector, NULL,
+ open_connection, NULL) != 0) {
char errbuf[1024];
disabled = 1;
- log_err ("pthread_create() failed: %s",
+ log_err ("plugin_thread_create() failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
static int email_shutdown (void)
{
- int i = 0;
-
if (connector != ((pthread_t) 0)) {
pthread_kill (connector, SIGTERM);
connector = (pthread_t) 0;
available_collectors = 0;
if (collectors != NULL) {
- for (i = 0; i < max_conns; ++i) {
+ for (int i = 0; i < max_conns; ++i) {
if (collectors[i] == NULL)
continue;
@@ -688,15 +674,12 @@ static void email_submit (const char *type, const char *type_instance, gauge_t v
* after they have been copied to l2. */
static void copy_type_list (type_list_t *l1, type_list_t *l2)
{
- type_t *ptr1;
- type_t *ptr2;
-
type_t *last = NULL;
- for (ptr1 = l1->head, ptr2 = l2->head; NULL != ptr1;
+ for (type_t *ptr1 = l1->head, *ptr2 = l2->head; NULL != ptr1;
ptr1 = ptr1->next, last = ptr2, ptr2 = ptr2->next) {
if (NULL == ptr2) {
- ptr2 = (type_t *)smalloc (sizeof (type_t));
+ ptr2 = smalloc (sizeof (*ptr2));
ptr2->name = NULL;
ptr2->next = NULL;
static int email_read (void)
{
- type_t *ptr;
-
double score_old;
int score_count_old;
pthread_mutex_unlock (&count_mutex);
- for (ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
+ for (type_t *ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
email_submit ("email_count", ptr->name, ptr->value);
}
pthread_mutex_unlock (&size_mutex);
- for (ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
+ for (type_t *ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
email_submit ("email_size", ptr->name, ptr->value);
}
pthread_mutex_unlock (&check_mutex);
- for (ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next)
+ for (type_t *ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next)
email_submit ("spam_check", ptr->name, ptr->value);
return (0);
diff --git a/src/entropy.c b/src/entropy.c
index 03de9efb48175dccecf7bdd6ab3a53ddf730e33d..f4f4ac4a916c2952ba92ab94af2a890660c72de6 100644 (file)
--- a/src/entropy.c
+++ b/src/entropy.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
diff --git a/src/ethstat.c b/src/ethstat.c
index a30a5d155243bb193892455dc56afe8bbc5d5c36..d0e77281e69b5d9ff4ff0d1c406a3aaa12b81e8c 100644 (file)
--- a/src/ethstat.c
+++ b/src/ethstat.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_avltree.h"
#include "utils_complain.h"
return (ENOMEM);
}
- map = malloc (sizeof (*map));
+ map = calloc (1, sizeof (*map));
if (map == NULL)
{
sfree (key);
- ERROR ("ethstat plugin: malloc(3) failed.");
+ ERROR ("ethstat plugin: calloc failed.");
return (ENOMEM);
}
- memset (map, 0, sizeof (*map));
sstrncpy (map->type, ci->values[1].value.string, sizeof (map->type));
if (ci->values_num == 3)
if (value_map == NULL)
{
- value_map = c_avl_create ((void *) strcmp);
+ value_map = c_avl_create ((int (*) (const void *, const void *)) strcmp);
if (value_map == NULL)
{
sfree (map);
static int ethstat_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static int ethstat_read_interface (char *device)
{
int fd;
- struct ifreq req;
- struct ethtool_drvinfo drvinfo;
struct ethtool_gstrings *strings;
struct ethtool_stats *stats;
size_t n_stats;
size_t strings_size;
size_t stats_size;
- size_t i;
int status;
- memset (&req, 0, sizeof (req));
- sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
-
fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0);
if (fd < 0)
{
return 1;
}
- memset (&drvinfo, 0, sizeof (drvinfo));
- drvinfo.cmd = ETHTOOL_GDRVINFO;
- req.ifr_data = (void *) &drvinfo;
+ struct ethtool_drvinfo drvinfo = {
+ .cmd = ETHTOOL_GDRVINFO
+ };
+
+ struct ifreq req = {
+ .ifr_data = (void *) &drvinfo
+ };
+
+ sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
+
status = ioctl (fd, SIOCETHTOOL, &req);
if (status < 0)
{
close (fd);
sfree (strings);
sfree (stats);
- ERROR("ethstat plugin: malloc(3) failed.");
+ ERROR("ethstat plugin: malloc failed.");
return (-1);
}
return (-1);
}
- for (i = 0; i < n_stats; i++)
+ for (size_t i = 0; i < n_stats; i++)
{
char *stat_name;
static int ethstat_read(void)
{
- size_t i;
-
- for (i = 0; i < interfaces_num; i++)
+ for (size_t i = 0; i < interfaces_num; i++)
ethstat_read_interface (interfaces[i]);
return 0;
diff --git a/src/exec.c b/src/exec.c
index 699be61d69f3f69a040cf68821eb44fb25aa6d5f..dfd4b05f59a95fc5409ab8b6a86aaba00b49df59 100644 (file)
--- a/src/exec.c
+++ b/src/exec.c
#define _BSD_SOURCE /* For setgroups */
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <grp.h>
#include <signal.h>
-#include <pthread.h>
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
#define PL_NORMAL 0x01
#define PL_NOTIF_ACTION 0x02
return (-1);
}
- pl = (program_list_t *) malloc (sizeof (program_list_t));
+ pl = calloc (1, sizeof (*pl));
if (pl == NULL)
{
- ERROR ("exec plugin: malloc failed.");
+ ERROR ("exec plugin: calloc failed.");
return (-1);
}
- memset (pl, '\0', sizeof (program_list_t));
if (strcasecmp ("NotificationExec", ci->key) == 0)
pl->flags |= PL_NOTIF_ACTION;
return (-1);
}
- pl->argv = (char **) malloc (ci->values_num * sizeof (char *));
+ pl->argv = calloc (ci->values_num, sizeof (*pl->argv));
if (pl->argv == NULL)
{
- ERROR ("exec plugin: malloc failed.");
+ ERROR ("exec plugin: calloc failed.");
sfree (pl->exec);
sfree (pl->user);
sfree (pl);
return (-1);
}
- memset (pl->argv, '\0', ci->values_num * sizeof (char *));
{
char *tmp = strrchr (ci->values[1].value.string, '/');
pl->argv[0] = strdup (buffer);
if (pl->argv[0] == NULL)
{
- ERROR ("exec plugin: malloc failed.");
+ ERROR ("exec plugin: strdup failed.");
sfree (pl->argv);
sfree (pl->exec);
sfree (pl->user);
static int exec_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if ((strcasecmp ("Exec", child->key) == 0)
{
sigset_t ss;
- memset (&ss, 0, sizeof (ss));
sigemptyset (&ss);
sigprocmask (SIG_SETMASK, &ss, /* old mask = */ NULL);
} /* }}} void reset_signal_mask */
@@ -475,11 +473,10 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err)
else if (pid == 0)
{
int fd_num;
- int fd;
/* Close all file descriptors but the pipe end we need. */
fd_num = getdtablesize ();
- for (fd = 0; fd < fd_num; fd++)
+ for (int fd = 0; fd < fd_num; fd++)
{
if ((fd == fd_pipe_in[0])
|| (fd == fd_pipe_out[1])
{
program_list_t *pl = ((program_list_and_notification_t *) arg)->pl;
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)
+ for (notification_meta_t *meta = n->meta; meta != NULL; meta = meta->next)
{
if (meta->type == NM_TYPE_STRING)
fprintf (fh, "%s: %s\n", meta->name, meta->nm_value.nm_string);
static int exec_init (void) /* {{{ */
{
- struct sigaction sa;
+ struct sigaction sa = {
+ .sa_handler = sigchld_handler
+ };
- memset (&sa, '\0', sizeof (sa));
- sa.sa_handler = sigchld_handler;
sigaction (SIGCHLD, &sa, NULL);
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SETUID) && defined(CAP_SETGID)
+ if ((check_capability (CAP_SETUID) != 0) ||
+ (check_capability (CAP_SETGID) != 0))
+ {
+ if (getuid () == 0)
+ WARNING ("exec plugin: Running collectd as root, but the CAP_SETUID "
+ "or CAP_SETGID capabilities are missing. The plugin's read function "
+ "will probably fail. Is your init system dropping capabilities?");
+ else
+ WARNING ("exec plugin: collectd doesn't have the CAP_SETUID or "
+ "CAP_SETGID capabilities. If you don't want to run collectd as root, "
+ "try running \"setcap 'cap_setuid=ep cap_setgid=ep'\" on the "
+ "collectd binary.");
+ }
+#endif
+
return (0);
} /* int exec_init }}} */
static int exec_read (void) /* {{{ */
{
- program_list_t *pl;
-
- for (pl = pl_head; pl != NULL; pl = pl->next)
+ for (program_list_t *pl = pl_head; pl != NULL; pl = pl->next)
{
pthread_t t;
pthread_attr_t attr;
static int exec_notification (const notification_t *n, /* {{{ */
user_data_t __attribute__((unused)) *user_data)
{
- program_list_t *pl;
program_list_and_notification_t *pln;
- for (pl = pl_head; pl != NULL; pl = pl->next)
+ for (program_list_t *pl = pl_head; pl != NULL; pl = pl->next)
{
pthread_t t;
pthread_attr_t attr;
if (pl->pid != 0)
continue;
- pln = (program_list_and_notification_t *) malloc (sizeof
- (program_list_and_notification_t));
+ pln = malloc (sizeof (*pln));
if (pln == NULL)
{
ERROR ("exec plugin: malloc failed.");
diff --git a/src/fhcount.c b/src/fhcount.c
index 666dacc09db1b6e876cf5b11e769c37f97f05626..4b3abff7276502efca4c9697b788a2770561ce41 100644 (file)
--- a/src/fhcount.c
+++ b/src/fhcount.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
static const char *config_keys[] = {
diff --git a/src/filecount.c b/src/filecount.c
index 9ea8af7abe2792ebc7235094cb67f37e75a668e8..9de9e6c53a5fced05d2d8ead5c1297a29195476a 100644 (file)
--- a/src/filecount.c
+++ b/src/filecount.c
**/
#include "collectd.h"
+
#include "common.h"
-#include "plugin.h"
+#include "plugin.h"
#include <sys/types.h>
#include <sys/stat.h>
{
fc_directory_conf_t *dir;
int status;
- int i;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
}
/* Initialize `dir' */
- dir = (fc_directory_conf_t *) malloc (sizeof (*dir));
+ dir = calloc (1, sizeof (*dir));
if (dir == NULL)
{
- ERROR ("filecount plugin: malloc failed.");
+ ERROR ("filecount plugin: calloc failed.");
return (-1);
}
- memset (dir, 0, sizeof (*dir));
dir->path = strdup (ci->values[0].value.string);
if (dir->path == NULL)
dir->size = 0;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
{
fc_directory_conf_t **temp;
- temp = (fc_directory_conf_t **) realloc (directories,
+ temp = realloc (directories,
sizeof (*directories) * (directories_num + 1));
if (temp == NULL)
{
static int fc_config (oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("Directory", child->key) == 0)
if (dir->mtime != 0)
dir->now = time (NULL);
-
+
status = walk_directory (dir->path, fc_read_dir_callback, dir,
/* include hidden */ (dir->options & FC_HIDDEN) ? 1 : 0);
if (status != 0)
static int fc_read (void)
{
- size_t i;
-
- for (i = 0; i < directories_num; i++)
+ for (size_t i = 0; i < directories_num; i++)
fc_read_dir (directories[i]);
return (0);
diff --git a/src/fscache.c b/src/fscache.c
index 8fbd271394e90554fcf92f1c850f6b4733242537..33633d63247db02deb1c7a909d228557b90184c2 100644 (file)
--- a/src/fscache.c
+++ b/src/fscache.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <stdio.h> /* a header needed for FILE */
char *lineptr;
char *fields[32];
int fields_num;
- int i;
/* Find the colon and replace it with a null byte */
lineptr = strchr (linebuffer, ':');
section_len--;
section[section_len] = 0;
}
- if (section_len <= 0)
+ if (section_len == 0)
continue;
fields_num = strsplit (lineptr, fields, STATIC_ARRAY_SIZE (fields));
if (fields_num <= 0)
continue;
- for (i = 0; i < fields_num; i++)
+ for (int i = 0; i < fields_num; i++)
{
char *field_name;
char *field_value_str;
diff --git a/src/gmond.c b/src/gmond.c
index 2ac9f2501c390e09b3a0f9783fb3078ec0c2fae4..13ec638950151403bcdee841fb45523c565a34ec 100644 (file)
--- a/src/gmond.c
+++ b/src/gmond.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
-#include "configfile.h"
#include "utils_avltree.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
struct metric_map_s
{
- char *ganglia_name;
- char *type;
- char *type_instance;
- char *ds_name;
- int ds_type;
- int ds_index;
+ char *ganglia_name;
+ char *type;
+ char *type_instance;
+ char *ds_name;
+ int ds_type;
+ size_t ds_index;
};
typedef struct metric_map_s metric_map_t;
return (NULL);
/* Look up the DS type and ds_index. */
- if ((map[i].ds_type < 0) || (map[i].ds_index < 0)) /* {{{ */
+ if (map[i].ds_type < 0) /* {{{ */
{
const data_set_t *ds;
}
else
{
- int j;
+ size_t j;
for (j = 0; j < ds->ds_num; j++)
if (strcasecmp (ds->ds[j].name, map[i].ds_name) == 0)
size_t *ret_sockets_num,
const char *node, const char *service, int listen)
{
- struct addrinfo ai_hints;
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
int ai_return;
socket_entry_t *sockets = NULL;
if (*ret_sockets != NULL)
return (EINVAL);
- memset (&ai_hints, 0, sizeof (ai_hints));
- ai_hints.ai_flags = 0;
-#ifdef AI_PASSIVE
- ai_hints.ai_flags |= AI_PASSIVE;
-#endif
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_DGRAM;
- ai_hints.ai_protocol = IPPROTO_UDP;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG | AI_PASSIVE,
+ .ai_protocol = IPPROTO_UDP,
+ .ai_socktype = SOCK_DGRAM
+ };
ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
if (ai_return != 0)
return (-1);
}
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) /* {{{ */
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) /* {{{ */
{
socket_entry_t *tmp;
if (ai_ptr->ai_family == AF_INET)
{
struct sockaddr_in *addr;
- struct ip_mreq mreq;
int loop;
addr = (struct sockaddr_in *) ai_ptr->ai_addr;
}
loop = 1;
- setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+ status = setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_MULTICAST_LOOP,
(void *) &loop, sizeof (loop));
+ if (status != 0)
+ {
+ char errbuf[1024];
+ WARNING ("gmond plugin: setsockopt(2) failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
+
+ struct ip_mreq mreq = {
+ .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+ .imr_interface.s_addr = htonl (INADDR_ANY)
+ };
- memset (&mreq, 0, sizeof (mreq));
- mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
- mreq.imr_interface.s_addr = htonl (INADDR_ANY);
- setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ status = setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(void *) &mreq, sizeof (mreq));
+ if (status != 0)
+ {
+ char errbuf[1024];
+ WARNING ("gmond plugin: setsockopt(2) failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
} /* if (ai_ptr->ai_family == AF_INET) */
else if (ai_ptr->ai_family == AF_INET6)
{
struct sockaddr_in6 *addr;
- struct ipv6_mreq mreq;
int loop;
addr = (struct sockaddr_in6 *) ai_ptr->ai_addr;
}
loop = 1;
- setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+ status = setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
(void *) &loop, sizeof (loop));
+ if (status != 0)
+ {
+ char errbuf[1024];
+ WARNING ("gmond plugin: setsockopt(2) failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
+
+ struct ipv6_mreq mreq = {
+ .ipv6mr_interface = 0 /* any */
+ };
- memset (&mreq, 0, sizeof (mreq));
memcpy (&mreq.ipv6mr_multiaddr,
&addr->sin6_addr, sizeof (addr->sin6_addr));
- mreq.ipv6mr_interface = 0; /* any */
- setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
+ status = setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
(void *) &mreq, sizeof (mreq));
+ if (status != 0)
+ {
+ char errbuf[1024];
+ WARNING ("gmond plugin: setsockopt(2) failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
} /* if (ai_ptr->ai_family == AF_INET6) */
sockets_num++;
static int request_meta_data (const char *host, const char *name) /* {{{ */
{
- Ganglia_metadata_msg msg;
- char buffer[BUFF_SIZE];
+ Ganglia_metadata_msg msg = { 0 };
+ char buffer[BUFF_SIZE] = { 0 };
unsigned int buffer_size;
XDR xdr;
- size_t i;
-
- memset (&msg, 0, sizeof (msg));
msg.id = gmetadata_request;
msg.Ganglia_metadata_msg_u.grequest.metric_id.host = strdup (host);
return (-1);
}
- memset (buffer, 0, sizeof (buffer));
xdrmem_create (&xdr, buffer, sizeof (buffer), XDR_ENCODE);
if (!xdr_Ganglia_metadata_msg (&xdr, &msg))
host, name);
pthread_mutex_lock (&mc_send_sockets_lock);
- for (i = 0; i < mc_send_sockets_num; i++)
+ for (size_t i = 0; i < mc_send_sockets_num; i++)
{
ssize_t status = sendto (mc_send_sockets[i].fd, buffer, (size_t) buffer_size,
/* flags = */ 0,
return (se);
/* insert new entry */
- se = (staging_entry_t *) malloc (sizeof (*se));
+ se = calloc (1, sizeof (*se));
if (se == NULL)
return (NULL);
- memset (se, 0, sizeof (*se));
sstrncpy (se->key, key, sizeof (se->key));
se->flags = 0;
static int staging_entry_update (const char *host, const char *name, /* {{{ */
const char *type, const char *type_instance,
- int ds_index, int ds_type, value_t value)
+ size_t ds_index, int ds_type, value_t value)
{
const data_set_t *ds;
staging_entry_t *se;
if (ds->ds_num <= ds_index)
{
- ERROR ("gmond plugin: Invalid index %i: %s has only %i data source(s).",
+ ERROR ("gmond plugin: Invalid index %zu: %s has only %zu data source(s).",
ds_index, ds->type, ds->ds_num);
return (-1);
}
msg_meta = msg->Ganglia_metadata_msg_u.gfull;
- if (msg_meta.metric.tmax <= 0)
+ if (msg_meta.metric.tmax == 0)
return (-1);
map = metric_lookup (msg_meta.metric_id.name);
case gmetric_float:
case gmetric_double:
{
- Ganglia_value_msg msg;
+ Ganglia_value_msg msg = { 0 };
- memset (&msg, 0, sizeof (msg));
if (xdr_Ganglia_value_msg (&xdr, &msg))
mc_handle_value_msg (&msg);
break;
case gmetadata_full:
case gmetadata_request:
{
- Ganglia_metadata_msg msg;
- memset (&msg, 0, sizeof (msg));
+ Ganglia_metadata_msg msg = { 0 };
if (xdr_Ganglia_metadata_msg (&xdr, &msg))
mc_handle_metadata_msg (&msg);
break;
{
socket_entry_t *mc_receive_socket_entries;
int status;
- size_t i;
mc_receive_socket_entries = NULL;
status = create_sockets (&mc_receive_socket_entries, &mc_receive_sockets_num,
if (mc_receive_sockets == NULL)
{
ERROR ("gmond plugin: calloc failed.");
- for (i = 0; i < mc_receive_sockets_num; i++)
+ for (size_t i = 0; i < mc_receive_sockets_num; i++)
close (mc_receive_socket_entries[i].fd);
free (mc_receive_socket_entries);
mc_receive_socket_entries = NULL;
return ((void *) -1);
}
- for (i = 0; i < mc_receive_sockets_num; i++)
+ for (size_t i = 0; i < mc_receive_sockets_num; i++)
{
mc_receive_sockets[i].fd = mc_receive_socket_entries[i].fd;
mc_receive_sockets[i].events = POLLIN | POLLPRI;
break;
}
- for (i = 0; i < mc_receive_sockets_num; i++)
+ for (size_t i = 0; i < mc_receive_sockets_num; i++)
{
if (mc_receive_sockets[i].revents != 0)
mc_handle_socket (mc_receive_sockets + i);
return (0);
} /* }}} int mc_receive_thread_stop */
-/*
+/*
* Config:
*
* <Plugin gmond>
static int gmond_config_add_metric (oconfig_item_t *ci) /* {{{ */
{
metric_map_t *map;
- int i;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
return (-1);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("Type", child->key) == 0)
static int gmond_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("MCReceiveFrom", child->key) == 0)
(mc_receive_port != NULL) ? mc_receive_port : MC_RECEIVE_PORT_DEFAULT,
/* listen = */ 0);
- staging_tree = c_avl_create ((void *) strcmp);
+ staging_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
if (staging_tree == NULL)
{
ERROR ("gmond plugin: c_avl_create failed.");
static int gmond_shutdown (void) /* {{{ */
{
- size_t i;
-
mc_receive_thread_stop ();
pthread_mutex_lock (&mc_send_sockets_lock);
- for (i = 0; i < mc_send_sockets_num; i++)
+ for (size_t i = 0; i < mc_send_sockets_num; i++)
{
close (mc_send_sockets[i].fd);
mc_send_sockets[i].fd = -1;
diff --git a/src/gps.c b/src/gps.c
--- /dev/null
+++ b/src/gps.c
@@ -0,0 +1,367 @@
+/**
+ * collectd - src/gps.c
+ * Copyright (C) 2015 Nicolas JOURDEN
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Nicolas JOURDEN <nicolas.jourden at laposte.net>
+ * Florian octo Forster <octo at collectd.org>
+ * Marc Fournier <marc.fournier at camptocamp.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_time.h"
+
+#define CGPS_TRUE 1
+#define CGPS_FALSE 0
+#define CGPS_DEFAULT_HOST "localhost"
+#define CGPS_DEFAULT_PORT "2947" /* DEFAULT_GPSD_PORT */
+#define CGPS_DEFAULT_TIMEOUT MS_TO_CDTIME_T (15)
+#define CGPS_DEFAULT_PAUSE_CONNECT TIME_T_TO_CDTIME_T (5)
+#define CGPS_MAX_ERROR 100
+#define CGPS_CONFIG "?WATCH={\"enable\":true,\"json\":true,\"nmea\":false}\r\n"
+
+#include <gps.h>
+#include <pthread.h>
+
+typedef struct {
+ char *host;
+ char *port;
+ cdtime_t timeout;
+ cdtime_t pause_connect;
+} cgps_config_t;
+
+typedef struct {
+ gauge_t sats_used;
+ gauge_t sats_visible;
+ gauge_t hdop;
+ gauge_t vdop;
+} cgps_data_t;
+
+static cgps_config_t cgps_config_data;
+
+static cgps_data_t cgps_data = {NAN, NAN, NAN, NAN};
+
+static pthread_t cgps_thread_id;
+static pthread_mutex_t cgps_data_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t cgps_thread_lock = PTHREAD_MUTEX_INITIALIZER;
+static int cgps_thread_shutdown = CGPS_FALSE;
+static int cgps_thread_running = CGPS_FALSE;
+
+/**
+ * Non blocking pause for the thread.
+ */
+static int cgps_thread_pause(cdtime_t pTime)
+{
+ cdtime_t now;
+ now = cdtime ();
+ struct timespec pause_th;
+ CDTIME_T_TO_TIMESPEC (MS_TO_CDTIME_T(10), &pause_th);
+ while (CGPS_TRUE)
+ {
+ if ( (cdtime () - now) > pTime )
+ {
+ break;
+ }
+
+ pthread_mutex_lock (&cgps_thread_lock);
+ if (cgps_thread_shutdown == CGPS_TRUE)
+ {
+ return CGPS_FALSE;
+ }
+ pthread_mutex_unlock (&cgps_thread_lock);
+ nanosleep (&pause_th, NULL);
+ }
+
+ return CGPS_TRUE;
+}
+
+/**
+ * Thread reading from gpsd.
+ */
+static void * cgps_thread (void * pData)
+{
+ struct gps_data_t gpsd_conn;
+ unsigned int err_count;
+ cgps_thread_running = CGPS_TRUE;
+
+ while (CGPS_TRUE)
+ {
+ pthread_mutex_lock (&cgps_thread_lock);
+ if (cgps_thread_shutdown == CGPS_TRUE)
+ {
+ goto quit;
+ }
+ pthread_mutex_unlock (&cgps_thread_lock);
+
+ err_count = 0;
+
+#if GPSD_API_MAJOR_VERSION > 4
+ int status = gps_open (cgps_config_data.host, cgps_config_data.port, &gpsd_conn);
+#else
+ int status = gps_open_r (cgps_config_data.host, cgps_config_data.port, &gpsd_conn);
+#endif
+ if (status < 0)
+ {
+ WARNING ("gps plugin: connecting to %s:%s failed: %s",
+ cgps_config_data.host, cgps_config_data.port, gps_errstr (status));
+
+ // Here we make a pause until a new tentative to connect, we check also if
+ // the thread does not need to stop.
+ if (cgps_thread_pause(cgps_config_data.pause_connect) == CGPS_FALSE)
+ {
+ goto quit;
+ }
+
+ continue;
+ }
+
+ gps_stream (&gpsd_conn, WATCH_ENABLE | WATCH_JSON | WATCH_NEWSTYLE, NULL);
+ gps_send (&gpsd_conn, CGPS_CONFIG);
+
+ while (CGPS_TRUE)
+ {
+ pthread_mutex_lock (&cgps_thread_lock);
+ if (cgps_thread_shutdown == CGPS_TRUE)
+ {
+ goto stop;
+ }
+ pthread_mutex_unlock (&cgps_thread_lock);
+
+#if GPSD_API_MAJOR_VERSION > 4
+ long timeout_us = CDTIME_T_TO_US (cgps_config_data.timeout);
+ if (!gps_waiting (&gpsd_conn, (int) timeout_us ))
+#else
+ if (!gps_waiting (&gpsd_conn))
+#endif
+ {
+ continue;
+ }
+
+ if (gps_read (&gpsd_conn) == -1)
+ {
+ WARNING ("gps plugin: incorrect data! (err_count: %d)", err_count);
+ err_count++;
+
+ if (err_count > CGPS_MAX_ERROR)
+ {
+ // Server is not responding ...
+ if (gps_send (&gpsd_conn, CGPS_CONFIG) == -1)
+ {
+ WARNING ("gps plugin: gpsd seems to be down, reconnecting");
+ gps_close (&gpsd_conn);
+ break;
+ }
+ // Server is responding ...
+ else
+ {
+ err_count = 0;
+ }
+ }
+
+ continue;
+ }
+
+ pthread_mutex_lock (&cgps_data_lock);
+
+ // Number of sats in view:
+ cgps_data.sats_used = (gauge_t) gpsd_conn.satellites_used;
+ cgps_data.sats_visible = (gauge_t) gpsd_conn.satellites_visible;
+
+ // dilution of precision:
+ cgps_data.vdop = NAN;
+ cgps_data.hdop = NAN;
+ if (cgps_data.sats_used > 0)
+ {
+ cgps_data.hdop = gpsd_conn.dop.hdop;
+ cgps_data.vdop = gpsd_conn.dop.vdop;
+ }
+
+ DEBUG ("gps plugin: %.0f sats used (of %.0f visible), hdop = %.3f, vdop = %.3f",
+ cgps_data.sats_used, cgps_data.sats_visible, cgps_data.hdop, cgps_data.vdop);
+
+ pthread_mutex_unlock (&cgps_data_lock);
+ }
+ }
+
+stop:
+ DEBUG ("gps plugin: thread closing gpsd connection ... ");
+ gps_stream (&gpsd_conn, WATCH_DISABLE, NULL);
+ gps_close (&gpsd_conn);
+quit:
+ DEBUG ("gps plugin: thread shutting down ... ");
+ cgps_thread_running = CGPS_FALSE;
+ pthread_mutex_unlock (&cgps_thread_lock);
+ pthread_exit (NULL);
+}
+
+
+/**
+ * Submit a piece of the data.
+ */
+static void cgps_submit (const char *type, gauge_t value, const char *type_instance)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "gps", sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+}
+
+/**
+ * Read the data and submit by piece.
+ */
+static int cgps_read (void)
+{
+ cgps_data_t data_copy;
+
+ pthread_mutex_lock (&cgps_data_lock);
+ data_copy = cgps_data;
+ pthread_mutex_unlock (&cgps_data_lock);
+
+ cgps_submit ("dilution_of_precision", data_copy.hdop, "horizontal");
+ cgps_submit ("dilution_of_precision", data_copy.vdop, "vertical");
+ cgps_submit ("satellites", data_copy.sats_used, "used");
+ cgps_submit ("satellites", data_copy.sats_visible, "visible");
+
+ return (0);
+}
+
+/**
+ * Read configuration.
+ */
+static int cgps_config (oconfig_item_t *ci)
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("Host", child->key) == 0)
+ cf_util_get_string (child, &cgps_config_data.host);
+ else if (strcasecmp ("Port", child->key) == 0)
+ cf_util_get_service (child, &cgps_config_data.port);
+ else if (strcasecmp ("Timeout", child->key) == 0)
+ cf_util_get_cdtime (child, &cgps_config_data.timeout);
+ else if (strcasecmp ("PauseConnect", child->key) == 0)
+ cf_util_get_cdtime (child, &cgps_config_data.pause_connect);
+ else
+ WARNING ("gps plugin: Ignoring unknown config option \"%s\".", child->key);
+ }
+
+ // Controlling the value for timeout:
+ // If set too high it blocks the reading (> 5 s), too low it gets not reading (< 500 us).
+ // To avoid any issues we replace "out of range" value by the default value.
+ if (
+ cgps_config_data.timeout > TIME_T_TO_CDTIME_T(5)
+ ||
+ cgps_config_data.timeout < US_TO_CDTIME_T(500)
+ )
+ {
+ WARNING ("gps plugin: timeout set to %.6f sec. setting to default (%.6f).",
+ CDTIME_T_TO_DOUBLE(cgps_config_data.timeout),
+ CDTIME_T_TO_DOUBLE(CGPS_DEFAULT_TIMEOUT)
+ );
+ cgps_config_data.timeout = CGPS_DEFAULT_TIMEOUT;
+ }
+
+ return (0);
+}
+
+/**
+ * Init.
+ */
+static int cgps_init (void)
+{
+ int status;
+
+ if (cgps_thread_running == CGPS_TRUE)
+ {
+ DEBUG ("gps plugin: error gps thread already running ... ");
+ return 0;
+ }
+
+ DEBUG ("gps plugin: config{host: \"%s\", port: \"%s\", timeout: %.6f sec., pause connect: %.3f sec.}",
+ cgps_config_data.host, cgps_config_data.port,
+ CDTIME_T_TO_DOUBLE (cgps_config_data.timeout),
+ CDTIME_T_TO_DOUBLE (cgps_config_data.pause_connect));
+
+ status = plugin_thread_create (&cgps_thread_id, NULL, cgps_thread, NULL);
+ if (status != 0)
+ {
+ ERROR ("gps plugin: pthread_create() failed.");
+ return (-1);
+ }
+
+ return (0);
+}
+
+/**
+ * Shutdown.
+ */
+static int cgps_shutdown (void)
+{
+ void * res;
+
+ pthread_mutex_lock (&cgps_thread_lock);
+ cgps_thread_shutdown = CGPS_TRUE;
+ pthread_mutex_unlock (&cgps_thread_lock);
+
+ pthread_join(cgps_thread_id, &res);
+ free(res);
+
+ // Clean mutex:
+ pthread_mutex_unlock(&cgps_thread_lock);
+ pthread_mutex_destroy(&cgps_thread_lock);
+ pthread_mutex_unlock(&cgps_data_lock);
+ pthread_mutex_destroy(&cgps_data_lock);
+
+ sfree (cgps_config_data.port);
+ sfree (cgps_config_data.host);
+
+ return (0);
+}
+
+/**
+ * Register the module.
+ */
+void module_register (void)
+{
+ cgps_config_data.host = sstrdup (CGPS_DEFAULT_HOST);
+ cgps_config_data.port = sstrdup (CGPS_DEFAULT_PORT);
+ cgps_config_data.timeout = CGPS_DEFAULT_TIMEOUT;
+ cgps_config_data.pause_connect = CGPS_DEFAULT_PAUSE_CONNECT;
+
+ plugin_register_complex_config ("gps", cgps_config);
+ plugin_register_init ("gps", cgps_init);
+ plugin_register_read ("gps", cgps_read);
+ plugin_register_shutdown ("gps", cgps_shutdown);
+}
diff --git a/src/grpc.cc b/src/grpc.cc
--- /dev/null
+++ b/src/grpc.cc
@@ -0,0 +1,678 @@
+/**
+ * collectd - src/grpc.cc
+ * Copyright (C) 2015-2016 Sebastian Harl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Sebastian Harl <sh at tokkee.org>
+ **/
+
+#include <grpc++/grpc++.h>
+#include <google/protobuf/util/time_util.h>
+
+#include <fstream>
+#include <iostream>
+#include <queue>
+#include <vector>
+
+#include "collectd.grpc.pb.h"
+
+extern "C" {
+#include <fnmatch.h>
+#include <stdbool.h>
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "daemon/utils_cache.h"
+}
+
+using collectd::Collectd;
+
+using collectd::DispatchValuesRequest;
+using collectd::DispatchValuesResponse;
+using collectd::QueryValuesRequest;
+using collectd::QueryValuesResponse;
+
+using google::protobuf::util::TimeUtil;
+
+/*
+ * private types
+ */
+
+struct Listener {
+ grpc::string addr;
+ grpc::string port;
+
+ grpc::SslServerCredentialsOptions *ssl;
+};
+static std::vector<Listener> listeners;
+static grpc::string default_addr("0.0.0.0:50051");
+
+/*
+ * helper functions
+ */
+
+static bool ident_matches(const value_list_t *vl, const value_list_t *matcher)
+{
+ if (fnmatch(matcher->host, vl->host, 0))
+ return false;
+
+ if (fnmatch(matcher->plugin, vl->plugin, 0))
+ return false;
+ if (fnmatch(matcher->plugin_instance, vl->plugin_instance, 0))
+ return false;
+
+ if (fnmatch(matcher->type, vl->type, 0))
+ return false;
+ if (fnmatch(matcher->type_instance, vl->type_instance, 0))
+ return false;
+
+ return true;
+} /* ident_matches */
+
+static grpc::string read_file(const char *filename)
+{
+ std::ifstream f;
+ grpc::string s, content;
+
+ f.open(filename);
+ if (!f.is_open()) {
+ ERROR("grpc: Failed to open '%s'", filename);
+ return "";
+ }
+
+ while (std::getline(f, s)) {
+ content += s;
+ content.push_back('\n');
+ }
+ f.close();
+ return content;
+} /* read_file */
+
+/*
+ * proto conversion
+ */
+
+static void marshal_ident(const value_list_t *vl, collectd::types::Identifier *msg)
+{
+ msg->set_host(vl->host);
+ msg->set_plugin(vl->plugin);
+ if (vl->plugin_instance[0] != '\0')
+ msg->set_plugin_instance(vl->plugin_instance);
+ msg->set_type(vl->type);
+ if (vl->type_instance[0] != '\0')
+ msg->set_type_instance(vl->type_instance);
+} /* marshal_ident */
+
+static grpc::Status unmarshal_ident(const collectd::types::Identifier &msg, value_list_t *vl,
+ bool require_fields)
+{
+ std::string s;
+
+ s = msg.host();
+ if (!s.length() && require_fields)
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("missing host name"));
+ sstrncpy(vl->host, s.c_str(), sizeof(vl->host));
+
+ s = msg.plugin();
+ if (!s.length() && require_fields)
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("missing plugin name"));
+ sstrncpy(vl->plugin, s.c_str(), sizeof(vl->plugin));
+
+ s = msg.type();
+ if (!s.length() && require_fields)
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("missing type name"));
+ sstrncpy(vl->type, s.c_str(), sizeof(vl->type));
+
+ s = msg.plugin_instance();
+ sstrncpy(vl->plugin_instance, s.c_str(), sizeof(vl->plugin_instance));
+
+ s = msg.type_instance();
+ sstrncpy(vl->type_instance, s.c_str(), sizeof(vl->type_instance));
+
+ return grpc::Status::OK;
+} /* unmarshal_ident() */
+
+static grpc::Status marshal_value_list(const value_list_t *vl, collectd::types::ValueList *msg)
+{
+ auto id = msg->mutable_identifier();
+ marshal_ident(vl, id);
+
+ auto ds = plugin_get_ds(vl->type);
+ if ((ds == NULL) || (ds->ds_num != vl->values_len)) {
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve data-set for values"));
+ }
+
+ auto t = TimeUtil::NanosecondsToTimestamp(CDTIME_T_TO_NS(vl->time));
+ auto d = TimeUtil::NanosecondsToDuration(CDTIME_T_TO_NS(vl->interval));
+ msg->set_allocated_time(new google::protobuf::Timestamp(t));
+ msg->set_allocated_interval(new google::protobuf::Duration(d));
+
+ for (size_t i = 0; i < vl->values_len; ++i) {
+ auto v = msg->add_values();
+ switch (ds->ds[i].type) {
+ case DS_TYPE_COUNTER:
+ v->set_counter(vl->values[i].counter);
+ break;
+ case DS_TYPE_GAUGE:
+ v->set_gauge(vl->values[i].gauge);
+ break;
+ case DS_TYPE_DERIVE:
+ v->set_derive(vl->values[i].derive);
+ break;
+ case DS_TYPE_ABSOLUTE:
+ v->set_absolute(vl->values[i].absolute);
+ break;
+ default:
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("unknown value type"));
+ }
+
+ auto name = msg->add_ds_names();
+ name->assign(ds->ds[i].name);
+ }
+
+ return grpc::Status::OK;
+} /* marshal_value_list */
+
+static grpc::Status unmarshal_value_list(const collectd::types::ValueList &msg, value_list_t *vl)
+{
+ vl->time = NS_TO_CDTIME_T(TimeUtil::TimestampToNanoseconds(msg.time()));
+ vl->interval = NS_TO_CDTIME_T(TimeUtil::DurationToNanoseconds(msg.interval()));
+
+ auto status = unmarshal_ident(msg.identifier(), vl, true);
+ if (!status.ok())
+ return status;
+
+ value_t *values = NULL;
+ size_t values_len = 0;
+
+ status = grpc::Status::OK;
+ for (auto v : msg.values()) {
+ value_t *val = (value_t *)realloc(values, (values_len + 1) * sizeof(*values));
+ if (!val) {
+ status = grpc::Status(grpc::StatusCode::RESOURCE_EXHAUSTED,
+ grpc::string("failed to allocate values array"));
+ break;
+ }
+
+ values = val;
+ val = values + values_len;
+ values_len++;
+
+ switch (v.value_case()) {
+ case collectd::types::Value::ValueCase::kCounter:
+ val->counter = counter_t(v.counter());
+ break;
+ case collectd::types::Value::ValueCase::kGauge:
+ val->gauge = gauge_t(v.gauge());
+ break;
+ case collectd::types::Value::ValueCase::kDerive:
+ val->derive = derive_t(v.derive());
+ break;
+ case collectd::types::Value::ValueCase::kAbsolute:
+ val->absolute = absolute_t(v.absolute());
+ break;
+ default:
+ status = grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("unknown value type"));
+ break;
+ }
+
+ if (!status.ok())
+ break;
+ }
+ if (status.ok()) {
+ vl->values = values;
+ vl->values_len = values_len;
+ }
+ else if (values) {
+ free(values);
+ }
+
+ return status;
+} /* unmarshal_value_list() */
+
+/*
+ * Collectd service
+ */
+class CollectdImpl : public collectd::Collectd::Service {
+public:
+ grpc::Status QueryValues(grpc::ServerContext *ctx, QueryValuesRequest const *req, grpc::ServerWriter<QueryValuesResponse> *writer) override {
+ value_list_t match;
+ auto status = unmarshal_ident(req->identifier(), &match, false);
+ if (!status.ok()) {
+ return status;
+ }
+
+ std::queue<value_list_t> value_lists;
+ status = this->queryValuesRead(&match, &value_lists);
+ if (status.ok()) {
+ status = this->queryValuesWrite(ctx, writer, &value_lists);
+ }
+
+ while (!value_lists.empty()) {
+ auto vl = value_lists.front();
+ value_lists.pop();
+ sfree(vl.values);
+ }
+
+ return status;
+ }
+
+ grpc::Status DispatchValues(grpc::ServerContext *ctx,
+ grpc::ServerReader<DispatchValuesRequest> *reader,
+ DispatchValuesResponse *res) override {
+ DispatchValuesRequest req;
+
+ while (reader->Read(&req)) {
+ value_list_t vl = VALUE_LIST_INIT;
+ auto status = unmarshal_value_list(req.value_list(), &vl);
+ if (!status.ok())
+ return status;
+
+ if (plugin_dispatch_values(&vl))
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to enqueue values for writing"));
+ }
+
+ res->Clear();
+ return grpc::Status::OK;
+ }
+
+private:
+ grpc::Status queryValuesRead(value_list_t const *match, std::queue<value_list_t> *value_lists) {
+ uc_iter_t *iter;
+ if ((iter = uc_get_iterator()) == NULL) {
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to query values: cannot create iterator"));
+ }
+
+ grpc::Status status = grpc::Status::OK;
+ char *name = NULL;
+ while (uc_iterator_next(iter, &name) == 0) {
+ value_list_t vl;
+ if (parse_identifier_vl(name, &vl) != 0) {
+ status = grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to parse identifier"));
+ break;
+ }
+
+ if (!ident_matches(&vl, match))
+ continue;
+
+ if (uc_iterator_get_time(iter, &vl.time) < 0) {
+ status = grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve value timestamp"));
+ break;
+ }
+ if (uc_iterator_get_interval(iter, &vl.interval) < 0) {
+ status = grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve value interval"));
+ break;
+ }
+ if (uc_iterator_get_values(iter, &vl.values, &vl.values_len) < 0) {
+ status = grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve values"));
+ break;
+ }
+
+ value_lists->push(vl);
+ } // while (uc_iterator_next(iter, &name) == 0)
+
+ uc_iterator_destroy(iter);
+ return status;
+ }
+
+ grpc::Status queryValuesWrite(grpc::ServerContext *ctx,
+ grpc::ServerWriter<QueryValuesResponse> *writer,
+ std::queue<value_list_t> *value_lists) {
+ while (!value_lists->empty()) {
+ auto vl = value_lists->front();
+ QueryValuesResponse res;
+ res.Clear();
+
+ auto status = marshal_value_list(&vl, res.mutable_value_list());
+ if (!status.ok()) {
+ return status;
+ }
+
+ if (!writer->Write(res)) {
+ return grpc::Status::CANCELLED;
+ }
+
+ value_lists->pop();
+ sfree(vl.values);
+ }
+
+ return grpc::Status::OK;
+ }
+};
+
+/*
+ * gRPC server implementation
+ */
+class CollectdServer final
+{
+public:
+ void Start()
+ {
+ auto auth = grpc::InsecureServerCredentials();
+
+ grpc::ServerBuilder builder;
+
+ if (listeners.empty()) {
+ builder.AddListeningPort(default_addr, auth);
+ INFO("grpc: Listening on %s", default_addr.c_str());
+ }
+ else {
+ for (auto l : listeners) {
+ grpc::string addr = l.addr + ":" + l.port;
+
+ auto use_ssl = grpc::string("");
+ auto a = auth;
+ if (l.ssl != nullptr) {
+ use_ssl = grpc::string(" (SSL enabled)");
+ a = grpc::SslServerCredentials(*l.ssl);
+ }
+
+ builder.AddListeningPort(addr, a);
+ INFO("grpc: Listening on %s%s", addr.c_str(), use_ssl.c_str());
+ }
+ }
+
+ builder.RegisterService(&collectd_service_);
+
+ server_ = builder.BuildAndStart();
+ } /* Start() */
+
+ void Shutdown()
+ {
+ server_->Shutdown();
+ } /* Shutdown() */
+
+private:
+ CollectdImpl collectd_service_;
+
+ std::unique_ptr<grpc::Server> server_;
+}; /* class CollectdServer */
+
+class CollectdClient final
+{
+public:
+ CollectdClient(std::shared_ptr<grpc::ChannelInterface> channel) : stub_(Collectd::NewStub(channel)) {
+ }
+
+ int DispatchValues(value_list_t const *vl) {
+ grpc::ClientContext ctx;
+
+ DispatchValuesRequest req;
+ auto status = marshal_value_list(vl, req.mutable_value_list());
+ if (!status.ok()) {
+ ERROR("grpc: Marshalling value_list_t failed.");
+ return -1;
+ }
+
+ DispatchValuesResponse res;
+ auto stream = stub_->DispatchValues(&ctx, &res);
+ if (!stream->Write(req)) {
+ NOTICE("grpc: Broken stream.");
+ /* intentionally not returning. */
+ }
+
+ stream->WritesDone();
+ status = stream->Finish();
+ if (!status.ok()) {
+ ERROR ("grpc: Error while closing stream.");
+ return -1;
+ }
+
+ return 0;
+ } /* int DispatchValues */
+
+private:
+ std::unique_ptr<Collectd::Stub> stub_;
+};
+
+static CollectdServer *server = nullptr;
+
+/*
+ * collectd plugin interface
+ */
+extern "C" {
+ static void c_grpc_destroy_write_callback (void *ptr) {
+ delete (CollectdClient *) ptr;
+ }
+
+ static int c_grpc_write(__attribute__((unused)) data_set_t const *ds,
+ value_list_t const *vl,
+ user_data_t *ud) {
+ CollectdClient *c = (CollectdClient *) ud->data;
+ return c->DispatchValues(vl);
+ }
+
+ static int c_grpc_config_listen(oconfig_item_t *ci)
+ {
+ if ((ci->values_num != 2)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING)
+ || (ci->values[1].type != OCONFIG_TYPE_STRING)) {
+ ERROR("grpc: The `%s` config option needs exactly "
+ "two string argument (address and port).", ci->key);
+ return -1;
+ }
+
+ auto listener = Listener();
+ listener.addr = grpc::string(ci->values[0].value.string);
+ listener.port = grpc::string(ci->values[1].value.string);
+ listener.ssl = nullptr;
+
+ auto ssl_opts = new(grpc::SslServerCredentialsOptions);
+ grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp = {};
+ bool use_ssl = false;
+
+ for (int i = 0; i < ci->children_num; i++) {
+ oconfig_item_t *child = ci->children + i;
+
+ if (!strcasecmp("EnableSSL", child->key)) {
+ if (cf_util_get_boolean(child, &use_ssl)) {
+ ERROR("grpc: Option `%s` expects a boolean value",
+ child->key);
+ return -1;
+ }
+ }
+ else if (!strcasecmp("SSLCACertificateFile", child->key)) {
+ char *certs = NULL;
+ if (cf_util_get_string(child, &certs)) {
+ ERROR("grpc: Option `%s` expects a string value",
+ child->key);
+ return -1;
+ }
+ ssl_opts->pem_root_certs = read_file(certs);
+ }
+ else if (!strcasecmp("SSLCertificateKeyFile", child->key)) {
+ char *key = NULL;
+ if (cf_util_get_string(child, &key)) {
+ ERROR("grpc: Option `%s` expects a string value",
+ child->key);
+ return -1;
+ }
+ pkcp.private_key = read_file(key);
+ }
+ else if (!strcasecmp("SSLCertificateFile", child->key)) {
+ char *cert = NULL;
+ if (cf_util_get_string(child, &cert)) {
+ ERROR("grpc: Option `%s` expects a string value",
+ child->key);
+ return -1;
+ }
+ pkcp.cert_chain = read_file(cert);
+ }
+ else {
+ WARNING("grpc: Option `%s` not allowed in <%s> block.",
+ child->key, ci->key);
+ }
+ }
+
+ ssl_opts->pem_key_cert_pairs.push_back(pkcp);
+ if (use_ssl)
+ listener.ssl = ssl_opts;
+ else
+ delete(ssl_opts);
+
+ listeners.push_back(listener);
+ return 0;
+ } /* c_grpc_config_listen() */
+
+ static int c_grpc_config_server(oconfig_item_t *ci)
+ {
+ if ((ci->values_num != 2)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING)
+ || (ci->values[1].type != OCONFIG_TYPE_STRING)) {
+ ERROR("grpc: The `%s` config option needs exactly "
+ "two string argument (address and port).", ci->key);
+ return -1;
+ }
+
+ grpc::SslCredentialsOptions ssl_opts;
+ bool use_ssl = false;
+
+ for (int i = 0; i < ci->children_num; i++) {
+ oconfig_item_t *child = ci->children + i;
+
+ if (!strcasecmp("EnableSSL", child->key)) {
+ if (cf_util_get_boolean(child, &use_ssl)) {
+ return -1;
+ }
+ }
+ else if (!strcasecmp("SSLCACertificateFile", child->key)) {
+ char *certs = NULL;
+ if (cf_util_get_string(child, &certs)) {
+ return -1;
+ }
+ ssl_opts.pem_root_certs = read_file(certs);
+ }
+ else if (!strcasecmp("SSLCertificateKeyFile", child->key)) {
+ char *key = NULL;
+ if (cf_util_get_string(child, &key)) {
+ return -1;
+ }
+ ssl_opts.pem_private_key = read_file(key);
+ }
+ else if (!strcasecmp("SSLCertificateFile", child->key)) {
+ char *cert = NULL;
+ if (cf_util_get_string(child, &cert)) {
+ return -1;
+ }
+ ssl_opts.pem_cert_chain = read_file(cert);
+ }
+ else {
+ WARNING("grpc: Option `%s` not allowed in <%s> block.",
+ child->key, ci->key);
+ }
+ }
+
+ auto node = grpc::string(ci->values[0].value.string);
+ auto service = grpc::string(ci->values[1].value.string);
+ auto addr = node + ":" + service;
+
+ CollectdClient *client;
+ if (use_ssl) {
+ auto channel_creds = grpc::SslCredentials(ssl_opts);
+ auto channel = grpc::CreateChannel(addr, channel_creds);
+ client = new CollectdClient(channel);
+ } else {
+ auto channel = grpc::CreateChannel(addr, grpc::InsecureChannelCredentials());
+ client = new CollectdClient(channel);
+ }
+
+ auto callback_name = grpc::string("grpc/") + addr;
+ user_data_t ud = {
+ .data = client,
+ .free_func = c_grpc_destroy_write_callback,
+ };
+
+ plugin_register_write (callback_name.c_str(), c_grpc_write, &ud);
+ return 0;
+ } /* c_grpc_config_server() */
+
+ static int c_grpc_config(oconfig_item_t *ci)
+ {
+ int i;
+
+ for (i = 0; i < ci->children_num; i++) {
+ oconfig_item_t *child = ci->children + i;
+
+ if (!strcasecmp("Listen", child->key)) {
+ if (c_grpc_config_listen(child))
+ return -1;
+ }
+ else if (!strcasecmp("Server", child->key)) {
+ if (c_grpc_config_server(child))
+ return -1;
+ }
+
+ else {
+ WARNING("grpc: Option `%s` not allowed here.", child->key);
+ }
+ }
+
+ return 0;
+ } /* c_grpc_config() */
+
+ static int c_grpc_init(void)
+ {
+ server = new CollectdServer();
+ if (!server) {
+ ERROR("grpc: Failed to create server");
+ return -1;
+ }
+
+ server->Start();
+ return 0;
+ } /* c_grpc_init() */
+
+ static int c_grpc_shutdown(void)
+ {
+ if (!server)
+ return 0;
+
+ server->Shutdown();
+
+ delete server;
+ server = nullptr;
+
+ return 0;
+ } /* c_grpc_shutdown() */
+
+ void module_register(void)
+ {
+ plugin_register_complex_config("grpc", c_grpc_config);
+ plugin_register_init("grpc", c_grpc_init);
+ plugin_register_shutdown("grpc", c_grpc_shutdown);
+ } /* module_register() */
+} /* extern "C" */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
diff --git a/src/hddtemp.c b/src/hddtemp.c
index 82c158cab17180dc18a4d5e878d1704b60e081ce..865ea8614afda35cee5993eeec8cf61e86c6f8b6 100644 (file)
--- a/src/hddtemp.c
+++ b/src/hddtemp.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
# include <netdb.h>
-# include <sys/socket.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <libgen.h> /* for basename */
const char *host;
const char *port;
- struct addrinfo ai_hints;
- struct addrinfo *ai_list, *ai_ptr;
+ struct addrinfo *ai_list;
int ai_return;
- memset (&ai_hints, '\0', sizeof (ai_hints));
- ai_hints.ai_flags = 0;
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = PF_UNSPEC;
- ai_hints.ai_socktype = SOCK_STREAM;
- ai_hints.ai_protocol = IPPROTO_TCP;
-
host = hddtemp_host;
if (host == NULL)
host = HDDTEMP_DEF_HOST;
if (strlen (port) == 0)
port = HDDTEMP_DEF_PORT;
+ struct addrinfo ai_hints = {
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_family = AF_UNSPEC,
+ .ai_protocol = IPPROTO_TCP,
+ .ai_socktype = SOCK_STREAM
+ };
+
if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
{
char errbuf[1024];
}
fd = -1;
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
/* create our socket descriptor */
fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
char *saveptr;
int num_fields;
int num_disks;
- int i;
/* get data from daemon */
if (hddtemp_query_daemon (buf, sizeof (buf)) < 0)
num_disks = num_fields / 4;
- for (i = 0; i < num_disks; i++)
+ for (int i = 0; i < num_disks; i++)
{
char *name;
double temperature;
diff --git a/src/interface.c b/src/interface.c
index df8ffb46c34522ee5696b22a3409a687c37161e4..b8ed6e402bf564b2185b11a1c2dee1416fef36b6 100644 (file)
--- a/src/interface.c
+++ b/src/interface.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_ignorelist.h"
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
/* One cannot include both. This sucks. */
#if HAVE_LINUX_IF_H
{
"Interface",
"IgnoreSelected",
- NULL
+ "ReportInactive",
};
-static int config_keys_num = 2;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static ignorelist_t *ignorelist = NULL;
+static _Bool report_inactive = 1;
+
#ifdef HAVE_LIBKSTAT
#define MAX_NUMIF 256
extern kstat_ctl_t *kc;
static kstat_t *ksp[MAX_NUMIF];
static int numif = 0;
+static _Bool unique_name = 0;
#endif /* HAVE_LIBKSTAT */
static int interface_config (const char *key, const char *value)
invert = 0;
ignorelist_set_invert (ignorelist, invert);
}
+ else if (strcasecmp (key, "ReportInactive") == 0)
+ report_inactive = IS_TRUE (value);
+ else if (strcasecmp (key, "UniqueName") == 0)
+ {
+ #ifdef HAVE_LIBKSTAT
+ if (IS_TRUE (value))
+ unique_name = 1;
+ #else
+ WARNING ("interface plugin: the \"UniqueName\" option is only valid on Solaris.");
+ #endif /* HAVE_LIBKSTAT */
+ }
else
{
return (-1);
static int interface_init (void)
{
kstat_t *ksp_chain;
- derive_t val;
numif = 0;
continue;
if (kstat_read (kc, ksp_chain, NULL) == -1)
continue;
- if ((val = get_kstat_value (ksp_chain, "obytes")) == -1LL)
+ if (get_kstat_value (ksp_chain, "obytes") == -1LL)
continue;
ksp[numif++] = ksp_chain;
}
{
#if HAVE_GETIFADDRS
struct ifaddrs *if_list;
- struct ifaddrs *if_ptr;
-/* Darin/Mac OS X and possible other *BSDs */
+/* Darwin/Mac OS X and possible other *BSDs */
#if HAVE_STRUCT_IF_DATA
# define IFA_DATA if_data
# define IFA_RX_BYTES ifi_ibytes
if (getifaddrs (&if_list) != 0)
return (-1);
- for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
+ for (struct ifaddrs *if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
{
if (if_ptr->ifa_addr != NULL && if_ptr->ifa_addr->sa_family == AF_LINK) {
if_data = (struct IFA_DATA *) if_ptr->ifa_data;
+ if (!report_inactive && if_data->IFA_RX_PACKT == 0 && if_data->IFA_TX_PACKT == 0)
+ continue;
+
if_submit (if_ptr->ifa_name, "if_octets",
if_data->IFA_RX_BYTES,
if_data->IFA_TX_BYTES);
if (numfields < 11)
continue;
- incoming = atoll (fields[0]);
- outgoing = atoll (fields[8]);
- if_submit (device, "if_octets", incoming, outgoing);
-
incoming = atoll (fields[1]);
outgoing = atoll (fields[9]);
+ if (!report_inactive && incoming == 0 && outgoing == 0)
+ continue;
+
if_submit (device, "if_packets", incoming, outgoing);
+ incoming = atoll (fields[0]);
+ outgoing = atoll (fields[8]);
+ if_submit (device, "if_octets", incoming, outgoing);
+
incoming = atoll (fields[2]);
outgoing = atoll (fields[10]);
if_submit (device, "if_errors", incoming, outgoing);
+
+ incoming = atoll (fields[3]);
+ outgoing = atoll (fields[11]);
+ if_submit (device, "if_dropped", incoming, outgoing);
}
fclose (fh);
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
- int i;
derive_t rx;
derive_t tx;
+ char iname[DATA_MAX_NAME_LEN];
if (kc == NULL)
return (-1);
- for (i = 0; i < numif; i++)
+ for (int i = 0; i < numif; i++)
{
if (kstat_read (kc, ksp[i], NULL) == -1)
continue;
+ if (unique_name)
+ ssnprintf(iname, sizeof(iname), "%s_%d_%s", ksp[i]->ks_module, ksp[i]->ks_instance, ksp[i]->ks_name);
+ else
+ sstrncpy(iname, ksp[i]->ks_name, sizeof(iname));
+
/* try to get 64bit counters */
- rx = get_kstat_value (ksp[i], "rbytes64");
- tx = get_kstat_value (ksp[i], "obytes64");
+ rx = get_kstat_value (ksp[i], "ipackets64");
+ tx = get_kstat_value (ksp[i], "opackets64");
/* or fallback to 32bit */
if (rx == -1LL)
- rx = get_kstat_value (ksp[i], "rbytes");
+ rx = get_kstat_value (ksp[i], "ipackets");
if (tx == -1LL)
- tx = get_kstat_value (ksp[i], "obytes");
+ tx = get_kstat_value (ksp[i], "opackets");
+ if (!report_inactive && rx == 0 && tx == 0)
+ continue;
if ((rx != -1LL) || (tx != -1LL))
- if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
+ if_submit (iname, "if_packets", rx, tx);
/* try to get 64bit counters */
- rx = get_kstat_value (ksp[i], "ipackets64");
- tx = get_kstat_value (ksp[i], "opackets64");
+ rx = get_kstat_value (ksp[i], "rbytes64");
+ tx = get_kstat_value (ksp[i], "obytes64");
/* or fallback to 32bit */
if (rx == -1LL)
- rx = get_kstat_value (ksp[i], "ipackets");
+ rx = get_kstat_value (ksp[i], "rbytes");
if (tx == -1LL)
- tx = get_kstat_value (ksp[i], "opackets");
+ tx = get_kstat_value (ksp[i], "obytes");
if ((rx != -1LL) || (tx != -1LL))
- if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
+ if_submit (iname, "if_octets", rx, tx);
/* no 64bit error counters yet */
rx = get_kstat_value (ksp[i], "ierrors");
tx = get_kstat_value (ksp[i], "oerrors");
if ((rx != -1LL) || (tx != -1LL))
- if_submit (ksp[i]->ks_name, "if_errors", rx, tx);
+ if_submit (iname, "if_errors", rx, tx);
}
/* #endif HAVE_LIBKSTAT */
#elif defined(HAVE_LIBSTATGRAB)
sg_network_io_stats *ios;
- int i, num;
+ int num;
ios = sg_get_network_io_stats (&num);
- for (i = 0; i < num; i++)
+ for (int i = 0; i < num; i++) {
+ if (!report_inactive && ios[i].rx == 0 && ios[i].tx == 0)
+ continue;
if_submit (ios[i].interface_name, "if_octets", ios[i].rx, ios[i].tx);
+ }
/* #endif HAVE_LIBSTATGRAB */
#elif defined(HAVE_PERFSTAT)
perfstat_id_t id;
- int i, ifs;
+ int ifs;
if ((nif = perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0)) < 0)
{
if (pnif != nif || ifstat == NULL)
{
- if (ifstat != NULL)
- free(ifstat);
- ifstat = malloc(nif * sizeof(perfstat_netinterface_t));
+ free(ifstat);
+ ifstat = malloc(nif * sizeof (*ifstat));
}
pnif = nif;
return (-1);
}
- for (i = 0; i < ifs; i++)
+ for (int i = 0; i < ifs; i++)
{
+ if (!report_inactive && ifstat[i].ipackets == 0 && ifstat[i].opackets == 0)
+ continue;
+
if_submit (ifstat[i].name, "if_octets", ifstat[i].ibytes, ifstat[i].obytes);
if_submit (ifstat[i].name, "if_packets", ifstat[i].ipackets ,ifstat[i].opackets);
if_submit (ifstat[i].name, "if_errors", ifstat[i].ierrors, ifstat[i].oerrors );
#endif
plugin_register_read ("interface", interface_read);
} /* void module_register */
+
diff --git a/src/ipc.c b/src/ipc.c
index b4038472efb76e4ff48df62e95b91307a8ff2dfc..b164cdf72b517da03de6847a4e7c68f4f6e5608e 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#if KERNEL_LINUX
/* _GNU_SOURCE is needed for struct shm_info.used_ids on musl libc */
@@ -213,7 +213,7 @@ static caddr_t ipc_get_info (cid_t cid, int cmd, int version, int stsize, int *n
*nmemb = size / stsize;
- buff = (caddr_t)malloc (size);
+ buff = malloc (size);
if (buff == NULL) {
ERROR ("ipc plugin: ipc_get_info malloc failed.");
return (NULL);
ipcinfo_sem_t *ipcinfo_sem;
unsigned short sem_nsems=0;
unsigned short sems=0;
- int i,n;
+ int n;
ipcinfo_sem = (ipcinfo_sem_t *)ipc_get_info(0,
GET_IPCINFO_SEM_ALL, IPCINFO_SEM_VERSION, sizeof(ipcinfo_sem_t), &n);
if (ipcinfo_sem == NULL)
return -1;
- for (i=0; i<n; i++) {
+ for (int i=0; i<n; i++) {
sem_nsems += ipcinfo_sem[i].sem_nsems;
sems++;
}
ipcinfo_shm_t *pshm;
unsigned int shm_segments=0;
size64_t shm_bytes=0;
- int i,n;
+ int n;
ipcinfo_shm = (ipcinfo_shm_t *)ipc_get_info(0,
GET_IPCINFO_SHM_ALL, IPCINFO_SHM_VERSION, sizeof(ipcinfo_shm_t), &n);
if (ipcinfo_shm == NULL)
return -1;
- for (i=0, pshm=ipcinfo_shm; i<n; i++, pshm++) {
+ for (int i=0, pshm=ipcinfo_shm; i<n; i++, pshm++) {
shm_segments++;
shm_bytes += pshm->shm_segsz;
}
uint32_t msg_used_space=0;
uint32_t msg_alloc_queues=0;
msgqnum32_t msg_qnum=0;
- int i,n;
+ int n;
ipcinfo_msg = (ipcinfo_msg_t *)ipc_get_info(0,
GET_IPCINFO_MSG_ALL, IPCINFO_MSG_VERSION, sizeof(ipcinfo_msg_t), &n);
if (ipcinfo_msg == NULL)
return -1;
- for (i=0; i<n; i++) {
+ for (int i=0; i<n; i++) {
msg_alloc_queues++;
msg_used_space += ipcinfo_msg[i].msg_cbytes;
msg_qnum += ipcinfo_msg[i].msg_qnum;
-
+ }
free(ipcinfo_msg);
ipc_submit_g("msg", "count", "queues", msg_alloc_queues);
diff --git a/src/ipmi.c b/src/ipmi.c
index 51d33dcb79635733d395fec6338c3ec4a7fe0036..ad62299e3390bba91aedf9c5656f711643962e44 100644 (file)
--- a/src/ipmi.c
+++ b/src/ipmi.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_ignorelist.h"
-#include <pthread.h>
-
#include <OpenIPMI/ipmiif.h>
#include <OpenIPMI/ipmi_err.h>
#include <OpenIPMI/ipmi_posix.h>
*/
static void c_ipmi_error (const char *func, int status)
{
- char errbuf[4096];
-
- memset (errbuf, 0, sizeof (errbuf));
+ char errbuf[4096] = { 0 };
if (IPMI_IS_OS_ERR (status))
{
c_ipmi_sensor_list_t *list_item;
c_ipmi_sensor_list_t *list_prev;
- char buffer[DATA_MAX_NAME_LEN];
+ char buffer[DATA_MAX_NAME_LEN] = { 0 };
const char *entity_id_string;
char sensor_name[DATA_MAX_NAME_LEN];
char *sensor_name_ptr;
sensor_id = ipmi_sensor_convert_to_id (sensor);
- memset (buffer, 0, sizeof (buffer));
ipmi_sensor_get_name (sensor, buffer, sizeof (buffer));
buffer[sizeof (buffer) - 1] = 0;
{
/* `sensor_id_ptr' now points to "(123)". */
ssnprintf (sensor_name, sizeof (sensor_name),
- "%s %s", sensor_name_ptr, sensor_id_ptr);
+ "%s %s", sensor_name_ptr, sensor_id_ptr);
}
/* else: don't touch sensor_name. */
}
static int sensor_list_read_all (void)
{
- c_ipmi_sensor_list_t *list_item;
-
pthread_mutex_lock (&sensor_list_lock);
- for (list_item = sensor_list;
+ for (c_ipmi_sensor_list_t *list_item = sensor_list;
list_item != NULL;
list_item = list_item->next)
{
static int thread_init (os_handler_t **ret_os_handler)
{
os_handler_t *os_handler;
- ipmi_open_option_t open_option[1];
ipmi_con_t *smi_connection = NULL;
ipmi_domain_id_t domain_id;
int status;
return (-1);
}
- memset (open_option, 0, sizeof (open_option));
- open_option[0].option = IPMI_OPEN_OPTION_ALL;
- open_option[0].ival = 1;
+ ipmi_open_option_t open_option[1] = {
+ [0] = {
+ .option = IPMI_OPEN_OPTION_ALL,
+ { .ival = 1 }
+ }
+ };
status = ipmi_open_domain ("mydomain", &smi_connection, /* num_con = */ 1,
domain_connection_change_handler, /* user data = */ NULL,
diff --git a/src/iptables.c b/src/iptables.c
index 590b693110a637dd36e4529b2cb4a854ca51c27b..f6911221df8739f31d77710eb59802a4d9fff1d4 100644 (file)
--- a/src/iptables.c
+++ b/src/iptables.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
-
-#include <sys/socket.h>
#include <libiptc/libiptc.h>
#include <libiptc/libip6tc.h>
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
/*
* iptc_handle_t was available before libiptc was officially available as a
* shared library. Note, that when the shared lib was introduced, the API and
*/
static const char *config_keys[] =
{
- "Chain",
- "Chain6"
+ "Chain",
+ "Chain6"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-/*
- Each table/chain combo that will be queried goes into this list
-*/
-
enum protocol_version_e
{
IPV4,
};
typedef enum protocol_version_e protocol_version_t;
+/*
+ * Each table/chain combo that will be queried goes into this list
+ */
#ifndef XT_TABLE_MAXNAMELEN
# define XT_TABLE_MAXNAMELEN 32
#endif
char chain[XT_TABLE_MAXNAMELEN];
union
{
- int num;
- char *comment;
+ int num;
+ char *comment;
} rule;
enum
{
- RTYPE_NUM,
- RTYPE_COMMENT,
- RTYPE_COMMENT_ALL
+ RTYPE_NUM,
+ RTYPE_COMMENT,
+ RTYPE_COMMENT_ALL
} rule_type;
char name[64];
} ip_chain_t;
static int iptables_config (const char *key, const char *value)
{
- /* int ip_value; */
- protocol_version_t ip_version = 0;
-
- if (strcasecmp (key, "Chain") == 0)
- ip_version = IPV4;
- else if (strcasecmp (key, "Chain6") == 0)
- ip_version = IPV6;
- else
- return (1);
-
- ip_chain_t temp, *final, **list;
- char *table;
- int table_len;
- char *chain;
- int chain_len;
-
- char *value_copy;
- char *fields[4];
- int fields_num;
-
- memset (&temp, 0, sizeof (temp));
-
- value_copy = strdup (value);
- if (value_copy == NULL)
- {
- char errbuf[1024];
- ERROR ("strdup failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (1);
- }
-
- /*
- * Time to fill the temp element
- * Examine value string, it should look like:
- * Chain[6] <table> <chain> [<comment|num> [name]]
- */
-
- /* set IPv4 or IPv6 */
- temp.ip_version = ip_version;
-
- /* Chain <table> <chain> [<comment|num> [name]] */
- fields_num = strsplit (value_copy, fields, 4);
- if (fields_num < 2)
- {
- free (value_copy);
- return (1);
- }
-
- table = fields[0];
- chain = fields[1];
-
- table_len = strlen (table) + 1;
- if ((unsigned int)table_len > sizeof(temp.table))
- {
- ERROR ("Table `%s' too long.", table);
- free (value_copy);
- return (1);
- }
- sstrncpy (temp.table, table, table_len);
-
- chain_len = strlen (chain) + 1;
- if ((unsigned int)chain_len > sizeof(temp.chain))
- {
- ERROR ("Chain `%s' too long.", chain);
- free (value_copy);
- return (1);
- }
- sstrncpy (temp.chain, chain, chain_len);
-
- if (fields_num >= 3)
- {
- char *comment = fields[2];
- int rule = atoi (comment);
-
- if (rule)
- {
- temp.rule.num = rule;
- temp.rule_type = RTYPE_NUM;
- }
- else
- {
- temp.rule.comment = strdup (comment);
- if (temp.rule.comment == NULL)
- {
- free (value_copy);
- return (1);
- }
- temp.rule_type = RTYPE_COMMENT;
- }
- }
- else
- {
- temp.rule_type = RTYPE_COMMENT_ALL;
- }
-
- if (fields_num >= 4)
- sstrncpy (temp.name, fields[3], sizeof (temp.name));
-
- free (value_copy);
- value_copy = NULL;
- table = NULL;
- chain = NULL;
-
- list = (ip_chain_t **) realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
- if (list == NULL)
- {
- char errbuf[1024];
- ERROR ("realloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- sfree (temp.rule.comment);
- return (1);
- }
-
- chain_list = list;
- final = (ip_chain_t *) malloc( sizeof(temp) );
- if (final == NULL)
- {
- char errbuf[1024];
- ERROR ("malloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- sfree (temp.rule.comment);
- return (1);
- }
- memcpy (final, &temp, sizeof (temp));
- chain_list[chain_num] = final;
- chain_num++;
-
- DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
-
- return (0);
+ /* int ip_value; */
+ protocol_version_t ip_version = 0;
+
+ if (strcasecmp (key, "Chain") == 0)
+ ip_version = IPV4;
+ else if (strcasecmp (key, "Chain6") == 0)
+ ip_version = IPV6;
+ else
+ return (1);
+
+ ip_chain_t temp = { 0 };
+ ip_chain_t *final, **list;
+ char *table;
+ int table_len;
+ char *chain;
+ int chain_len;
+
+ char *value_copy;
+ char *fields[4];
+ int fields_num;
+
+ value_copy = strdup (value);
+ if (value_copy == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("strdup failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (1);
+ }
+
+ /*
+ * Time to fill the temp element
+ * Examine value string, it should look like:
+ * Chain[6] <table> <chain> [<comment|num> [name]]
+ */
+
+ /* set IPv4 or IPv6 */
+ temp.ip_version = ip_version;
+
+ /* Chain <table> <chain> [<comment|num> [name]] */
+ fields_num = strsplit (value_copy, fields, 4);
+ if (fields_num < 2)
+ {
+ free (value_copy);
+ return (1);
+ }
+
+ table = fields[0];
+ chain = fields[1];
+
+ table_len = strlen (table) + 1;
+ if ((unsigned int)table_len > sizeof(temp.table))
+ {
+ ERROR ("Table `%s' too long.", table);
+ free (value_copy);
+ return (1);
+ }
+ sstrncpy (temp.table, table, table_len);
+
+ chain_len = strlen (chain) + 1;
+ if ((unsigned int)chain_len > sizeof(temp.chain))
+ {
+ ERROR ("Chain `%s' too long.", chain);
+ free (value_copy);
+ return (1);
+ }
+ sstrncpy (temp.chain, chain, chain_len);
+
+ if (fields_num >= 3)
+ {
+ char *comment = fields[2];
+ int rule = atoi (comment);
+
+ if (rule)
+ {
+ temp.rule.num = rule;
+ temp.rule_type = RTYPE_NUM;
+ }
+ else
+ {
+ temp.rule.comment = strdup (comment);
+ if (temp.rule.comment == NULL)
+ {
+ free (value_copy);
+ return (1);
+ }
+ temp.rule_type = RTYPE_COMMENT;
+ }
+ }
+ else
+ {
+ temp.rule_type = RTYPE_COMMENT_ALL;
+ }
+
+ if (fields_num >= 4)
+ sstrncpy (temp.name, fields[3], sizeof (temp.name));
+
+ free (value_copy);
+ value_copy = NULL;
+ table = NULL;
+ chain = NULL;
+
+ list = realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
+ if (list == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("realloc failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ sfree (temp.rule.comment);
+ return (1);
+ }
+
+ chain_list = list;
+ final = malloc(sizeof (*final));
+ if (final == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("malloc failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ sfree (temp.rule.comment);
+ return (1);
+ }
+ memcpy (final, &temp, sizeof (temp));
+ chain_list[chain_num] = final;
+ chain_num++;
+
+ DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
+
+ return (0);
} /* int iptables_config */
static int submit6_match (const struct ip6t_entry_match *match,
- const struct ip6t_entry *entry,
- const ip_chain_t *chain,
- int rule_num)
+ const struct ip6t_entry *entry,
+ const ip_chain_t *chain,
+ int rule_num)
{
int status;
value_t values[1];
if (strcmp (match->u.user.name, "comment") != 0)
return (0);
if ((chain->rule_type == RTYPE_COMMENT)
- && (strcmp (chain->rule.comment, (char *) match->data) != 0))
+ && (strcmp (chain->rule.comment, (char *) match->data) != 0))
return (0);
}
sstrncpy (vl.plugin, "ip6tables", sizeof (vl.plugin));
status = ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
- "%s-%s", chain->table, chain->chain);
+ "%s-%s", chain->table, chain->chain);
if ((status < 1) || ((unsigned int)status >= sizeof (vl.plugin_instance)))
return (0);
{
if (chain->rule_type == RTYPE_NUM)
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
- "%i", chain->rule.num);
+ "%i", chain->rule.num);
else
sstrncpy (vl.type_instance, (char *) match->data,
- sizeof (vl.type_instance));
+ sizeof (vl.type_instance));
}
sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
/* This needs to return `int' for IPT_MATCH_ITERATE to work. */
static int submit_match (const struct ipt_entry_match *match,
- const struct ipt_entry *entry,
- const ip_chain_t *chain,
- int rule_num)
+ const struct ipt_entry *entry,
+ const ip_chain_t *chain,
+ int rule_num)
{
int status;
value_t values[1];
/* Select the rules to collect */
if (chain->rule_type == RTYPE_NUM)
{
- if (chain->rule.num != rule_num)
- return (0);
+ if (chain->rule.num != rule_num)
+ return (0);
}
else
{
- if (strcmp (match->u.user.name, "comment") != 0)
- return (0);
- if ((chain->rule_type == RTYPE_COMMENT)
- && (strcmp (chain->rule.comment, (char *) match->data) != 0))
- return (0);
+ if (strcmp (match->u.user.name, "comment") != 0)
+ return (0);
+ if ((chain->rule_type == RTYPE_COMMENT)
+ && (strcmp (chain->rule.comment, (char *) match->data) != 0))
+ return (0);
}
vl.values = values;
sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin));
status = ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
- "%s-%s", chain->table, chain->chain);
+ "%s-%s", chain->table, chain->chain);
if ((status < 1) || ((unsigned int)status >= sizeof (vl.plugin_instance)))
- return (0);
+ return (0);
if (chain->name[0] != '\0')
{
- sstrncpy (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)
- ssnprintf (vl.type_instance, sizeof (vl.type_instance),
- "%i", chain->rule.num);
- else
- sstrncpy (vl.type_instance, (char *) match->data,
- sizeof (vl.type_instance));
+ if (chain->rule_type == RTYPE_NUM)
+ ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+ "%i", chain->rule.num);
+ else
+ sstrncpy (vl.type_instance, (char *) match->data,
+ sizeof (vl.type_instance));
}
sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
/* ipv6 submit_chain */
-static void submit6_chain( ip6tc_handle_t *handle, ip_chain_t *chain )
+static void submit6_chain (ip6tc_handle_t *handle, ip_chain_t *chain)
{
const struct ip6t_entry *entry;
int rule_num;
/* ipv4 submit_chain */
-static void submit_chain( iptc_handle_t *handle, ip_chain_t *chain )
+static void submit_chain (iptc_handle_t *handle, ip_chain_t *chain)
{
const struct ipt_entry *entry;
int rule_num;
- /* Find first rule for chain and use the iterate macro */
+ /* Find first rule for chain and use the iterate macro */
entry = iptc_first_rule( chain->chain, handle );
if (entry == NULL)
{
- DEBUG ("iptc_first_rule failed: %s", iptc_strerror (errno));
- return;
+ DEBUG ("iptc_first_rule failed: %s", iptc_strerror (errno));
+ return;
}
rule_num = 1;
while (entry)
{
- if (chain->rule_type == RTYPE_NUM)
- {
- submit_match (NULL, entry, chain, rule_num);
- }
- else
- {
- IPT_MATCH_ITERATE( entry, submit_match, entry, chain, rule_num );
- }
-
- entry = iptc_next_rule( entry, handle );
- rule_num++;
+ if (chain->rule_type == RTYPE_NUM)
+ {
+ submit_match (NULL, entry, chain, rule_num);
+ }
+ else
+ {
+ IPT_MATCH_ITERATE( entry, submit_match, entry, chain, rule_num );
+ }
+
+ entry = iptc_next_rule( entry, handle );
+ rule_num++;
} /* while (entry) */
}
static int iptables_read (void)
{
- int i;
int num_failures = 0;
ip_chain_t *chain;
- /* Init the iptc handle structure and query the correct table */
- for (i = 0; i < chain_num; i++)
+ /* Init the iptc handle structure and query the correct table */
+ for (int i = 0; i < chain_num; i++)
{
- chain = chain_list[i];
-
- if (!chain)
- {
- DEBUG ("iptables plugin: chain == NULL");
- continue;
- }
-
- if ( chain->ip_version == IPV4 )
+ chain = chain_list[i];
+
+ if (!chain)
+ {
+ DEBUG ("iptables plugin: chain == NULL");
+ continue;
+ }
+
+ if ( chain->ip_version == IPV4 )
{
#ifdef HAVE_IPTC_HANDLE_T
- iptc_handle_t _handle;
- iptc_handle_t *handle = &_handle;
+ iptc_handle_t _handle;
+ iptc_handle_t *handle = &_handle;
- *handle = iptc_init (chain->table);
+ *handle = iptc_init (chain->table);
#else
- iptc_handle_t *handle;
- handle = iptc_init (chain->table);
+ iptc_handle_t *handle;
+ handle = iptc_init (chain->table);
#endif
- if (!handle)
- {
- ERROR ("iptables plugin: iptc_init (%s) failed: %s",
- chain->table, iptc_strerror (errno));
- num_failures++;
- continue;
- }
+ if (!handle)
+ {
+ ERROR ("iptables plugin: iptc_init (%s) failed: %s",
+ chain->table, iptc_strerror (errno));
+ num_failures++;
+ continue;
+ }
- submit_chain (handle, chain);
- iptc_free (handle);
+ submit_chain (handle, chain);
+ iptc_free (handle);
}
else if ( chain->ip_version == IPV6 )
{
#ifdef HAVE_IP6TC_HANDLE_T
- ip6tc_handle_t _handle;
- ip6tc_handle_t *handle = &_handle;
+ ip6tc_handle_t _handle;
+ ip6tc_handle_t *handle = &_handle;
- *handle = ip6tc_init (chain->table);
+ *handle = ip6tc_init (chain->table);
#else
- ip6tc_handle_t *handle;
- handle = ip6tc_init (chain->table);
+ ip6tc_handle_t *handle;
+ handle = ip6tc_init (chain->table);
#endif
-
- if (!handle)
- {
- ERROR ("iptables plugin: ip6tc_init (%s) failed: %s",
- chain->table, ip6tc_strerror (errno));
- num_failures++;
- continue;
- }
-
- submit6_chain (handle, chain);
- ip6tc_free (handle);
+ if (!handle)
+ {
+ ERROR ("iptables plugin: ip6tc_init (%s) failed: %s",
+ chain->table, ip6tc_strerror (errno));
+ num_failures++;
+ continue;
+ }
+
+ submit6_chain (handle, chain);
+ ip6tc_free (handle);
}
- else num_failures++;
-
+ else
+ num_failures++;
} /* for (i = 0 .. chain_num) */
return ((num_failures < chain_num) ? 0 : -1);
static int iptables_shutdown (void)
{
- int i;
-
- for (i = 0; i < chain_num; i++)
+ for (int i = 0; i < chain_num; i++)
{
- if ((chain_list[i] != NULL) && (chain_list[i]->rule_type == RTYPE_COMMENT))
- {
- sfree (chain_list[i]->rule.comment);
- }
- sfree (chain_list[i]);
+ if ((chain_list[i] != NULL) && (chain_list[i]->rule_type == RTYPE_COMMENT))
+ sfree (chain_list[i]->rule.comment);
+ sfree (chain_list[i]);
}
sfree (chain_list);
return (0);
} /* int iptables_shutdown */
+static int iptables_init (void)
+{
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_ADMIN)
+ if (check_capability (CAP_NET_ADMIN) != 0)
+ {
+ if (getuid () == 0)
+ WARNING ("iptables plugin: Running collectd as root, but the "
+ "CAP_NET_ADMIN capability is missing. The plugin's read "
+ "function will probably fail. Is your init system dropping "
+ "capabilities?");
+ else
+ WARNING ("iptables plugin: collectd doesn't have the CAP_NET_ADMIN "
+ "capability. If you don't want to run collectd as root, try "
+ "running \"setcap cap_net_admin=ep\" on the collectd binary.");
+ }
+#endif
+ return (0);
+} /* int iptables_init */
+
void module_register (void)
{
plugin_register_config ("iptables", iptables_config,
- config_keys, config_keys_num);
+ config_keys, config_keys_num);
+ plugin_register_init ("iptables", iptables_init);
plugin_register_read ("iptables", iptables_read);
plugin_register_shutdown ("iptables", iptables_shutdown);
} /* void module_register */
-/*
- * vim:shiftwidth=4:softtabstop=4:tabstop=8
- */
diff --git a/src/ipvs.c b/src/ipvs.c
index cbb554286bd08f292219ff91b8a81a601925638d..92690e88e0098635a8cc56fe9c6191116b81082e 100644 (file)
--- a/src/ipvs.c
+++ b/src/ipvs.c
*/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#if HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif /* HAVE_ARPA_INET_H */
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif /* HAVE_SYS_SOCKET_H */
#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
(se->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
ntohs (se->port));
- if ((0 > len) || (size <= len)) {
+ if ((0 > len) || (size <= ((size_t) len))) {
log_err ("plugin instance truncated: %s", pi);
return -1;
}
len = ssnprintf (ti, size, "%s_%u", inet_ntoa (addr),
ntohs (de->port));
- if ((0 > len) || (size <= len)) {
+ if ((0 > len) || (size <= ((size_t) len))) {
log_err ("type instance truncated: %s", ti);
return -1;
}
return 0;
} /* get_ti */
-static void cipvs_submit_connections (char *pi, char *ti, derive_t value)
+static void cipvs_submit_connections (const char *pi, const char *ti,
+ derive_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
return;
} /* cipvs_submit_connections */
-static void cipvs_submit_if (char *pi, char *t, char *ti,
+static void cipvs_submit_if (const char *pi, const char *t, const char *ti,
derive_t rx, derive_t tx)
{
value_t values[2];
return;
} /* cipvs_submit_if */
-static void cipvs_submit_dest (char *pi, struct ip_vs_dest_entry *de) {
+static void cipvs_submit_dest (const char *pi, struct ip_vs_dest_entry *de)
+{
struct ip_vs_stats_user stats = de->stats;
char ti[DATA_MAX_NAME_LEN];
char pi[DATA_MAX_NAME_LEN];
- int i = 0;
-
if (0 != get_pi (se, pi, sizeof (pi)))
{
free (dests);
cipvs_submit_if (pi, "if_packets", NULL, stats.inpkts, stats.outpkts);
cipvs_submit_if (pi, "if_octets", NULL, stats.inbytes, stats.outbytes);
- for (i = 0; i < dests->num_dests; ++i)
+ for (size_t i = 0; i < dests->num_dests; ++i)
cipvs_submit_dest (pi, &dests->entrytable[i]);
free (dests);
static int cipvs_read (void)
{
struct ip_vs_get_services *services = NULL;
- int i = 0;
if (sockfd < 0)
return (-1);
if (NULL == (services = ipvs_get_services ()))
return -1;
- for (i = 0; i < services->num_services; ++i)
+ for (size_t i = 0; i < services->num_services; ++i)
cipvs_submit_service (&services->entrytable[i]);
free (services);
diff --git a/src/irq.c b/src/irq.c
index 93f3f53bea09b964db1f32109c88faf685465e15..0f1d3f0ce50954ffd7d4524a52cd36d5bd884744 100644 (file)
--- a/src/irq.c
+++ b/src/irq.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_ignorelist.h"
#if !KERNEL_LINUX
diff --git a/src/java.c b/src/java.c
index c74fe6c79de8fee4a3e80cd3a6fd7f15ea7dcb62..67740ac8dae78c6da33a4d47891c9824fa04096a 100644 (file)
--- a/src/java.c
+++ b/src/java.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include "filter_chain.h"
-#include <pthread.h>
#include <jni.h>
#if !defined(JNI_VERSION_1_2)
jmethodID m_addchild;
jobject o_key;
jobject o_ocitem;
- int i;
c_ocitem = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/OConfigItem");
if (c_ocitem == NULL)
(*jvm_env)->DeleteLocalRef (jvm_env, o_key);
/* Call OConfigItem.addValue for each value */
- for (i = 0; i < ci->values_num; i++) /* {{{ */
+ for (int i = 0; i < ci->values_num; i++) /* {{{ */
{
jobject o_value;
} /* }}} for (i = 0; i < ci->values_num; i++) */
/* Call OConfigItem.addChild for each child */
- for (i = 0; i < ci->children_num; i++) /* {{{ */
+ for (int i = 0; i < ci->children_num; i++) /* {{{ */
{
jobject o_child;
jmethodID m_add;
jobject o_type;
jobject o_dataset;
- int i;
/* Look up the org/collectd/api/DataSet class */
c_dataset = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/DataSet");
/* Decrease reference counter on the java.lang.String object. */
(*jvm_env)->DeleteLocalRef (jvm_env, o_type);
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
jobject o_datasource;
jmethodID m_valuelist_constructor;
jobject o_valuelist;
int status;
- int i;
/* First, create a new ValueList instance..
* Look up the class.. */
return (NULL);
}
- for (i = 0; i < vl->values_len; i++)
+ for (size_t i = 0; i < vl->values_len; i++)
{
status = ctoj_value_list_add_value (jvm_env, vl->values[i], ds->ds[i].type,
c_valuelist, o_valuelist);
value_t *values;
int values_num;
- int i;
values_num = ds->ds_num;
BAIL_OUT (-1);
}
- for (i = 0; i < values_num; i++)
+ for (int i = 0; i < values_num; i++)
{
jobject o_number;
int status;
static jint JNICALL cjni_api_dispatch_notification (JNIEnv *jvm_env, /* {{{ */
jobject this, jobject o_notification)
{
- notification_t n;
+ notification_t n = { 0 };
int status;
- memset (&n, 0, sizeof (n));
- n.meta = NULL;
-
status = jtoc_notification (jvm_env, &n, o_notification);
if (status != 0)
{
static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */
jobject this, jobject o_name, jobject o_read)
{
- user_data_t ud;
cjni_callback_info_t *cbi;
cbi = cjni_callback_info_create (jvm_env, o_name, o_read, CB_TYPE_READ);
DEBUG ("java plugin: Registering new read callback: %s", cbi->name);
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) cbi;
- ud.free_func = cjni_callback_info_destroy;
+ user_data_t ud = {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy
+ };
plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
(*jvm_env)->DeleteLocalRef (jvm_env, o_read);
static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */
jobject this, jobject o_name, jobject o_write)
{
- user_data_t ud;
cjni_callback_info_t *cbi;
cbi = cjni_callback_info_create (jvm_env, o_name, o_write, CB_TYPE_WRITE);
DEBUG ("java plugin: Registering new write callback: %s", cbi->name);
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) cbi;
- ud.free_func = cjni_callback_info_destroy;
+ user_data_t ud = {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy
+ };
plugin_register_write (cbi->name, cjni_write, &ud);
static jint JNICALL cjni_api_register_flush (JNIEnv *jvm_env, /* {{{ */
jobject this, jobject o_name, jobject o_flush)
{
- user_data_t ud;
cjni_callback_info_t *cbi;
cbi = cjni_callback_info_create (jvm_env, o_name, o_flush, CB_TYPE_FLUSH);
DEBUG ("java plugin: Registering new flush callback: %s", cbi->name);
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) cbi;
- ud.free_func = cjni_callback_info_destroy;
+ user_data_t ud = {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy
+ };
plugin_register_flush (cbi->name, cjni_flush, &ud);
static jint JNICALL cjni_api_register_log (JNIEnv *jvm_env, /* {{{ */
jobject this, jobject o_name, jobject o_log)
{
- user_data_t ud;
cjni_callback_info_t *cbi;
cbi = cjni_callback_info_create (jvm_env, o_name, o_log, CB_TYPE_LOG);
DEBUG ("java plugin: Registering new log callback: %s", cbi->name);
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) cbi;
- ud.free_func = cjni_callback_info_destroy;
+ user_data_t ud = {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy
+ };
plugin_register_log (cbi->name, cjni_log, &ud);
static jint JNICALL cjni_api_register_notification (JNIEnv *jvm_env, /* {{{ */
jobject this, jobject o_name, jobject o_notification)
{
- user_data_t ud;
cjni_callback_info_t *cbi;
cbi = cjni_callback_info_create (jvm_env, o_name, o_notification,
@@ -1534,9 +1526,10 @@ static jint JNICALL cjni_api_register_notification (JNIEnv *jvm_env, /* {{{ */
DEBUG ("java plugin: Registering new notification callback: %s", cbi->name);
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) cbi;
- ud.free_func = cjni_callback_info_destroy;
+ user_data_t ud = {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy
+ };
plugin_register_notification (cbi->name, cjni_notification, &ud);
@@ -1568,9 +1561,8 @@ static jint JNICALL cjni_api_register_match_target (JNIEnv *jvm_env, /* {{{ */
if (type == CB_TYPE_MATCH)
{
- match_proc_t m_proc;
+ match_proc_t m_proc = { 0 };
- memset (&m_proc, 0, sizeof (m_proc));
m_proc.create = cjni_match_target_create;
m_proc.destroy = cjni_match_target_destroy;
m_proc.match = (void *) cjni_match_target_invoke;
@@ -1579,9 +1571,8 @@ static jint JNICALL cjni_api_register_match_target (JNIEnv *jvm_env, /* {{{ */
}
else if (type == CB_TYPE_TARGET)
{
- target_proc_t t_proc;
+ target_proc_t t_proc = { 0 };
- memset (&t_proc, 0, sizeof (t_proc));
t_proc.create = cjni_match_target_create;
t_proc.destroy = cjni_match_target_destroy;
t_proc.invoke = cjni_match_target_invoke;
@@ -1801,14 +1792,13 @@ static cjni_callback_info_t *cjni_callback_info_create (JNIEnv *jvm_env, /* {{{
return (NULL);
}
- cbi = (cjni_callback_info_t *) malloc (sizeof (*cbi));
+ cbi = calloc (1, sizeof (*cbi));
if (cbi == NULL)
{
- ERROR ("java plugin: cjni_callback_info_create: malloc failed.");
+ ERROR ("java plugin: cjni_callback_info_create: calloc failed.");
(*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
return (NULL);
}
- memset (cbi, 0, sizeof (*cbi));
cbi->type = type;
cbi->name = strdup (c_name);
pthread_mutex_lock (&java_callbacks_lock);
- tmp = (cjni_callback_info_t *) realloc (java_callbacks,
+ tmp = realloc (java_callbacks,
(java_callbacks_num + 1) * sizeof (*java_callbacks));
if (tmp == NULL)
{
static int cjni_create_jvm (void) /* {{{ */
{
JNIEnv *jvm_env;
- JavaVMInitArgs vm_args;
+ JavaVMInitArgs vm_args = { 0 };
JavaVMOption vm_options[jvm_argc];
int status;
- size_t i;
if (jvm != NULL)
return (0);
jvm_env = NULL;
- memset (&vm_args, 0, sizeof (vm_args));
vm_args.version = JNI_VERSION_1_2;
vm_args.options = vm_options;
vm_args.nOptions = (jint) jvm_argc;
- for (i = 0; i < jvm_argc; i++)
+ for (size_t i = 0; i < jvm_argc; i++)
{
DEBUG ("java plugin: cjni_create_jvm: jvm_argv[%zu] = %s",
i, jvm_argv[i]);
if (cjni_env == NULL)
{
/* This pointer is free'd in `cjni_jvm_env_destroy'. */
- cjni_env = (cjni_jvm_env_t *) malloc (sizeof (*cjni_env));
+ cjni_env = calloc (1, sizeof (*cjni_env));
if (cjni_env == NULL)
{
- ERROR ("java plugin: cjni_thread_attach: malloc failed.");
+ ERROR ("java plugin: cjni_thread_attach: calloc failed.");
return (NULL);
}
- memset (cjni_env, 0, sizeof (*cjni_env));
cjni_env->reference_counter = 0;
cjni_env->jvm_env = NULL;
else
{
int status;
- JavaVMAttachArgs args;
+ JavaVMAttachArgs args = { 0 };
assert (cjni_env->jvm_env == NULL);
- memset (&args, 0, sizeof (args));
args.version = JNI_VERSION_1_2;
status = (*jvm)->AttachCurrentThread (jvm, (void *) &jvm_env, (void *) &args);
return (-1);
}
- tmp = (char **) realloc (jvm_argv, sizeof (char *) * (jvm_argc + 1));
+ tmp = realloc (jvm_argv, sizeof (char *) * (jvm_argc + 1));
if (tmp == NULL)
{
ERROR ("java plugin: realloc failed.");
if (jvm_env == NULL)
return (-1);
- class = (java_plugin_class_t *) realloc (java_classes_list,
+ class = realloc (java_classes_list,
(java_classes_list_len + 1) * sizeof (*java_classes_list));
if (class == NULL)
{
{ /* Replace all dots ('.') with slashes ('/'). Dots are usually used
thorough the Java community, but (Sun's) `FindClass' and friends need
slashes. */
- size_t i;
- for (i = 0; class->name[i] != 0; i++)
+ for (size_t i = 0; class->name[i] != 0; i++)
if (class->name[i] == '.')
class->name[i] = '/';
}
cjni_callback_info_t *cbi;
jobject o_ocitem;
const char *name;
- size_t i;
jclass class;
jmethodID method;
name = ci->values[0].value.string;
cbi = NULL;
- for (i = 0; i < java_callbacks_num; i++)
+ for (size_t i = 0; i < java_callbacks_num; i++)
{
if (java_callbacks[i].type != CB_TYPE_CONFIG)
continue;
int success;
int errors;
int status;
- int i;
success = 0;
errors = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
jobject o_ci;
jobject o_tmp;
int type;
- size_t i;
cbi_ret = NULL;
o_ci = NULL;
/* Lets see if we have a matching factory here.. */
cbi_factory = NULL;
- for (i = 0; i < java_callbacks_num; i++)
+ for (size_t i = 0; i < java_callbacks_num; i++)
{
if (java_callbacks[i].type != type)
continue;
/* Allocate a new callback info structure. This is going to be our user_data
* pointer. */
- cbi_ret = (cjni_callback_info_t *) malloc (sizeof (*cbi_ret));
+ cbi_ret = calloc (1, sizeof (*cbi_ret));
if (cbi_ret == NULL)
{
- ERROR ("java plugin: cjni_match_target_create: malloc failed.");
+ ERROR ("java plugin: cjni_match_target_create: calloc failed.");
BAIL_OUT (-1);
}
- memset (cbi_ret, 0, sizeof (*cbi_ret));
+
cbi_ret->object = NULL;
cbi_ret->type = type;
* `value_list_t'. */
if (cbi->type == CB_TYPE_TARGET)
{
- value_list_t new_vl;
+ value_list_t new_vl = { 0 };
- memset (&new_vl, 0, sizeof (new_vl));
status = jtoc_value_list (jvm_env, &new_vl, o_vl);
if (status != 0)
{
static int cjni_init_plugins (JNIEnv *jvm_env) /* {{{ */
{
int status;
- size_t i;
- for (i = 0; i < java_callbacks_num; i++)
+ for (size_t i = 0; i < java_callbacks_num; i++)
{
if (java_callbacks[i].type != CB_TYPE_INIT)
continue;
static int cjni_shutdown_plugins (JNIEnv *jvm_env) /* {{{ */
{
int status;
- size_t i;
- for (i = 0; i < java_callbacks_num; i++)
+ for (size_t i = 0; i < java_callbacks_num; i++)
{
if (java_callbacks[i].type != CB_TYPE_SHUTDOWN)
continue;
static int cjni_shutdown (void) /* {{{ */
{
JNIEnv *jvm_env;
- JavaVMAttachArgs args;
+ JavaVMAttachArgs args = { 0 };
int status;
- size_t i;
if (jvm == NULL)
return (0);
jvm_env = NULL;
- memset (&args, 0, sizeof (args));
args.version = JNI_VERSION_1_2;
status = (*jvm)->AttachCurrentThread (jvm, (void *) &jvm_env, &args);
cjni_shutdown_plugins (jvm_env);
/* Release all the global references to callback functions */
- for (i = 0; i < java_callbacks_num; i++)
+ for (size_t i = 0; i < java_callbacks_num; i++)
{
if (java_callbacks[i].object != NULL)
{
sfree (java_callbacks);
/* Release all the global references to directly loaded classes. */
- for (i = 0; i < java_classes_list_len; i++)
+ for (size_t i = 0; i < java_classes_list_len; i++)
{
if (java_classes_list[i].object != NULL)
{
pthread_key_delete (jvm_env_key);
/* Free the JVM argument list */
- for (i = 0; i < jvm_argc; i++)
+ for (size_t i = 0; i < jvm_argc; i++)
sfree (jvm_argv[i]);
jvm_argc = 0;
sfree (jvm_argv);
index 5abee2f1a44f1fd0abdce185c1cb390ffd00aeab..e81a59438394960ab8cb6b4b0c0e40a30ca6befa 100644 (file)
AUTOMAKE_OPTIONS = foreign no-dependencies
-if COMPILER_IS_GCC
-AM_CFLAGS = -Wall -Werror
-endif
-
pkginclude_HEADERS = collectd/client.h collectd/network.h collectd/network_buffer.h collectd/lcc_features.h
lib_LTLIBRARIES = libcollectdclient.la
nodist_pkgconfig_DATA = libcollectdclient.pc
index bdb21f659558047e87199bb0d63bbd8d03f43a9c..4dbee1e8d56d17d2fe38b862b397d61b2aa49a9b 100644 (file)
/*
* Private functions
*/
+__attribute__ ((format (printf, 1, 0)))
static int lcc_tracef(char const *format, ...)
{
va_list ap;
static void lcc_response_free (lcc_response_t *res) /* {{{ */
{
- size_t i;
-
if (res == NULL)
return;
- for (i = 0; i < res->lines_num; i++)
+ for (size_t i = 0; i < res->lines_num; i++)
free (res->lines[i]);
free (res->lines);
res->lines = NULL;
static int lcc_receive (lcc_connection_t *c, /* {{{ */
lcc_response_t *ret_res)
{
- lcc_response_t res;
+ lcc_response_t res = { 0 };
char *ptr;
char buffer[4096];
size_t i;
- memset (&res, 0, sizeof (res));
-
/* Read the first line, containing the status and a message */
ptr = fgets (buffer, sizeof (buffer), c->fh);
if (ptr == NULL)
* beginning of the message. */
ptr = NULL;
errno = 0;
- res.status = strtol (buffer, &ptr, 0);
+ res.status = (int) strtol (buffer, &ptr, 0);
if ((errno != 0) || (ptr == &buffer[0]))
{
lcc_set_errno (c, errno);
/* Allocate space for the char-pointers */
res.lines_num = (size_t) res.status;
res.status = 0;
- res.lines = (char **) malloc (res.lines_num * sizeof (char *));
+ res.lines = malloc (res.lines_num * sizeof (*res.lines));
if (res.lines == NULL)
{
lcc_set_errno (c, ENOMEM);
static int lcc_sendreceive (lcc_connection_t *c, /* {{{ */
const char *command, lcc_response_t *ret_res)
{
- lcc_response_t res;
+ lcc_response_t res = { 0 };
int status;
if (c->fh == NULL)
if (status != 0)
return (status);
- memset (&res, 0, sizeof (res));
status = lcc_receive (c, &res);
if (status == 0)
memcpy (ret_res, &res, sizeof (*ret_res));
static int lcc_open_unixsocket (lcc_connection_t *c, const char *path) /* {{{ */
{
- struct sockaddr_un sa;
+ struct sockaddr_un sa = { 0 };
int fd;
int status;
@@ -409,7 +405,6 @@ static int lcc_open_unixsocket (lcc_connection_t *c, const char *path) /* {{{ */
return (-1);
}
- memset (&sa, 0, sizeof (sa));
sa.sun_family = AF_UNIX;
strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);
@@ -435,9 +430,7 @@ static int lcc_open_unixsocket (lcc_connection_t *c, const char *path) /* {{{ */
static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */
const char *addr_orig)
{
- struct addrinfo ai_hints;
struct addrinfo *ai_res;
- struct addrinfo *ai_ptr;
char addr_copy[NI_MAXHOST];
char *addr;
char *port;
addr_copy[sizeof(addr_copy) - 1] = '\0';
addr = addr_copy;
- memset (&ai_hints, 0, sizeof (ai_hints));
- ai_hints.ai_flags = 0;
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_STREAM;
-
port = NULL;
if (*addr == '[') /* IPv6+port format */
{
}
}
- ai_res = NULL;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_socktype = SOCK_STREAM
+ };
+
status = getaddrinfo (addr,
port == NULL ? LCC_DEFAULT_PORT : port,
&ai_hints, &ai_res);
return (-1);
}
- for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
if (fd < 0)
if (ret_con == NULL)
return (-1);
- c = (lcc_connection_t *) malloc (sizeof (*c));
+ c = calloc (1, sizeof (*c));
if (c == NULL)
return (-1);
- memset (c, 0, sizeof (*c));
status = lcc_open_socket (c, address);
if (status != 0)
/* Allocate space for the values */
if (ret_values != NULL)
{
- values = (gauge_t *) malloc (values_num * sizeof (*values));
+ values = malloc (values_num * sizeof (*values));
if (values == NULL)
BAIL_OUT (ENOMEM);
}
if (ret_values_names != NULL)
{
- values_names = (char **) calloc (values_num, sizeof (*values_names));
+ values_names = calloc (values_num, sizeof (*values_names));
if (values_names == NULL)
BAIL_OUT (ENOMEM);
}
char command[1024] = "";
lcc_response_t res;
int status;
- size_t i;
if ((c == NULL) || (vl == NULL) || (vl->values_len < 1)
|| (vl->values == NULL) || (vl->values_types == NULL))
else
SSTRCAT (command, " N");
- for (i = 0; i < vl->values_len; i++)
+ for (size_t i = 0; i < vl->values_len; i++)
{
if (vl->values_types[i] == LCC_TYPE_COUNTER)
SSTRCATF (command, ":%"PRIu64, vl->values[i].counter);
lcc_identifier_t **ret_ident, size_t *ret_ident_num)
{
lcc_response_t res;
- size_t i;
int status;
lcc_identifier_t *ident;
}
ident_num = res.lines_num;
- ident = (lcc_identifier_t *) malloc (ident_num * sizeof (*ident));
+ ident = malloc (ident_num * sizeof (*ident));
if (ident == NULL)
{
lcc_response_free (&res);
return (-1);
}
- for (i = 0; i < res.lines_num; i++)
+ for (size_t i = 0; i < res.lines_num; i++)
{
char *time_str;
char *ident_str;
return (0);
} /* }}} int lcc_string_to_identifier */
-int lcc_identifier_compare (const lcc_identifier_t *i0, /* {{{ */
- const lcc_identifier_t *i1)
+int lcc_identifier_compare (const void *a, /* {{{ */
+ const void *b)
{
+ const lcc_identifier_t *i0 = a;
+ const lcc_identifier_t *i1 = b;
int status;
if ((i0 == NULL) && (i1 == NULL))
}
qsort (idents, idents_num, sizeof (*idents),
- (void *) lcc_identifier_compare);
+ lcc_identifier_compare);
return (0);
} /* }}} int lcc_sort_identifiers */
index 8e7f4b60acd5498dd4edb04da56e39f29d62b02b..47462a6ba7884b70385f45d1e275cfed064448e6 100644 (file)
/* Compares the identifiers "i0" and "i1" and returns less than zero or greater
* than zero if "i0" is smaller than or greater than "i1", respectively. If
* "i0" and "i1" are identical, zero is returned. */
-int lcc_identifier_compare (const lcc_identifier_t *i0,
- const lcc_identifier_t *i1);
+int lcc_identifier_compare (const void *i0,
+ const void *i1);
int lcc_sort_identifiers (lcc_connection_t *c,
lcc_identifier_t *idents, size_t idents_num);
index 049f7f0283fc16bf6f3baacba8c7cbb55c2b662c..64cf9c93bd26b821622e1a82fdbe7e3a2f8f194a 100644 (file)
lcc_network_t *lcc_network_create (void);
void lcc_network_destroy (lcc_network_t *net);
-/*
+/*
* Add servers
*/
lcc_server_t *lcc_server_create (lcc_network_t *net,
index 420471df577eb28aece3cc3770fca73ffce2faec..16293ca09c59a64973b497605d11d23166e7746f 100644 (file)
static int server_open_socket (lcc_server_t *srv) /* {{{ */
{
- struct addrinfo ai_hints = { 0 };
- struct addrinfo *ai_list = NULL;
- struct addrinfo *ai_ptr;
+ struct addrinfo *ai_list;
int status;
if (srv == NULL)
if (srv->fd >= 0)
server_close_socket (srv);
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_DGRAM;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_socktype = SOCK_DGRAM
+ };
status = getaddrinfo (srv->node, srv->service, &ai_hints, &ai_list);
if (status != 0)
return (status);
assert (ai_list != NULL);
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
srv->fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
if (srv->fd < 0)
static int server_send_buffer (lcc_server_t *srv) /* {{{ */
{
- char buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT];
+ char buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT] = { 0 };
size_t buffer_size;
int status;
return (status);
}
- memset (buffer, 0, sizeof (buffer));
buffer_size = sizeof (buffer);
status = lcc_network_buffer_finalize (srv->buffer);
{
lcc_network_t *net;
- net = malloc (sizeof (*net));
+ net = calloc (1, sizeof (*net));
if (net == NULL)
return (NULL);
- memset (net, 0, sizeof (*net));
net->servers = NULL;
if (service == NULL)
service = NET_DEFAULT_PORT;
- srv = malloc (sizeof (*srv));
+ srv = calloc (1, sizeof (*srv));
if (srv == NULL)
return (NULL);
- memset (srv, 0, sizeof (*srv));
srv->fd = -1;
srv->security_level = NONE;
int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ */
{
- int if_index;
+ unsigned int if_index;
int status;
if ((srv == NULL) || (interface == NULL))
@@ -415,18 +410,16 @@ int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ *
* index is preferred here, because of its similarity
* to the way IPv6 handles this. Unfortunately, it
* appears not to be portable. */
- struct ip_mreqn mreq;
-
- memset (&mreq, 0, sizeof (mreq));
- mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
- mreq.imr_address.s_addr = ntohl (INADDR_ANY);
- mreq.imr_ifindex = if_index;
+ struct ip_mreqn mreq = {
+ .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+ .imr_address.s_addr = ntohl (INADDR_ANY),
+ .imr_ifindex = (int) if_index
+ };
#else
- struct ip_mreq mreq;
-
- memset (&mreq, 0, sizeof (mreq));
- mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
- mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+ struct ip_mreq mreq = {
+ .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+ .imr_interface.s_addr = ntohl (INADDR_ANY)
+ };
#endif
status = setsockopt (srv->fd, IPPROTO_IP, IP_MULTICAST_IF,
@@ -456,8 +449,8 @@ int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ *
/* else: Not a multicast interface. */
#if defined(SO_BINDTODEVICE)
- status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE,
- interface, strlen (interface) + 1);
+ status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE, interface,
+ (socklen_t) (strlen (interface) + 1));
if (status != 0)
return (-1);
#endif
int lcc_network_values_send (lcc_network_t *net, /* {{{ */
const lcc_value_list_t *vl)
{
- lcc_server_t *srv;
-
if ((net == NULL) || (vl == NULL))
return (EINVAL);
- for (srv = net->servers; srv != NULL; srv = srv->next)
+ for (lcc_server_t *srv = net->servers; srv != NULL; srv = srv->next)
server_value_add (srv, vl);
return (0);
index 8d35d2031bf07f2608494056fccb24bc34a811e1..2c6277c856b24eb82dd319cf64a14c7798cad4d3 100644 (file)
#include <pthread.h>
#if HAVE_LIBGCRYPT
-# include <pthread.h>
# if defined __APPLE__
/* default xcode compiler throws warnings even when deprecated functionality
* is not used. -Werror breaks the build because of erroneous warnings.
value_t pkg_values[vl->values_len];
size_t offset;
- size_t i;
packet_len = sizeof (pkg_type) + sizeof (pkg_length)
+ sizeof (pkg_num_values)
pkg_length = htons ((uint16_t) packet_len);
pkg_num_values = htons ((uint16_t) vl->values_len);
- for (i = 0; i < vl->values_len; i++)
+ for (size_t i = 0; i < vl->values_len; i++)
{
pkg_values_types[i] = (uint8_t) vl->values_types[i];
switch (vl->values_types[i])
return (NULL);
}
- nb = malloc (sizeof (*nb));
+ nb = calloc (1, sizeof (*nb));
if (nb == NULL)
return (NULL);
- memset (nb, 0, sizeof (*nb));
nb->size = size;
- nb->buffer = malloc (nb->size);
+ nb->buffer = calloc (1, nb->size);
if (nb->buffer == NULL)
{
free (nb);
return (NULL);
}
- memset (nb->buffer, 0, nb->size);
nb->ptr = nb->buffer;
nb->free = nb->size;
uint16_t pkg_type = htons (TYPE_ENCR_AES256);
uint16_t pkg_length = 0; /* Filled in in finalize. */
uint16_t pkg_user_len = htons ((uint16_t) username_length);
- char hash[20];
+ /* Filled in in finalize. */
+ char hash[20] = { 0 };
nb->encr_header_len = username_length;
nb->encr_header_len += PART_ENCRYPTION_AES256_SIZE;
gcry_randomize ((void *) &nb->encr_iv, sizeof (nb->encr_iv),
GCRY_STRONG_RANDOM);
- /* Filled in in finalize. */
- memset (hash, 0, sizeof (hash));
-
ADD_STATIC (nb, pkg_type);
ADD_STATIC (nb, pkg_length);
ADD_STATIC (nb, pkg_user_len);
index b5162cc485c177c4833956c7c36b91db8253a985..5ac0ef34e6a14c1b22afbf9a9914ed480606234c 100644 (file)
-AUTOMAKE_OPTIONS = foreign no-dependencies
-
BUILT_SOURCES = parser.h
#CLEANFILES = parser.[ch] scanner.c
AM_YFLAGS = -d
index 5d2c5b2afa7a7907b6a2e3139fcf7357f563f0ae..d6f07446f9c604848787c184d28366db473a4cda 100644 (file)
--- a/src/liboconfig/oconfig.c
+++ b/src/liboconfig/oconfig.c
yyin = fd;
} /* void yyset_in */
-oconfig_item_t *oconfig_parse_fh (FILE *fh)
+static oconfig_item_t *oconfig_parse_fh (FILE *fh)
{
int status;
oconfig_item_t *ret;
if (NULL == c_file) {
status = snprintf (file, sizeof (file), "<fd#%d>", fileno (fh));
- if ((status < 0) || (status >= sizeof (file))) {
+ if ((status < 0) || (((size_t) status) >= sizeof (file))) {
c_file = "<unknown>";
}
else {
{
oconfig_item_t *ci_copy;
- ci_copy = (oconfig_item_t *) malloc (sizeof (*ci_copy));
+ ci_copy = calloc (1, sizeof (*ci_copy));
if (ci_copy == NULL)
{
- fprintf (stderr, "malloc failed.\n");
+ fprintf (stderr, "calloc failed.\n");
return (NULL);
}
- memset (ci_copy, 0, sizeof (*ci_copy));
ci_copy->values = NULL;
ci_copy->parent = NULL;
ci_copy->children = NULL;
if (ci_orig->values_num > 0) /* {{{ */
{
- int i;
-
- ci_copy->values = (oconfig_value_t *) calloc (ci_orig->values_num,
- sizeof (*ci_copy->values));
+ ci_copy->values = (oconfig_value_t *) calloc ((size_t) ci_orig->values_num,
+ sizeof (*ci_copy->values));
if (ci_copy->values == NULL)
{
fprintf (stderr, "calloc failed.\n");
}
ci_copy->values_num = ci_orig->values_num;
- for (i = 0; i < ci_copy->values_num; i++)
+ for (int i = 0; i < ci_copy->values_num; i++)
{
ci_copy->values[i].type = ci_orig->values[i].type;
if (ci_copy->values[i].type == OCONFIG_TYPE_STRING)
{
- ci_copy->values[i].value.string
- = strdup (ci_orig->values[i].value.string);
- if (ci_copy->values[i].value.string == NULL)
- {
- fprintf (stderr, "strdup failed.\n");
- oconfig_free (ci_copy);
- return (NULL);
- }
+ ci_copy->values[i].value.string = strdup (ci_orig->values[i].value.string);
+ if (ci_copy->values[i].value.string == NULL)
+ {
+ fprintf (stderr, "strdup failed.\n");
+ oconfig_free (ci_copy);
+ return (NULL);
+ }
}
else /* ci_copy->values[i].type != OCONFIG_TYPE_STRING) */
{
- ci_copy->values[i].value = ci_orig->values[i].value;
+ ci_copy->values[i].value = ci_orig->values[i].value;
}
}
} /* }}} if (ci_orig->values_num > 0) */
if (ci_orig->children_num > 0) /* {{{ */
{
- int i;
-
- ci_copy->children = (oconfig_item_t *) calloc (ci_orig->children_num,
- sizeof (*ci_copy->children));
+ ci_copy->children = (oconfig_item_t *) calloc ((size_t) ci_orig->children_num,
+ sizeof (*ci_copy->children));
if (ci_copy->children == NULL)
{
fprintf (stderr, "calloc failed.\n");
}
ci_copy->children_num = ci_orig->children_num;
- for (i = 0; i < ci_copy->children_num; i++)
+ for (int i = 0; i < ci_copy->children_num; i++)
{
oconfig_item_t *child;
-
+
child = oconfig_clone (ci_orig->children + i);
if (child == NULL)
{
static void oconfig_free_all (oconfig_item_t *ci)
{
- int i;
-
if (ci == NULL)
return;
if (ci->key != NULL)
free (ci->key);
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
if ((ci->values[i].type == OCONFIG_TYPE_STRING)
&& (NULL != ci->values[i].value.string))
free (ci->values[i].value.string);
if (ci->values != NULL)
free (ci->values);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
oconfig_free_all (ci->children + i);
if (ci->children != NULL)
{
oconfig_free_all (ci);
free (ci);
- ci = NULL;
}
/*
index 840137cc25a7f4a59f5bceee43856d257e7c7795..24045de0d4de9330051a270898fe2d4e1fc6bc55 100644 (file)
--- a/src/liboconfig/oconfig.h
+++ b/src/liboconfig/oconfig.h
/*
* Functions
*/
-oconfig_item_t *oconfig_parse_fh (FILE *fh);
oconfig_item_t *oconfig_parse_file (const char *file);
oconfig_item_t *oconfig_clone (const oconfig_item_t *ci);
index f0e886cc1a1e28ab5f1c277eb830c54896410d59..4a550b32a1c8e6fa9ad89ec338a1c11c282cd25d 100644 (file)
--- a/src/liboconfig/parser.y
+++ b/src/liboconfig/parser.y
entire_file:
statement_list
{
- ci_root = malloc (sizeof (oconfig_item_t));
- memset (ci_root, '\0', sizeof (oconfig_item_t));
+ ci_root = calloc (1, sizeof (*ci_root));
ci_root->children = $1.statement;
ci_root->children_num = $1.statement_num;
}
| /* epsilon */
{
- ci_root = malloc (sizeof (oconfig_item_t));
- memset (ci_root, '\0', sizeof (oconfig_item_t));
+ ci_root = calloc (1, sizeof (*ci_root));
ci_root->children = NULL;
ci_root->children_num = 0;
}
%%
static int yyerror (const char *s)
{
- char *text;
+ const char *text;
if (*yytext == '\n')
text = "<newline>";
{
char *ret = strdup (orig);
int len;
- int i;
if (ret == NULL)
return (NULL);
memmove (ret, ret + 1, len);
ret[len] = '\0';
- for (i = 0; i < len; i++)
+ for (int i = 0; i < len; i++)
{
if (ret[i] == '\\')
{
index 41d66438dd86e1176621034734d4666a29e0d773..485800317b57f7189b2ed80aed40e0034e00fae4 100644 (file)
--- a/src/liboconfig/scanner.l
+++ b/src/liboconfig/scanner.l
#include "aux_types.h"
#include "parser.h"
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+#endif
+
+
/* multiline string buffer */
static char *ml_buffer = NULL;
static int ml_pos = 0;
if (ml_free <= len) {
ml_len += len - ml_free + 1;
- ml_buffer = (char *)realloc (ml_buffer, ml_len);
+ ml_buffer = realloc (ml_buffer, ml_len);
if (NULL == ml_buffer)
YY_FATAL_ERROR ("out of dynamic memory in ml_append");
}
return;
} /* ml_append */
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
diff --git a/src/load.c b/src/load.c
index 18b5f8e87457b2f9dbdc9e723e9f6b6da9967843..cc3be37e03fa4e508ccd3f067f109fbef8dd88cf 100644 (file)
--- a/src/load.c
+++ b/src/load.c
#define _BSD_SOURCE
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
diff --git a/src/log_logstash.c b/src/log_logstash.c
index 2d5f6203802852b0bf7174eaf0ab8c22bdf237a9..08868409d2b575edfd080f0cf81ffb8d1ada5740 100644 (file)
--- a/src/log_logstash.c
+++ b/src/log_logstash.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <sys/types.h>
-#include <pthread.h>
#include <yajl/yajl_common.h>
#include <yajl/yajl_gen.h>
#if HAVE_YAJL_YAJL_VERSION_H
if (0 == strcasecmp (key, "LogLevel")) {
log_level = parse_log_severity(value);
- if (log_level < 0) {
- log_level = LOG_INFO;
- ERROR("log_logstash: invalid loglevel [%s] defaulting to 'info'",
- value);
- return 1;
- }
+ if (log_level < 0) {
+ log_level = LOG_INFO;
+ ERROR("log_logstash: invalid loglevel [%s] defaulting to 'info'",
+ value);
+ return 1;
+ }
}
else if (0 == strcasecmp (key, "File")) {
sfree (log_file);
diff --git a/src/logfile.c b/src/logfile.c
index 11797182639e35902be3e431022f667d9eb99839..d18a5365556a67f9cd0be54595d3cfa3d0883588 100644 (file)
--- a/src/logfile.c
+++ b/src/logfile.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include <pthread.h>
-
#define DEFAULT_LOGFILE LOCALSTATEDIR"/log/collectd.log"
#if COLLECT_DEBUG
diff --git a/src/lpar.c b/src/lpar.c
index 4d534476f62c76754433b2c73d313967595e5843..5b0bd13d0cd1ea5881d2da1477311189664dc3e2 100644 (file)
--- a/src/lpar.c
+++ b/src/lpar.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
diff --git a/src/lua.c b/src/lua.c
--- /dev/null
+++ b/src/lua.c
@@ -0,0 +1,593 @@
+/**
+ * collectd - src/lua.c
+ * Copyright (C) 2010 Julien Ammous
+ * Copyright (C) 2010 Florian Forster
+ * Copyright (C) 2016 Ruben Kerkhof
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Julien Ammous
+ * Florian Forster <octo at collectd.org>
+ * Ruben Kerkhof <ruben at rubenkerkhof.com>
+ **/
+
+/* <lua5.1/luaconf.h> defines a macro using "sprintf". Although not used here,
+ * GCC will complain about the macro definition. */
+#define DONT_POISON_SPRINTF_YET
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+/* Include the Lua API header files. */
+#include "utils_lua.h"
+#include <lauxlib.h>
+#include <lua.h>
+#include <lualib.h>
+
+#include <pthread.h>
+
+#if COLLECT_DEBUG && __GNUC__
+#undef sprintf
+#pragma GCC poison sprintf
+#endif
+
+typedef struct lua_script_s {
+ char *script_path;
+ lua_State *lua_state;
+ struct lua_script_s *next;
+} lua_script_t;
+
+typedef struct {
+ lua_State *lua_state;
+ const char *lua_function_name;
+ pthread_mutex_t lock;
+ int callback_id;
+} clua_callback_data_t;
+
+static char base_path[PATH_MAX];
+static lua_script_t *scripts;
+
+static int clua_store_callback(lua_State *L, int idx) /* {{{ */
+{
+ /* Copy the function pointer */
+ lua_pushvalue(L, idx);
+
+ return luaL_ref(L, LUA_REGISTRYINDEX);
+} /* }}} int clua_store_callback */
+
+static int clua_load_callback(lua_State *L, int callback_ref) /* {{{ */
+{
+ lua_rawgeti(L, LUA_REGISTRYINDEX, callback_ref);
+
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 1);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int clua_load_callback */
+
+/* Store the threads in a global variable so they are not cleaned up by the
+ * garbage collector. */
+static int clua_store_thread(lua_State *L, int idx) /* {{{ */
+{
+ if (idx < 0)
+ idx += lua_gettop(L) + 1;
+
+ /* Copy the thread pointer */
+ lua_pushvalue(L, idx); /* +1 = 3 */
+ if (!lua_isthread(L, -1)) {
+ lua_pop(L, 3); /* -3 = 0 */
+ return (-1);
+ }
+
+ luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pop(L, 1); /* -1 = 0 */
+ return (0);
+} /* }}} int clua_store_thread */
+
+static int clua_read(user_data_t *ud) /* {{{ */
+{
+ clua_callback_data_t *cb = ud->data;
+
+ pthread_mutex_lock(&cb->lock);
+
+ lua_State *L = cb->lua_state;
+
+ int status = clua_load_callback(L, cb->callback_id);
+ if (status != 0) {
+ ERROR("Lua plugin: Unable to load callback \"%s\" (id %i).",
+ cb->lua_function_name, cb->callback_id);
+ pthread_mutex_unlock(&cb->lock);
+ return (-1);
+ }
+ /* +1 = 1 */
+
+ status = lua_pcall(L, 0, 1, 0);
+ if (status != 0) {
+ const char *errmsg = lua_tostring(L, -1);
+ if (errmsg == NULL)
+ ERROR("Lua plugin: Calling a read callback failed. "
+ "In addition, retrieving the error message failed.");
+ else
+ ERROR("Lua plugin: Calling a read callback failed: %s", errmsg);
+ lua_pop(L, 1);
+ pthread_mutex_unlock(&cb->lock);
+ return (-1);
+ }
+
+ if (!lua_isnumber(L, -1)) {
+ ERROR("Lua plugin: Read function \"%s\" (id %i) did not return a numeric "
+ "status.",
+ cb->lua_function_name, cb->callback_id);
+ status = -1;
+ } else {
+ status = (int)lua_tointeger(L, -1);
+ }
+
+ /* pop return value and function */
+ lua_pop(L, 1); /* -1 = 0 */
+
+ pthread_mutex_unlock(&cb->lock);
+ return (status);
+} /* }}} int clua_read */
+
+static int clua_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */
+ user_data_t *ud) {
+ clua_callback_data_t *cb = ud->data;
+
+ pthread_mutex_lock(&cb->lock);
+
+ lua_State *L = cb->lua_state;
+
+ int status = clua_load_callback(L, cb->callback_id);
+ if (status != 0) {
+ ERROR("Lua plugin: Unable to load callback \"%s\" (id %i).",
+ cb->lua_function_name, cb->callback_id);
+ pthread_mutex_unlock(&cb->lock);
+ return (-1);
+ }
+ /* +1 = 1 */
+
+ status = luaC_pushvaluelist(L, ds, vl);
+ if (status != 0) {
+ lua_pop(L, 1); /* -1 = 0 */
+ pthread_mutex_unlock(&cb->lock);
+ ERROR("Lua plugin: luaC_pushvaluelist failed.");
+ return (-1);
+ }
+ /* +1 = 2 */
+
+ status = lua_pcall(L, 1, 1, 0); /* -2+1 = 1 */
+ if (status != 0) {
+ const char *errmsg = lua_tostring(L, -1);
+ if (errmsg == NULL)
+ ERROR("Lua plugin: Calling the write callback failed. "
+ "In addition, retrieving the error message failed.");
+ else
+ ERROR("Lua plugin: Calling the write callback failed:\n%s", errmsg);
+ lua_pop(L, 1); /* -1 = 0 */
+ pthread_mutex_unlock(&cb->lock);
+ return (-1);
+ }
+
+ if (!lua_isnumber(L, -1)) {
+ ERROR("Lua plugin: Write function \"%s\" (id %i) did not return a numeric "
+ "value.",
+ cb->lua_function_name, cb->callback_id);
+ status = -1;
+ } else {
+ status = (int)lua_tointeger(L, -1);
+ }
+
+ lua_pop(L, 1); /* -1 = 0 */
+ pthread_mutex_unlock(&cb->lock);
+ return (status);
+} /* }}} int clua_write */
+
+/*
+ * Exported functions
+ */
+
+static int lua_cb_log_debug(lua_State *L) /* {{{ */
+{
+ const char *msg = luaL_checkstring(L, 1);
+ plugin_log(LOG_DEBUG, "%s", msg);
+ return 0;
+} /* }}} int lua_cb_log_debug */
+
+static int lua_cb_log_error(lua_State *L) /* {{{ */
+{
+ const char *msg = luaL_checkstring(L, 1);
+ plugin_log(LOG_ERR, "%s", msg);
+ return 0;
+} /* }}} int lua_cb_log_error */
+
+static int lua_cb_log_info(lua_State *L) /* {{{ */
+{
+ const char *msg = luaL_checkstring(L, 1);
+ plugin_log(LOG_INFO, "%s", msg);
+ return 0;
+} /* }}} int lua_cb_log_info */
+
+static int lua_cb_log_notice(lua_State *L) /* {{{ */
+{
+ const char *msg = luaL_checkstring(L, 1);
+ plugin_log(LOG_NOTICE, "%s", msg);
+ return 0;
+} /* }}} int lua_cb_log_notice */
+
+static int lua_cb_log_warning(lua_State *L) /* {{{ */
+{
+ const char *msg = luaL_checkstring(L, 1);
+ plugin_log(LOG_WARNING, "%s", msg);
+ return 0;
+} /* }}} int lua_cb_log_warning */
+
+static int lua_cb_dispatch_values(lua_State *L) /* {{{ */
+{
+ int nargs = lua_gettop(L);
+
+ if (nargs != 1)
+ return luaL_error(L, "Invalid number of arguments (%d != 1)", nargs);
+
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ value_list_t *vl = luaC_tovaluelist(L, -1);
+ if (vl == NULL)
+ return luaL_error(L, "%s", "luaC_tovaluelist failed");
+
+#if COLLECT_DEBUG
+ char identifier[6 * DATA_MAX_NAME_LEN];
+ FORMAT_VL(identifier, sizeof(identifier), vl);
+
+ DEBUG("Lua plugin: collectd.dispatch_values(): Received value list \"%s\", "
+ "time %.3f, interval %.3f.",
+ identifier, CDTIME_T_TO_DOUBLE(vl->time),
+ CDTIME_T_TO_DOUBLE(vl->interval));
+#endif
+
+ plugin_dispatch_values(vl);
+
+ sfree(vl->values);
+ sfree(vl);
+ return 0;
+} /* }}} lua_cb_dispatch_values */
+
+static int lua_cb_register_read(lua_State *L) /* {{{ */
+{
+ int nargs = lua_gettop(L);
+
+ if (nargs != 1)
+ return luaL_error(L, "Invalid number of arguments (%d != 1)", nargs);
+
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+
+ char function_name[DATA_MAX_NAME_LEN];
+ ssnprintf(function_name, sizeof(function_name), "lua/%s", lua_tostring(L, 1));
+
+ int callback_id = clua_store_callback(L, 1);
+ if (callback_id < 0)
+ return luaL_error(L, "%s", "Storing callback function failed");
+
+ lua_State *thread = lua_newthread(L);
+ if (thread == NULL)
+ return luaL_error(L, "%s", "lua_newthread failed");
+ clua_store_thread(L, -1);
+ lua_pop(L, 1);
+
+ clua_callback_data_t *cb = calloc(1, sizeof(*cb));
+ if (cb == NULL)
+ return luaL_error(L, "%s", "calloc failed");
+
+ cb->lua_state = thread;
+ cb->callback_id = callback_id;
+ cb->lua_function_name = strdup(function_name);
+ pthread_mutex_init(&cb->lock, NULL);
+
+ user_data_t ud = {
+ .data = cb
+ };
+
+ int status = plugin_register_complex_read(/* group = */ "lua",
+ /* name = */ function_name,
+ /* callback = */ clua_read,
+ /* interval = */ 0,
+ /* user_data = */ &ud);
+
+ if (status != 0)
+ return luaL_error(L, "%s", "plugin_register_complex_read failed");
+ return 0;
+} /* }}} int lua_cb_register_read */
+
+static int lua_cb_register_write(lua_State *L) /* {{{ */
+{
+ int nargs = lua_gettop(L);
+
+ if (nargs != 1)
+ return luaL_error(L, "Invalid number of arguments (%d != 1)", nargs);
+
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+
+ char function_name[DATA_MAX_NAME_LEN] = "";
+ ssnprintf(function_name, sizeof(function_name), "lua/%s", lua_tostring(L, 1));
+
+ int callback_id = clua_store_callback(L, 1);
+ if (callback_id < 0)
+ return luaL_error(L, "%s", "Storing callback function failed");
+
+ lua_State *thread = lua_newthread(L);
+ if (thread == NULL)
+ return luaL_error(L, "%s", "lua_newthread failed");
+ clua_store_thread(L, -1);
+ lua_pop(L, 1);
+
+ clua_callback_data_t *cb = calloc(1, sizeof(*cb));
+ if (cb == NULL)
+ return luaL_error(L, "%s", "calloc failed");
+
+ cb->lua_state = thread;
+ cb->callback_id = callback_id;
+ cb->lua_function_name = strdup(function_name);
+ pthread_mutex_init(&cb->lock, NULL);
+
+ user_data_t ud = {
+ .data = cb
+ };
+
+ int status = plugin_register_write(/* name = */ function_name,
+ /* callback = */ clua_write,
+ /* user_data = */ &ud);
+
+ if (status != 0)
+ return luaL_error(L, "%s", "plugin_register_write failed");
+ return 0;
+} /* }}} int lua_cb_register_write */
+
+static const luaL_Reg collectdlib[] = {
+ {"log_debug", lua_cb_log_debug},
+ {"log_error", lua_cb_log_error},
+ {"log_info", lua_cb_log_info},
+ {"log_notice", lua_cb_log_notice},
+ {"log_warning", lua_cb_log_warning},
+ {"dispatch_values", lua_cb_dispatch_values},
+ {"register_read", lua_cb_register_read},
+ {"register_write", lua_cb_register_write},
+ {NULL, NULL}
+};
+
+static int open_collectd(lua_State *L) /* {{{ */
+{
+#if LUA_VERSION_NUM < 502
+ luaL_register(L, "collectd", collectdlib);
+#else
+ luaL_newlib(L, collectdlib);
+#endif
+ return 1;
+} /* }}} */
+
+static void lua_script_free(lua_script_t *script) /* {{{ */
+{
+ if (script == NULL)
+ return;
+
+ lua_script_t *next = script->next;
+
+ if (script->lua_state != NULL) {
+ lua_close(script->lua_state);
+ script->lua_state = NULL;
+ }
+
+ sfree(script->script_path);
+ sfree(script);
+
+ lua_script_free(next);
+} /* }}} void lua_script_free */
+
+static int lua_script_init(lua_script_t *script) /* {{{ */
+{
+ memset(script, 0, sizeof(*script));
+
+ /* initialize the lua context */
+ script->lua_state = luaL_newstate();
+ if (script->lua_state == NULL) {
+ ERROR("Lua plugin: luaL_newstate() failed.");
+ return (-1);
+ }
+
+ /* Open up all the standard Lua libraries. */
+ luaL_openlibs(script->lua_state);
+
+ /* Load the 'collectd' library */
+#if LUA_VERSION_NUM < 502
+ lua_pushcfunction(script->lua_state, open_collectd);
+ lua_pushstring(script->lua_state, "collectd");
+ lua_call(script->lua_state, 1, 0);
+#else
+ luaL_requiref(script->lua_state, "collectd", open_collectd, 1);
+ lua_pop(script->lua_state, 1);
+#endif
+
+ /* Prepend BasePath to package.path */
+ if (base_path[0] != '\0') {
+ lua_getglobal(script->lua_state, "package");
+ lua_getfield(script->lua_state, -1, "path");
+
+ const char *cur_path = lua_tostring(script->lua_state, -1);
+ char *new_path = ssnprintf_alloc("%s/?.lua;%s", base_path, cur_path);
+
+ lua_pop(script->lua_state, 1);
+ lua_pushstring(script->lua_state, new_path);
+
+ free(new_path);
+
+ lua_setfield(script->lua_state, -2, "path");
+ lua_pop(script->lua_state, 1);
+ }
+
+ return (0);
+} /* }}} int lua_script_init */
+
+static int lua_script_load(const char *script_path) /* {{{ */
+{
+ lua_script_t *script = malloc(sizeof(*script));
+ if (script == NULL) {
+ ERROR("Lua plugin: malloc failed.");
+ return (-1);
+ }
+
+ int status = lua_script_init(script);
+ if (status != 0) {
+ lua_script_free(script);
+ return (status);
+ }
+
+ script->script_path = strdup(script_path);
+ if (script->script_path == NULL) {
+ ERROR("Lua plugin: strdup failed.");
+ lua_script_free(script);
+ return (-1);
+ }
+
+ status = luaL_loadfile(script->lua_state, script->script_path);
+ if (status != 0) {
+ ERROR("Lua plugin: luaL_loadfile failed: %s",
+ lua_tostring(script->lua_state, -1));
+ lua_pop(script->lua_state, 1);
+ lua_script_free(script);
+ return (-1);
+ }
+
+ status = lua_pcall(script->lua_state,
+ /* nargs = */ 0,
+ /* nresults = */ LUA_MULTRET,
+ /* errfunc = */ 0);
+ if (status != 0) {
+ const char *errmsg = lua_tostring(script->lua_state, -1);
+
+ if (errmsg == NULL)
+ ERROR("Lua plugin: lua_pcall failed with status %i. "
+ "In addition, no error message could be retrieved from the stack.",
+ status);
+ else
+ ERROR("Lua plugin: Executing script \"%s\" failed:\n%s",
+ script->script_path, errmsg);
+
+ lua_script_free(script);
+ return (-1);
+ }
+
+ /* Append this script to the global list of scripts. */
+ if (scripts) {
+ lua_script_t *last = scripts;
+ while (last->next)
+ last = last->next;
+
+ last->next = script;
+ } else {
+ scripts = script;
+ }
+
+ return (0);
+} /* }}} int lua_script_load */
+
+static int lua_config_base_path(const oconfig_item_t *ci) /* {{{ */
+{
+ int status = cf_util_get_string_buffer(ci, base_path, sizeof(base_path));
+ if (status != 0)
+ return (status);
+
+ size_t len = strlen(base_path);
+ while ((len > 0) && (base_path[len - 1] == '/')) {
+ len--;
+ base_path[len] = '\0';
+ }
+
+ DEBUG("Lua plugin: base_path = \"%s\";", base_path);
+
+ return (0);
+} /* }}} int lua_config_base_path */
+
+static int lua_config_script(const oconfig_item_t *ci) /* {{{ */
+{
+ char rel_path[PATH_MAX];
+
+ int status = cf_util_get_string_buffer(ci, rel_path, sizeof(rel_path));
+ if (status != 0)
+ return (status);
+
+ char abs_path[PATH_MAX];
+
+ if (base_path[0] == '\0')
+ sstrncpy(abs_path, rel_path, sizeof(abs_path));
+ else
+ ssnprintf(abs_path, sizeof(abs_path), "%s/%s", base_path, rel_path);
+
+ DEBUG("Lua plugin: abs_path = \"%s\";", abs_path);
+
+ status = lua_script_load(abs_path);
+ if (status != 0)
+ return (status);
+
+ INFO("Lua plugin: File \"%s\" loaded successfully", abs_path);
+
+ return 0;
+} /* }}} int lua_config_script */
+
+/*
+ * <Plugin lua>
+ * BasePath "/"
+ * Script "script1.lua"
+ * Script "script2.lua"
+ * </Plugin>
+ */
+static int lua_config(oconfig_item_t *ci) /* {{{ */
+{
+ int status = 0;
+ for (int i = 0; i < ci->children_num; i++) {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp("BasePath", child->key) == 0) {
+ status = lua_config_base_path(child);
+ } else if (strcasecmp("Script", child->key) == 0) {
+ status = lua_config_script(child);
+ } else {
+ ERROR("Lua plugin: Option `%s' is not allowed here.", child->key);
+ status = 1;
+ }
+ }
+
+ return status;
+} /* }}} int lua_config */
+
+static int lua_shutdown(void) /* {{{ */
+{
+ lua_script_free(scripts);
+
+ return (0);
+} /* }}} int lua_shutdown */
+
+void module_register(void) {
+ plugin_register_complex_config("lua", lua_config);
+ plugin_register_shutdown("lua", lua_shutdown);
+}
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/lvm.c b/src/lvm.c
index 9e245423fef2c829d842619a3a77ee8213864ae4..6b9a0317c2124eb78fe4c81ed485a319b85f8336 100644 (file)
--- a/src/lvm.c
+++ b/src/lvm.c
#include <lvm2app.h>
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
diff --git a/src/madwifi.c b/src/madwifi.c
index 7987378ed4a857e5674080b2d540bfdfbc11b6f6..053bd7fa2c7a47851c33ae1e19e5c5b38d058132 100644 (file)
--- a/src/madwifi.c
+++ b/src/madwifi.c
/**
- * There are several data streams provided by Madwifi plugin, some are
+ * There are several data streams provided by Madwifi plugin, some are
* connected to network interface, some are connected to each node
* associated to that interface. Nodes represents other sides in
* wireless communication, for example on network interface in AP mode,
* node_stat Node statistic counters
*
* Both statistic counters have type instances for each counter returned
- * by Madwifi. See madwifi.h for content of ieee80211_nodestats,
+ * by Madwifi. See madwifi.h for content of ieee80211_nodestats,
* ieee80211_stats and ath_stats structures. Type instances use the same
* name as fields in these structures (like ns_rx_dup). Some fields are
* not reported, because they are not counters (like ns_tx_deauth_code
* or ast_tx_rssi). Fields ns_rx_bytes and ns_tx_bytes are reported as
* node_octets data stream instead of type instance of node_stat.
* Statistics are not logged when they are zero.
- *
+ *
* There are two sets of these counters - the first 'WatchList' is a
* set of counters that are individually logged. The second 'MiscList'
* is a set of counters that are summed together and the sum is logged.
- * By default, the most important statistics are in the WatchList and
+ * By default, the most important statistics are in the WatchList and
* many error statistics are in MiscList. There are also many statistics
* that are not in any of these sets, so they are not monitored by default.
* It is possible to alter these lists using configuration options:
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_ignorelist.h"
#include <dirent.h>
#include <sys/ioctl.h>
-#include <sys/socket.h>
#if !KERNEL_LINUX
# error "No applicable input method."
static inline int item_watched(int i)
{
assert (i >= 0);
- assert (i < ((STATIC_ARRAY_SIZE (watch_items) + 1) * 32));
+ assert ((size_t) i < (STATIC_ARRAY_SIZE (watch_items) * 32));
return watch_items[i / 32] & FLAG (i);
}
static inline int item_summed(int i)
{
assert (i >= 0);
- assert (i < ((STATIC_ARRAY_SIZE (misc_items) + 1) * 32));
+ assert ((size_t) i < (STATIC_ARRAY_SIZE (misc_items) * 32));
return misc_items[i / 32] & FLAG (i);
}
static inline void watchlist_add (uint32_t *wl, int item)
{
assert (item >= 0);
- assert (item < ((WL_LEN + 1) * 32));
+ assert (item < WL_LEN * 32);
wl[item / 32] |= FLAG (item);
}
static inline void watchlist_remove (uint32_t *wl, int item)
{
assert (item >= 0);
- assert (item < ((WL_LEN + 1) * 32));
+ assert (item < WL_LEN * 32);
wl[item / 32] &= ~FLAG (item);
}
static inline void watchlist_set (uint32_t *wl, uint32_t val)
{
- int i;
- for (i = 0; i < WL_LEN; i++)
+ for (int i = 0; i < WL_LEN; i++)
wl[i] = val;
}
static int watchitem_find (const char *name)
{
int max = STATIC_ARRAY_SIZE (specs);
- int i;
- for (i = 0; i < max; i++)
+ for (int i = 0; i < max; i++)
if (strcasecmp (name, specs[i].name) == 0)
return i;
static int madwifi_real_init (void)
{
- int max = STATIC_ARRAY_SIZE (specs);
- int i;
+ size_t max = STATIC_ARRAY_SIZE (specs);
- for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
bounds[i] = 0;
watchlist_set(watch_items, 0);
watchlist_set(misc_items, 0);
- for (i = 0; i < max; i++)
+ for (size_t i = 0; i < max; i++)
{
bounds[specs[i].flags & SRC_MASK] = i;
misc_items[i / 32] |= FLAG (i);
}
- for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
bounds[i]++;
return (0);
u_int32_t *vals, int vals_num)
{
char ti2[16];
- int i;
- for (i = 0; i < vals_num; i++)
+ for (int i = 0; i < vals_num; i++)
{
if (vals[i] == 0)
continue;
@@ -615,12 +610,11 @@ process_stat_struct (int which, const void *ptr, const char *dev, const char *ma
const char *type_name, const char *misc_name)
{
uint32_t misc = 0;
- int i;
assert (which >= 1);
- assert (which < STATIC_ARRAY_SIZE (bounds));
+ assert (((size_t) which) < STATIC_ARRAY_SIZE (bounds));
- for (i = bounds[which - 1]; i < bounds[which]; i++)
+ for (int i = bounds[which - 1]; i < bounds[which]; i++)
{
uint32_t val = *(uint32_t *)(((char *) ptr) + specs[i].offset) ;
@@ -630,7 +624,7 @@ process_stat_struct (int which, const void *ptr, const char *dev, const char *ma
if (item_summed (i))
misc += val;
}
-
+
if (misc != 0)
submit_derive (dev, type_name, misc_name, mac, misc);
static int
process_station (int sk, const char *dev, struct ieee80211req_sta_info *si)
{
- struct iwreq iwr;
static char mac[DATA_MAX_NAME_LEN];
struct ieee80211req_sta_stats stats;
const struct ieee80211_nodestats *ns = &stats.is_stats;
if (item_watched (STAT_NODE_RSSI))
submit_gauge (dev, "node_rssi", mac, NULL, si->isi_rssi);
- memset (&iwr, 0, sizeof (iwr));
+ struct iwreq iwr = {
+ .u.data.pointer = (void *) &stats,
+ .u.data.length = sizeof (stats)
+ };
sstrncpy(iwr.ifr_name, dev, sizeof (iwr.ifr_name));
- iwr.u.data.pointer = (void *) &stats;
- iwr.u.data.length = sizeof (stats);
+
memcpy(stats.is_u.macaddr, si->isi_macaddr, IEEE80211_ADDR_LEN);
status = ioctl(sk, IEEE80211_IOCTL_STA_STATS, &iwr);
if (status < 0)
static int
process_stations (int sk, const char *dev)
{
- uint8_t buf[24*1024];
- struct iwreq iwr;
+ uint8_t buf[24*1024] = { 0 };
uint8_t *cp;
- int len, nodes;
+ int nodes;
+ size_t len;
int status;
- memset (&iwr, 0, sizeof (iwr));
+ struct iwreq iwr = {
+ .u.data.pointer = (void *) buf,
+ .u.data.length = sizeof (buf)
+ };
sstrncpy (iwr.ifr_name, dev, sizeof (iwr.ifr_name));
- iwr.u.data.pointer = (void *) buf;
- iwr.u.data.length = sizeof (buf);
status = ioctl (sk, IEEE80211_IOCTL_STA_INFO, &iwr);
if (status < 0)
int status;
int num_success;
int num_fail;
-
+
if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
{
WARNING ("madwifi plugin: opening /proc/net/dev failed");
/* procfs iteration is not safe because it does not check whether given
interface is madwifi interface and there are private ioctls used, which
- may do something completely different on non-madwifi devices.
+ may do something completely different on non-madwifi devices.
Therefore, it is not used unless explicitly enabled (and should be used
together with ignorelist). */
index abde2b3495f818bf25b3188b4dadfd090210d6c9..80a29ac7b467db7f1f25f842b893011e2bf526aa 100644 (file)
/**
* collectd - src/match_empty_counter.c
- * Copyright (C) 2009 Florian Forster
+ * Copyright (C) 2009-2016 Florian Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
**/
#include "collectd.h"
+
#include "common.h"
-#include "utils_cache.h"
#include "filter_chain.h"
-/*
- * private data types
- */
-struct mec_match_s;
-typedef struct mec_match_s mec_match_t;
-struct mec_match_s
-{
- int dummy;
-};
-
/*
* internal helper functions
*/
static int mec_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
{
- mec_match_t *m;
-
- m = (mec_match_t *) malloc (sizeof (*m));
- if (m == NULL)
- {
- ERROR ("mec_create: malloc failed.");
- return (-ENOMEM);
- }
- memset (m, 0, sizeof (*m));
-
if (ci->children_num != 0)
{
ERROR ("empty_counter match: This match does not take any additional "
"configuration.");
}
- *user_data = m;
+ *user_data = NULL;
return (0);
} /* }}} int mec_create */
-static int mec_destroy (void **user_data) /* {{{ */
+static int mec_destroy (__attribute__((unused)) void **user_data) /* {{{ */
{
- if (user_data != NULL)
- {
- sfree (*user_data);
- }
-
return (0);
} /* }}} int mec_destroy */
-static int mec_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+static int mec_match (__attribute__((unused)) const data_set_t *ds, /* {{{ */
const value_list_t *vl,
- notification_meta_t __attribute__((unused)) **meta, void **user_data)
+ __attribute__((unused)) notification_meta_t **meta,
+ __attribute__((unused)) void **user_data)
{
- int num_counters;
- int num_empty;
- int i;
-
- if ((user_data == NULL) || (*user_data == NULL))
- return (-1);
+ int num_counters = 0;
+ int num_empty = 0;
-
- num_counters = 0;
- num_empty = 0;
-
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
- if (ds->ds[i].type != DS_TYPE_COUNTER)
+ if ((ds->ds[i].type != DS_TYPE_DERIVE)
+ && (ds->ds[i].type != DS_TYPE_COUNTER))
continue;
num_counters++;
- if (vl->values[i].counter == 0)
+ if (((ds->ds[i].type == DS_TYPE_DERIVE) && (vl->values[i].derive == 0))
+ || ((ds->ds[i].type == DS_TYPE_COUNTER) && (vl->values[i].counter == 0)))
num_empty++;
}
- if (num_counters == 0)
- return (FC_MATCH_NO_MATCH);
- else if (num_counters == num_empty)
+ if ((num_counters != 0) && (num_counters == num_empty))
return (FC_MATCH_MATCHES);
- else
- return (FC_MATCH_NO_MATCH);
+
+ return (FC_MATCH_NO_MATCH);
} /* }}} int mec_match */
void module_register (void)
{
- match_proc_t mproc;
-
- memset (&mproc, 0, sizeof (mproc));
- mproc.create = mec_create;
- mproc.destroy = mec_destroy;
- mproc.match = mec_match;
- fc_register_match ("empty_counter", mproc);
+ fc_register_match ("empty_counter", (match_proc_t) {
+ .create = mec_create,
+ .destroy = mec_destroy,
+ .match = mec_match,
+ });
} /* module_register */
/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
diff --git a/src/match_hashed.c b/src/match_hashed.c
index ba0c47c3f30275ce422f30b6fa717b0bb0d761cf..c4983c2ed056a0a455dc38131a3174876c1fb085 100644 (file)
--- a/src/match_hashed.c
+++ b/src/match_hashed.c
**/
#include "collectd.h"
+
#include "common.h"
-#include "utils_cache.h"
#include "filter_chain.h"
/*
static int mh_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
{
mh_match_t *m;
- int i;
- m = (mh_match_t *) malloc (sizeof (*m));
+ m = calloc (1, sizeof (*m));
if (m == NULL)
{
- ERROR ("mh_create: malloc failed.");
+ ERROR ("mh_create: calloc failed.");
return (-ENOMEM);
}
- memset (m, 0, sizeof (*m));
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
{
mh_match_t *m;
uint32_t hash_val;
- const char *host_ptr;
- size_t i;
if ((user_data == NULL) || (*user_data == NULL))
return (-1);
hash_val = 0;
- for (host_ptr = vl->host; *host_ptr != 0; host_ptr++)
+ for (const char *host_ptr = vl->host; *host_ptr != 0; host_ptr++)
{
/* 2184401929 is some appropriately sized prime number. */
hash_val = (hash_val * UINT32_C (2184401929)) + ((uint32_t) *host_ptr);
}
DEBUG ("hashed match: host = %s; hash_val = %"PRIu32";", vl->host, hash_val);
- for (i = 0; i < m->matches_num; i++)
+ for (size_t i = 0; i < m->matches_num; i++)
if ((hash_val % m->matches[i].total) == m->matches[i].match)
return (FC_MATCH_MATCHES);
void module_register (void)
{
- match_proc_t mproc;
+ match_proc_t mproc = { 0 };
- memset (&mproc, 0, sizeof (mproc));
mproc.create = mh_create;
mproc.destroy = mh_destroy;
mproc.match = mh_match;
diff --git a/src/match_regex.c b/src/match_regex.c
index 4fa6ce78d5d0c0007629a98e43fe4c5b3fbc2973..cd6301673a1a3673b8912375554da3a32bfd8bb1 100644 (file)
--- a/src/match_regex.c
+++ b/src/match_regex.c
*/
#include "collectd.h"
+
#include "filter_chain.h"
#include <sys/types.h>
static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */
const char *string)
{
- mr_regex_t *re;
-
if (re_head == NULL)
return (FC_MATCH_MATCHES);
- for (re = re_head; re != NULL; re = re->next)
+ for (mr_regex_t *re = re_head; re != NULL; re = re->next)
{
int status;
return (-1);
}
- re = (mr_regex_t *) malloc (sizeof (*re));
+ re = calloc (1, sizeof (*re));
if (re == NULL)
{
- log_err ("mr_config_add_regex: malloc failed.");
+ log_err ("mr_config_add_regex: calloc failed.");
return (-1);
}
- memset (re, 0, sizeof (*re));
re->next = NULL;
re->re_str = strdup (ci->values[0].value.string);
char errmsg[1024];
regerror (status, &re->re, errmsg, sizeof (errmsg));
errmsg[sizeof (errmsg) - 1] = 0;
- log_err ("Compiling regex `%s' for `%s' failed: %s.",
+ log_err ("Compiling regex `%s' for `%s' failed: %s.",
re->re_str, ci->key, errmsg);
free (re->re_str);
free (re);
{
mr_match_t *m;
int status;
- int i;
- m = (mr_match_t *) malloc (sizeof (*m));
+ m = calloc (1, sizeof (*m));
if (m == NULL)
{
- log_err ("mr_create: malloc failed.");
+ log_err ("mr_create: calloc failed.");
return (-ENOMEM);
}
- memset (m, 0, sizeof (*m));
-
+
m->invert = 0;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
void module_register (void)
{
- match_proc_t mproc;
+ match_proc_t mproc = { 0 };
- memset (&mproc, 0, sizeof (mproc));
mproc.create = mr_create;
mproc.destroy = mr_destroy;
mproc.match = mr_match;
diff --git a/src/match_timediff.c b/src/match_timediff.c
index 996201adfab746f28883865b05f6932572e756ce..00fdd0c1971bb4d044afc293d1d21d1e6a904e63 100644 (file)
--- a/src/match_timediff.c
+++ b/src/match_timediff.c
**/
#include "collectd.h"
+
#include "common.h"
-#include "utils_cache.h"
#include "filter_chain.h"
#define SATISFY_ALL 0
{
mt_match_t *m;
int status;
- int i;
- m = (mt_match_t *) malloc (sizeof (*m));
+ m = calloc (1, sizeof (*m));
if (m == NULL)
{
- ERROR ("mt_create: malloc failed.");
+ ERROR ("mt_create: calloc failed.");
return (-ENOMEM);
}
- memset (m, 0, sizeof (*m));
m->future = 0;
m->past = 0;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
void module_register (void)
{
- match_proc_t mproc;
+ match_proc_t mproc = { 0 };
- memset (&mproc, 0, sizeof (mproc));
mproc.create = mt_create;
mproc.destroy = mt_destroy;
mproc.match = mt_match;
diff --git a/src/match_value.c b/src/match_value.c
index 4d49984f618173b48323634a3ed34a1b85cde048..54ddba28e6cdea3a32af5fe3328cf5a3bd029839 100644 (file)
--- a/src/match_value.c
+++ b/src/match_value.c
*/
#include "collectd.h"
+
#include "common.h"
#include "utils_cache.h"
#include "filter_chain.h"
*/
static void mv_free_match (mv_match_t *m) /* {{{ */
{
- int i;
-
if (m == NULL)
return;
if (m->data_sources != NULL)
{
- for (i = 0; i < m->data_sources_num; ++i)
+ for (size_t i = 0; i < m->data_sources_num; ++i)
free(m->data_sources[i]);
free(m->data_sources);
}
-
+
free (m);
} /* }}} void mv_free_match */
{
size_t new_data_sources_num;
char **temp;
- int i;
/* Check number of arbuments. */
if (ci->values_num < 1)
}
/* Check type of arguments */
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
if (ci->values[i].type == OCONFIG_TYPE_STRING)
continue;
/* Allocate space for the char pointers */
new_data_sources_num = m->data_sources_num + ((size_t) ci->values_num);
- temp = (char **) realloc (m->data_sources,
+ temp = realloc (m->data_sources,
new_data_sources_num * sizeof (char *));
if (temp == NULL)
{
m->data_sources = temp;
/* Copy the strings, allocating memory as needed. */
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
- size_t j;
-
/* If we get here, there better be memory for us to write to. */
assert (m->data_sources_num < new_data_sources_num);
- j = m->data_sources_num;
+ size_t j = m->data_sources_num;
m->data_sources[j] = sstrdup (ci->values[i].value.string);
if (m->data_sources[j] == NULL)
{
{
mv_match_t *m;
int status;
- int i;
- m = (mv_match_t *) malloc (sizeof (*m));
+ m = calloc (1, sizeof (*m));
if (m == NULL)
{
- ERROR ("mv_create: malloc failed.");
+ ERROR ("mv_create: calloc failed.");
return (-ENOMEM);
}
- memset (m, 0, sizeof (*m));
m->min = NAN;
m->max = NAN;
m->data_sources_num = 0;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
mv_match_t *m;
gauge_t *values;
int status;
- int i;
if ((user_data == NULL) || (*user_data == NULL))
return (-1);
status = FC_MATCH_NO_MATCH;
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
int value_matches = 0;
if (m->satisfy == SATISFY_ANY)
break;
}
- else if (value_matches == 0)
+ else
{
status = FC_MATCH_NO_MATCH;
if (m->satisfy == SATISFY_ALL)
void module_register (void)
{
- match_proc_t mproc;
+ match_proc_t mproc = { 0 };
- memset (&mproc, 0, sizeof (mproc));
mproc.create = mv_create;
mproc.destroy = mv_destroy;
mproc.match = mv_match;
diff --git a/src/mbmon.c b/src/mbmon.c
index d23062db2d54734551789c76cac837c9915c43f2..9629b8960d67da5960f957d89f48bfd0c40f500c 100644 (file)
--- a/src/mbmon.c
+++ b/src/mbmon.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
const char *host;
const char *port;
- struct addrinfo ai_hints;
- struct addrinfo *ai_list, *ai_ptr;
+ struct addrinfo *ai_list;
int ai_return;
- memset (&ai_hints, '\0', sizeof (ai_hints));
- ai_hints.ai_flags = 0;
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = PF_UNSPEC;
- ai_hints.ai_socktype = SOCK_STREAM;
- ai_hints.ai_protocol = IPPROTO_TCP;
-
host = mbmon_host;
if (host == NULL)
host = MBMON_DEF_HOST;
if (port == NULL)
port = MBMON_DEF_PORT;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_protocol = IPPROTO_TCP,
+ .ai_socktype = SOCK_STREAM
+ };
+
if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
{
char errbuf[1024];
}
fd = -1;
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
/* create our socket descriptor */
if ((fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol)) < 0)
/* Trim trailing whitespace from a string. */
static void trim_spaces (char *s)
{
- size_t l;
-
- for (l = strlen (s) - 1; (l > 0) && isspace ((int) s[l]); l--)
+ for (size_t l = strlen (s) - 1; (l > 0) && isspace ((int) s[l]); l--)
s[l] = '\0';
}
double value;
char *nextc;
- char *type;
- char *inst;
+ const char *type;
+ const char *inst;
*t++ = '\0';
trim_spaces (s);
diff --git a/src/md.c b/src/md.c
index b34cc975be70343c9d96cc96b28d10157a59a1c4..44cad2edbeef32102cf7324fb73d5974c1159796 100644 (file)
--- a/src/md.c
+++ b/src/md.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_ignorelist.h"
diff --git a/src/memcachec.c b/src/memcachec.c
index 013b6c4ed6f83053fa42ace7848218fcaaf5448c..dff5546179f1bade7201718889e1669f87b96d77 100644 (file)
--- a/src/memcachec.c
+++ b/src/memcachec.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_match.h"
#include <libmemcached/memcached.h>
{
web_match_t *match;
int status;
- int i;
if (ci->values_num != 0)
{
WARNING ("memcachec plugin: Ignoring arguments for the `Match' block.");
}
- match = (web_match_t *) malloc (sizeof (*match));
+ match = calloc (1, sizeof (*match));
if (match == NULL)
{
- ERROR ("memcachec plugin: malloc failed.");
+ ERROR ("memcachec plugin: calloc failed.");
return (-1);
}
- memset (match, 0, sizeof (*match));
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
match->dstype);
if (match->match == NULL)
{
- ERROR ("memcachec plugin: tail_match_add_match_simple failed.");
+ ERROR ("memcachec plugin: match_create_simple failed.");
cmc_web_match_free (match);
return (-1);
}
{
web_page_t *page;
int status;
- int i;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
return (-1);
}
- page = (web_page_t *) malloc (sizeof (*page));
+ page = calloc (1, sizeof (*page));
if (page == NULL)
{
- ERROR ("memcachec plugin: malloc failed.");
+ ERROR ("memcachec plugin: calloc failed.");
return (-1);
}
- memset (page, 0, sizeof (*page));
page->server = NULL;
page->key = NULL;
/* Process all children */
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
web_page_t *prev;
prev = pages_g;
- while ((prev != NULL) && (prev->next != NULL))
+ while (prev->next != NULL)
prev = prev->next;
prev->next = page;
}
int success;
int errors;
int status;
- int i;
success = 0;
errors = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static int cmc_read_page (web_page_t *wp) /* {{{ */
{
- web_match_t *wm;
memcached_return rc;
size_t string_length;
uint32_t flags;
return (-1);
}
- for (wm = wp->matches; wm != NULL; wm = wm->next)
+ for (web_match_t *wm = wp->matches; wm != NULL; wm = wm->next)
{
cu_match_value_t *mv;
static int cmc_read (void) /* {{{ */
{
- web_page_t *wp;
-
- for (wp = pages_g; wp != NULL; wp = wp->next)
+ for (web_page_t *wp = pages_g; wp != NULL; wp = wp->next)
cmc_read_page (wp);
return (0);
diff --git a/src/memcached.c b/src/memcached.c
index d650f02f1d3fd866030ca2914fccaefd82a9175b..9e6e725293d152561bd3287427f3e90dffb217f5 100644 (file)
--- a/src/memcached.c
+++ b/src/memcached.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
static _Bool memcached_have_instances = 0;
-static void memcached_free (memcached_t *st)
+static void memcached_free (void *arg)
{
+ memcached_t *st = arg;
if (st == NULL)
return;
static int memcached_connect_unix (memcached_t *st)
{
- struct sockaddr_un serv_addr;
+ struct sockaddr_un serv_addr = { 0 };
int fd;
- memset (&serv_addr, 0, sizeof (serv_addr));
serv_addr.sun_family = AF_UNIX;
sstrncpy (serv_addr.sun_path, st->socket,
sizeof (serv_addr.sun_path));
static int memcached_connect_inet (memcached_t *st)
{
- char *host;
- char *port;
+ const char *host;
+ const char *port;
- struct addrinfo ai_hints;
- struct addrinfo *ai_list, *ai_ptr;
+ struct addrinfo *ai_list;
int status;
int fd = -1;
- memset (&ai_hints, 0, sizeof (ai_hints));
- ai_hints.ai_flags = 0;
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_STREAM;
- ai_hints.ai_protocol = 0;
-
host = (st->host != NULL) ? st->host : MEMCACHED_DEF_HOST;
port = (st->port != NULL) ? st->port : MEMCACHED_DEF_PORT;
- ai_list = NULL;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_socktype = SOCK_STREAM
+ };
+
status = getaddrinfo (host, port, &ai_hints, &ai_list);
if (status != 0)
{
return (-1);
}
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
/* create our socket descriptor */
fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
static int memcached_query_daemon (char *buffer, size_t buffer_size, memcached_t *st)
{
- int fd = -1;
- int status;
+ int fd, status;
size_t buffer_fill;
fd = memcached_connect (st);
@@ -246,21 +239,24 @@ static int memcached_query_daemon (char *buffer, size_t buffer_size, memcached_t
static void memcached_init_vl (value_list_t *vl, memcached_t const *st)
{
+ char const *host = st->host;
+
+ /* Set vl->host to hostname_g, if:
+ * - Legacy mode is used.
+ * - "Socket" option is given (doc: "Host option is ignored").
+ * - "Host" option is not provided.
+ * - "Host" option is set to "localhost" or "127.0.0.1". */
+ if ((strcmp (st->name, "__legacy__") == 0)
+ || (st->socket != NULL)
+ || (st->host == NULL)
+ || (strcmp ("127.0.0.1", st->host) == 0)
+ || (strcmp ("localhost", st->host) == 0))
+ host = hostname_g;
+
sstrncpy (vl->plugin, "memcached", sizeof (vl->plugin));
- if (strcmp (st->name, "__legacy__") == 0) /* legacy mode */
- {
- sstrncpy (vl->host, hostname_g, sizeof (vl->host));
- }
- else
- {
- if (st->socket != NULL)
- sstrncpy (vl->host, hostname_g, sizeof (vl->host));
- else
- sstrncpy (vl->host,
- (st->host != NULL) ? st->host : MEMCACHED_DEF_HOST,
- sizeof (vl->host));
+ sstrncpy (vl->host, host, sizeof (vl->host));
+ if (strcmp (st->name, "__legacy__") != 0)
sstrncpy (vl->plugin_instance, st->name, sizeof (vl->plugin_instance));
- }
}
static void submit_derive (const char *type, const char *type_inst,
static int memcached_add_read_callback (memcached_t *st)
{
- user_data_t ud;
char callback_name[3*DATA_MAX_NAME_LEN];
int status;
- memset (&ud, 0, sizeof (ud));
- ud.data = st;
- ud.free_func = (void *) memcached_free;
-
assert (st->name != NULL);
ssnprintf (callback_name, sizeof (callback_name), "memcached/%s", st->name);
+ user_data_t ud = {
+ .data = st,
+ .free_func = memcached_free
+ };
+
status = plugin_register_complex_read (/* group = */ "memcached",
/* name = */ callback_name,
/* callback = */ memcached_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user_data = */ &ud);
return (status);
} /* int memcached_add_read_callback */
static int config_add_instance(oconfig_item_t *ci)
{
memcached_t *st;
- int i;
int status = 0;
/* Disable automatic generation of default instance in the init callback. */
memcached_have_instances = 1;
- st = malloc (sizeof (*st));
+ st = calloc (1, sizeof (*st));
if (st == NULL)
{
- ERROR ("memcached plugin: malloc failed.");
+ ERROR ("memcached plugin: calloc failed.");
return (-1);
}
- memset (st, 0, sizeof (*st));
st->name = NULL;
st->socket = NULL;
st->host = NULL;
}
assert (st->name != NULL);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
{
int status = 0;
_Bool have_instance_block = 0;
- int i;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
return (0);
/* No instances were configured, lets start a default instance. */
- st = malloc (sizeof (*st));
+ st = calloc (1, sizeof (*st));
if (st == NULL)
return (ENOMEM);
- memset (st, 0, sizeof (*st));
st->name = sstrdup ("__legacy__");
st->socket = NULL;
st->host = NULL;
diff --git a/src/memory.c b/src/memory.c
index fb2f3d38a4045fd8790160a1155ed04cda33ab23..16b8e09fbac720d6c32f7a919bf2f46cc793713e 100644 (file)
--- a/src/memory.c
+++ b/src/memory.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#elif HAVE_LIBKSTAT
static int pagesize;
static kstat_t *ksp;
+static kstat_t *ksz;
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
static int memory_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("ValuesAbsolute", child->key) == 0)
ksp = NULL;
return (-1);
}
+ if (get_kstat (&ksz, "zfs", 0, "arcstats") != 0)
+ {
+ ksz = NULL;
+ return (-1);
+ }
+
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
* vm.stats.vm.v_inactive_count: 113730
* vm.stats.vm.v_cache_count: 10809
*/
- char *sysctl_keys[8] =
+ const char *sysctl_keys[8] =
{
"vm.stats.vm.v_page_size",
"vm.stats.vm.v_page_count",
};
double sysctl_vals[8];
- int i;
-
- for (i = 0; sysctl_keys[i] != NULL; i++)
+ for (int i = 0; sysctl_keys[i] != NULL; i++)
{
int value;
size_t value_len = sizeof (value);
} /* for (sysctl_keys) */
/* multiply all all page counts with the pagesize */
- for (i = 1; sysctl_keys[i] != NULL; i++)
+ for (int i = 1; sysctl_keys[i] != NULL; i++)
if (!isnan (sysctl_vals[i]))
sysctl_vals[i] *= sysctl_vals[0];
long long mem_lock;
long long mem_kern;
long long mem_unus;
+ long long arcsize;
+
long long pp_kernel;
long long physmem;
if (ksp == NULL)
return (-1);
+ if (ksz == NULL)
+ return (-1);
mem_used = get_kstat_value (ksp, "pagestotal");
mem_free = get_kstat_value (ksp, "pagesfree");
mem_lock = get_kstat_value (ksp, "pageslocked");
- mem_kern = 0;
- mem_unus = 0;
-
+ arcsize = get_kstat_value (ksz, "size");
pp_kernel = get_kstat_value (ksp, "pp_kernel");
physmem = get_kstat_value (ksp, "physmem");
availrmem = get_kstat_value (ksp, "availrmem");
+ mem_kern = 0;
+ mem_unus = 0;
+
if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
{
WARNING ("memory plugin: one of used, free or locked is negative.");
mem_lock *= pagesize; /* some? ;) */
mem_kern *= pagesize; /* it's 2011 RAM is cheap */
mem_unus *= pagesize;
+ mem_kern -= arcsize;
+
MEMORY_SUBMIT ("used", (gauge_t) mem_used,
"free", (gauge_t) mem_free,
"locked", (gauge_t) mem_lock,
"kernel", (gauge_t) mem_kern,
+ "arc", (gauge_t) arcsize,
"unusable", (gauge_t) mem_unus);
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
int mib[] = {CTL_VM, VM_METER};
- struct vmtotal vmtotal;
+ struct vmtotal vmtotal = { 0 };
gauge_t mem_active;
gauge_t mem_inactive;
gauge_t mem_free;
size_t size;
- memset (&vmtotal, 0, sizeof (vmtotal));
size = sizeof (vmtotal);
if (sysctl (mib, 2, &vmtotal, &size, NULL, 0) < 0) {
/* #endif HAVE_LIBSTATGRAB */
#elif HAVE_PERFSTAT
- perfstat_memory_total_t pmemory;
+ perfstat_memory_total_t pmemory = { 0 };
- memset (&pmemory, 0, sizeof (pmemory));
if (perfstat_memory_total(NULL, &pmemory, sizeof(pmemory), 1) < 0)
{
char errbuf[1024];
diff --git a/src/mic.c b/src/mic.c
index 570da51bcfd56c20296effdd64e570e3ff9eb6b9..3e31889fe83f560d89a09ce20df0d26c55d95dc6 100644 (file)
--- a/src/mic.c
+++ b/src/mic.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include "utils_ignorelist.h"
static int mic_read_temps(int mic)
{
size_t num_therms = STATIC_ARRAY_SIZE(therm_ids);
- size_t j;
- for (j = 0; j < num_therms; j++) {
+ for (size_t j = 0; j < num_therms; j++) {
U32 status;
U32 temp_buffer;
U32 buffer_size = (U32)sizeof(temp_buffer);
}
if (show_cpu_cores) {
- int j;
- for (j = 0; j < core_util.core; j++) {
+ for (int j = 0; j < core_util.core; j++) {
mic_submit_cpu(mic, "user", j, core_jiffs[j].user);
mic_submit_cpu(mic, "sys", j, core_jiffs[j].sys);
mic_submit_cpu(mic, "nice", j, core_jiffs[j].nice);
static int mic_read (void)
{
- int i;
U32 ret;
int error;
error=0;
- for (i=0;i<num_mics;i++) {
+ for (int i=0;i<num_mics;i++) {
ret = MicInitAdapter(&mic_handle,&mics[i]);
if (ret != MIC_ACCESS_API_SUCCESS) {
ERROR("mic plugin: Problem initializing MicAdapter: %s",
diff --git a/src/modbus.c b/src/modbus.c
index cf126b5ae3b6e967dd560c07b8a0e805ed9c37ef..473a4ee435230a96268eee789ce531ba2c56dbdc 100644 (file)
--- a/src/modbus.c
+++ b/src/modbus.c
REG_TYPE_UINT32,
REG_TYPE_FLOAT
}; /* }}} */
-enum mb_mreg_type_e /* {{{ */
+enum mb_mreg_type_e /* {{{ */
{
MREG_HOLDING,
MREG_INPUT
static mb_data_t *data_get_by_name (mb_data_t *src, /* {{{ */
const char *name)
{
- mb_data_t *ptr;
-
if (name == NULL)
return (NULL);
- for (ptr = src; ptr != NULL; ptr = ptr->next)
+ for (mb_data_t *ptr = src; ptr != NULL; ptr = ptr->next)
if (strcasecmp (ptr->name, name) == 0)
return (ptr);
if ((host == NULL) || (slave == NULL) || (data == NULL))
return (EINVAL);
- if (host->interval <= 0)
+ if (host->interval == 0)
host->interval = plugin_get_interval ();
if (slave->instance[0] == 0)
static int mb_read_data (mb_host_t *host, mb_slave_t *slave, /* {{{ */
mb_data_t *data)
{
- uint16_t values[2];
+ uint16_t values[2] = { 0 };
int values_num;
const data_set_t *ds;
int status = 0;
if (ds->ds_num != 1)
{
- ERROR ("Modbus plugin: The type \"%s\" has %i data sources. "
+ ERROR ("Modbus plugin: The type \"%s\" has %zu data sources. "
"I can only handle data sets with only one data source.",
data->type, ds->ds_num);
return (-1);
"is not UINT32.", data->type, DS_TYPE_TO_STRING (ds->ds[0].type));
}
- memset (values, 0, sizeof (values));
if ((data->register_type == REG_TYPE_INT32)
|| (data->register_type == REG_TYPE_UINT32)
|| (data->register_type == REG_TYPE_FLOAT))
modbus_free (host->connection);
#endif
}
-
+
#if LEGACY_LIBMODBUS
/* Version 2.0.3: Pass the connection struct as a pointer and pass the slave
* id to each call of "read_holding_registers". */
static int mb_read_slave (mb_host_t *host, mb_slave_t *slave) /* {{{ */
{
- mb_data_t *data;
int success;
int status;
return (EINVAL);
success = 0;
- for (data = slave->collect; data != NULL; data = data->next)
+ for (mb_data_t *data = slave->collect; data != NULL; data = data->next)
{
status = mb_read_data (host, slave, data);
if (status == 0)
static int mb_read (user_data_t *user_data) /* {{{ */
{
mb_host_t *host;
- size_t i;
int success;
int status;
host = user_data->data;
success = 0;
- for (i = 0; i < host->slaves_num; i++)
+ for (size_t i = 0; i < host->slaves_num; i++)
{
status = mb_read_slave (host, host->slaves + i);
if (status == 0)
static void slaves_free_all (mb_slave_t *slaves, size_t slaves_num) /* {{{ */
{
- size_t i;
-
if (slaves == NULL)
return;
- for (i = 0; i < slaves_num; i++)
+ for (size_t i = 0; i < slaves_num; i++)
data_free_all (slaves[i].collect);
sfree (slaves);
} /* }}} void slaves_free_all */
static int mb_config_add_data (oconfig_item_t *ci) /* {{{ */
{
- mb_data_t data;
+ mb_data_t data = { 0 };
int status;
- int i;
- memset (&data, 0, sizeof (data));
data.name = NULL;
data.register_type = REG_TYPE_UINT16;
data.next = NULL;
if (status != 0)
return (status);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
const char *address)
{
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
- struct addrinfo ai_hints;
int status;
if ((host == NULL) || (address == NULL))
return (EINVAL);
- memset (&ai_hints, 0, sizeof (ai_hints));
-#if AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- /* XXX: libmodbus can only handle IPv4 addresses. */
- ai_hints.ai_family = AF_INET;
- ai_hints.ai_addr = NULL;
- ai_hints.ai_canonname = NULL;
- ai_hints.ai_next = NULL;
+ struct addrinfo ai_hints = {
+ /* XXX: libmodbus can only handle IPv4 addresses. */
+ .ai_family = AF_INET,
+ .ai_flags = AI_ADDRCONFIG
+ };
- ai_list = NULL;
status = getaddrinfo (address, /* service = */ NULL,
&ai_hints, &ai_list);
if (status != 0)
return (status);
}
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
status = getnameinfo (ai_ptr->ai_addr, ai_ptr->ai_addrlen,
host->node, sizeof (host->node),
{
mb_slave_t *slave;
int status;
- int i;
if ((host == NULL) || (ci == NULL))
return (EINVAL);
if (status != 0)
return (status);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
{
mb_host_t *host;
int status;
- int i;
- host = malloc (sizeof (*host));
+ host = calloc (1, sizeof (*host));
if (host == NULL)
return (ENOMEM);
- memset (host, 0, sizeof (*host));
host->slaves = NULL;
status = cf_util_get_string_buffer (ci, host->host, sizeof (host->host));
return (EINVAL);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
status = 0;
{
user_data_t ud;
char name[1024];
- struct timespec interval = { 0, 0 };
ud.data = host;
ud.free_func = host_free;
ssnprintf (name, sizeof (name), "modbus-%s", host->host);
- CDTIME_T_TO_TIMESPEC (host->interval, &interval);
-
plugin_register_complex_read (/* group = */ NULL, name,
/* callback = */ mb_read,
- /* interval = */ (host->interval > 0) ? &interval : NULL,
+ /* interval = */ host->interval,
&ud);
}
else
static int mb_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
if (ci == NULL)
return (EINVAL);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/mqtt.c b/src/mqtt.c
--- /dev/null
+++ b/src/mqtt.c
@@ -0,0 +1,800 @@
+/**
+ * collectd - src/mqtt.c
+ * Copyright (C) 2014 Marc Falzon
+ * Copyright (C) 2014,2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Marc Falzon <marc at baha dot mu>
+ * Florian octo Forster <octo at collectd.org>
+ * Jan-Piet Mens <jpmens at gmail.com>
+ **/
+
+// Reference: http://mosquitto.org/api/files/mosquitto-h.html
+
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+#include "utils_complain.h"
+
+#include <mosquitto.h>
+
+#define MQTT_MAX_TOPIC_SIZE 1024
+#define MQTT_MAX_MESSAGE_SIZE MQTT_MAX_TOPIC_SIZE + 1024
+#define MQTT_DEFAULT_HOST "localhost"
+#define MQTT_DEFAULT_PORT 1883
+#define MQTT_DEFAULT_TOPIC_PREFIX "collectd"
+#define MQTT_DEFAULT_TOPIC "collectd/#"
+#ifndef MQTT_KEEPALIVE
+# define MQTT_KEEPALIVE 60
+#endif
+#ifndef SSL_VERIFY_PEER
+# define SSL_VERIFY_PEER 1
+#endif
+
+
+/*
+ * Data types
+ */
+struct mqtt_client_conf
+{
+ _Bool publish;
+ char *name;
+
+ struct mosquitto *mosq;
+ _Bool connected;
+
+ char *host;
+ int port;
+ char *client_id;
+ char *username;
+ char *password;
+ int qos;
+ char *cacertificatefile;
+ char *certificatefile;
+ char *certificatekeyfile;
+ char *tlsprotocol;
+ char *ciphersuite;
+
+ /* For publishing */
+ char *topic_prefix;
+ _Bool store_rates;
+ _Bool retain;
+
+ /* For subscribing */
+ pthread_t thread;
+ _Bool loop;
+ char *topic;
+ _Bool clean_session;
+
+ c_complain_t complaint_cantpublish;
+ pthread_mutex_t lock;
+};
+typedef struct mqtt_client_conf mqtt_client_conf_t;
+
+static mqtt_client_conf_t **subscribers = NULL;
+static size_t subscribers_num = 0;
+
+/*
+ * Functions
+ */
+#if LIBMOSQUITTO_MAJOR == 0
+static char const *mosquitto_strerror (int code)
+{
+ switch (code)
+ {
+ case MOSQ_ERR_SUCCESS: return "MOSQ_ERR_SUCCESS";
+ case MOSQ_ERR_NOMEM: return "MOSQ_ERR_NOMEM";
+ case MOSQ_ERR_PROTOCOL: return "MOSQ_ERR_PROTOCOL";
+ case MOSQ_ERR_INVAL: return "MOSQ_ERR_INVAL";
+ case MOSQ_ERR_NO_CONN: return "MOSQ_ERR_NO_CONN";
+ case MOSQ_ERR_CONN_REFUSED: return "MOSQ_ERR_CONN_REFUSED";
+ case MOSQ_ERR_NOT_FOUND: return "MOSQ_ERR_NOT_FOUND";
+ case MOSQ_ERR_CONN_LOST: return "MOSQ_ERR_CONN_LOST";
+ case MOSQ_ERR_SSL: return "MOSQ_ERR_SSL";
+ case MOSQ_ERR_PAYLOAD_SIZE: return "MOSQ_ERR_PAYLOAD_SIZE";
+ case MOSQ_ERR_NOT_SUPPORTED: return "MOSQ_ERR_NOT_SUPPORTED";
+ case MOSQ_ERR_AUTH: return "MOSQ_ERR_AUTH";
+ case MOSQ_ERR_ACL_DENIED: return "MOSQ_ERR_ACL_DENIED";
+ case MOSQ_ERR_UNKNOWN: return "MOSQ_ERR_UNKNOWN";
+ case MOSQ_ERR_ERRNO: return "MOSQ_ERR_ERRNO";
+ }
+
+ return "UNKNOWN ERROR CODE";
+}
+#else
+/* provided by libmosquitto */
+#endif
+
+static void mqtt_free (mqtt_client_conf_t *conf)
+{
+ if (conf == NULL)
+ return;
+
+ if (conf->connected)
+ (void) mosquitto_disconnect (conf->mosq);
+ conf->connected = 0;
+ (void) mosquitto_destroy (conf->mosq);
+
+ sfree (conf->host);
+ sfree (conf->username);
+ sfree (conf->password);
+ sfree (conf->client_id);
+ sfree (conf->topic_prefix);
+ sfree (conf);
+}
+
+static char *strip_prefix (char *topic)
+{
+ size_t num = 0;
+
+ for (size_t i = 0; topic[i] != 0; i++)
+ if (topic[i] == '/')
+ num++;
+
+ if (num < 2)
+ return (NULL);
+
+ while (num > 2)
+ {
+ char *tmp = strchr (topic, '/');
+ if (tmp == NULL)
+ return (NULL);
+ topic = tmp + 1;
+ num--;
+ }
+
+ return (topic);
+}
+
+static void on_message (
+#if LIBMOSQUITTO_MAJOR == 0
+#else
+ __attribute__((unused)) struct mosquitto *m,
+#endif
+ __attribute__((unused)) void *arg,
+ const struct mosquitto_message *msg)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ data_set_t const *ds;
+ char *topic;
+ char *name;
+ char *payload;
+ int status;
+
+ if (msg->payloadlen <= 0) {
+ DEBUG ("mqtt plugin: message has empty payload");
+ return;
+ }
+
+ topic = strdup (msg->topic);
+ name = strip_prefix (topic);
+
+ status = parse_identifier_vl (name, &vl);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: Unable to parse topic \"%s\".", topic);
+ sfree (topic);
+ return;
+ }
+ sfree (topic);
+
+ ds = plugin_get_ds (vl.type);
+ if (ds == NULL)
+ {
+ ERROR ("mqtt plugin: Unknown type: \"%s\".", vl.type);
+ return;
+ }
+
+ vl.values = calloc (ds->ds_num, sizeof (*vl.values));
+ if (vl.values == NULL)
+ {
+ ERROR ("mqtt plugin: calloc failed.");
+ return;
+ }
+ vl.values_len = ds->ds_num;
+
+ payload = malloc (msg->payloadlen+1);
+ if (payload == NULL)
+ {
+ ERROR ("mqtt plugin: malloc for payload buffer failed.");
+ sfree (vl.values);
+ return;
+ }
+ memmove (payload, msg->payload, msg->payloadlen);
+ payload[msg->payloadlen] = 0;
+
+ DEBUG ("mqtt plugin: payload = \"%s\"", payload);
+ status = parse_values (payload, &vl, ds);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: Unable to parse payload \"%s\".", payload);
+ sfree (payload);
+ sfree (vl.values);
+ return;
+ }
+ sfree (payload);
+
+ plugin_dispatch_values (&vl);
+ sfree (vl.values);
+} /* void on_message */
+
+/* must hold conf->lock when calling. */
+static int mqtt_reconnect (mqtt_client_conf_t *conf)
+{
+ int status;
+
+ if (conf->connected)
+ return (0);
+
+ status = mosquitto_reconnect (conf->mosq);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt_connect_broker: mosquitto_connect failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror(errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+ return (-1);
+ }
+
+ conf->connected = 1;
+
+ c_release (LOG_INFO,
+ &conf->complaint_cantpublish,
+ "mqtt plugin: successfully reconnected to broker \"%s:%d\"",
+ conf->host, conf->port);
+
+ return (0);
+} /* mqtt_reconnect */
+
+/* must hold conf->lock when calling. */
+static int mqtt_connect (mqtt_client_conf_t *conf)
+{
+ char const *client_id;
+ int status;
+
+ if (conf->mosq != NULL)
+ return mqtt_reconnect (conf);
+
+ if (conf->client_id)
+ client_id = conf->client_id;
+ else
+ client_id = hostname_g;
+
+#if LIBMOSQUITTO_MAJOR == 0
+ conf->mosq = mosquitto_new (client_id, /* user data = */ conf);
+#else
+ conf->mosq = mosquitto_new (client_id, conf->clean_session, /* user data = */ conf);
+#endif
+ if (conf->mosq == NULL)
+ {
+ ERROR ("mqtt plugin: mosquitto_new failed");
+ return (-1);
+ }
+
+#if LIBMOSQUITTO_MAJOR != 0
+ if (conf->cacertificatefile) {
+ status = mosquitto_tls_set(conf->mosq, conf->cacertificatefile, NULL,
+ conf->certificatefile, conf->certificatekeyfile, /* pw_callback */NULL);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ status = mosquitto_tls_opts_set(conf->mosq, SSL_VERIFY_PEER, conf->tlsprotocol, conf->ciphersuite);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_opts_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ status = mosquitto_tls_insecure_set(conf->mosq, false);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_insecure_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+#endif
+
+ if (conf->username && conf->password)
+ {
+ status = mosquitto_username_pw_set (conf->mosq, conf->username, conf->password);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: mosquitto_username_pw_set failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror (errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+
+#if LIBMOSQUITTO_MAJOR == 0
+ status = mosquitto_connect (conf->mosq, conf->host, conf->port,
+ /* keepalive = */ MQTT_KEEPALIVE, /* clean session = */ conf->clean_session);
+#else
+ status = mosquitto_connect (conf->mosq, conf->host, conf->port, MQTT_KEEPALIVE);
+#endif
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: mosquitto_connect failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror (errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror (status));
+
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ if (!conf->publish)
+ {
+ mosquitto_message_callback_set (conf->mosq, on_message);
+
+ status = mosquitto_subscribe (conf->mosq,
+ /* message_id = */ NULL,
+ conf->topic, conf->qos);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ ERROR ("mqtt plugin: Subscribing to \"%s\" failed: %s",
+ conf->topic, mosquitto_strerror (status));
+
+ mosquitto_disconnect (conf->mosq);
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+
+ conf->connected = 1;
+ return (0);
+} /* mqtt_connect */
+
+static void *subscribers_thread (void *arg)
+{
+ mqtt_client_conf_t *conf = arg;
+ int status;
+
+ conf->loop = 1;
+
+ while (conf->loop)
+ {
+ status = mqtt_connect (conf);
+ if (status != 0)
+ {
+ sleep (1);
+ continue;
+ }
+
+ /* The documentation says "0" would map to the default (1000ms), but
+ * that does not work on some versions. */
+#if LIBMOSQUITTO_MAJOR == 0
+ status = mosquitto_loop (conf->mosq, /* timeout = */ 1000 /* ms */);
+#else
+ status = mosquitto_loop (conf->mosq,
+ /* timeout[ms] = */ 1000,
+ /* max_packets = */ 100);
+#endif
+ if (status == MOSQ_ERR_CONN_LOST)
+ {
+ conf->connected = 0;
+ continue;
+ }
+ else if (status != MOSQ_ERR_SUCCESS)
+ {
+ ERROR ("mqtt plugin: mosquitto_loop failed: %s",
+ mosquitto_strerror (status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ conf->connected = 0;
+ continue;
+ }
+
+ DEBUG ("mqtt plugin: mosquitto_loop succeeded.");
+ } /* while (conf->loop) */
+
+ pthread_exit (0);
+} /* void *subscribers_thread */
+
+static int publish (mqtt_client_conf_t *conf, char const *topic,
+ void const *payload, size_t payload_len)
+{
+ int status;
+
+ pthread_mutex_lock (&conf->lock);
+
+ status = mqtt_connect (conf);
+ if (status != 0) {
+ pthread_mutex_unlock (&conf->lock);
+ ERROR ("mqtt plugin: unable to reconnect to broker");
+ return (status);
+ }
+
+ status = mosquitto_publish(conf->mosq, /* message_id */ NULL, topic,
+#if LIBMOSQUITTO_MAJOR == 0
+ (uint32_t) payload_len, payload,
+#else
+ (int) payload_len, payload,
+#endif
+ conf->qos, conf->retain);
+ if (status != MOSQ_ERR_SUCCESS)
+ {
+ char errbuf[1024];
+ c_complain (LOG_ERR,
+ &conf->complaint_cantpublish,
+ "mqtt plugin: mosquitto_publish failed: %s",
+ (status == MOSQ_ERR_ERRNO)
+ ? sstrerror(errno, errbuf, sizeof (errbuf))
+ : mosquitto_strerror(status));
+ /* Mark our connection "down" regardless of the error as a safety
+ * measure; we will try to reconnect the next time we have to publish a
+ * message */
+ conf->connected = 0;
+
+ pthread_mutex_unlock (&conf->lock);
+ return (-1);
+ }
+
+ pthread_mutex_unlock (&conf->lock);
+ return (0);
+} /* int publish */
+
+static int format_topic (char *buf, size_t buf_len,
+ data_set_t const *ds, value_list_t const *vl,
+ mqtt_client_conf_t *conf)
+{
+ char name[MQTT_MAX_TOPIC_SIZE];
+ int status;
+
+ if ((conf->topic_prefix == NULL) || (conf->topic_prefix[0] == 0))
+ return (FORMAT_VL (buf, buf_len, vl));
+
+ status = FORMAT_VL (name, sizeof (name), vl);
+ if (status != 0)
+ return (status);
+
+ status = ssnprintf (buf, buf_len, "%s/%s", conf->topic_prefix, name);
+ if ((status < 0) || (((size_t) status) >= buf_len))
+ return (ENOMEM);
+
+ return (0);
+} /* int format_topic */
+
+static int mqtt_write (const data_set_t *ds, const value_list_t *vl,
+ user_data_t *user_data)
+{
+ mqtt_client_conf_t *conf;
+ char topic[MQTT_MAX_TOPIC_SIZE];
+ char payload[MQTT_MAX_MESSAGE_SIZE];
+ int status = 0;
+
+ if ((user_data == NULL) || (user_data->data == NULL))
+ return (EINVAL);
+ conf = user_data->data;
+
+ status = format_topic (topic, sizeof (topic), ds, vl, conf);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: format_topic failed with status %d.", status);
+ return (status);
+ }
+
+ status = format_values (payload, sizeof (payload),
+ ds, vl, conf->store_rates);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: format_values failed with status %d.", status);
+ return (status);
+ }
+
+ status = publish (conf, topic, payload, strlen (payload) + 1);
+ if (status != 0)
+ {
+ ERROR ("mqtt plugin: publish failed: %s", mosquitto_strerror (status));
+ return (status);
+ }
+
+ return (status);
+} /* mqtt_write */
+
+/*
+ * <Publish "name">
+ * Host "example.com"
+ * Port 1883
+ * ClientId "collectd"
+ * User "guest"
+ * Password "secret"
+ * Prefix "collectd"
+ * StoreRates true
+ * Retain false
+ * QoS 0
+ * CACert "ca.pem" Enables TLS if set
+ * CertificateFile "client-cert.pem" optional
+ * CertificateKeyFile "client-key.pem" optional
+ * TLSProtocol "tlsv1.2" optional
+ * </Publish>
+ */
+static int mqtt_config_publisher (oconfig_item_t *ci)
+{
+ mqtt_client_conf_t *conf;
+ char cb_name[1024];
+ int status;
+
+ conf = calloc (1, sizeof (*conf));
+ if (conf == NULL)
+ {
+ ERROR ("mqtt plugin: calloc failed.");
+ return (-1);
+ }
+ conf->publish = 1;
+
+ conf->name = NULL;
+ status = cf_util_get_string (ci, &conf->name);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ conf->host = strdup (MQTT_DEFAULT_HOST);
+ conf->port = MQTT_DEFAULT_PORT;
+ conf->client_id = NULL;
+ conf->qos = 0;
+ conf->topic_prefix = strdup (MQTT_DEFAULT_TOPIC_PREFIX);
+ conf->store_rates = 1;
+
+ status = pthread_mutex_init (&conf->lock, NULL);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ C_COMPLAIN_INIT (&conf->complaint_cantpublish);
+
+ for (int i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("Host", child->key) == 0)
+ cf_util_get_string (child, &conf->host);
+ else if (strcasecmp ("Port", child->key) == 0)
+ {
+ int tmp = cf_util_get_port_number (child);
+ if (tmp < 0)
+ ERROR ("mqtt plugin: Invalid port number.");
+ else
+ conf->port = tmp;
+ }
+ else if (strcasecmp ("ClientId", child->key) == 0)
+ cf_util_get_string (child, &conf->client_id);
+ else if (strcasecmp ("User", child->key) == 0)
+ cf_util_get_string (child, &conf->username);
+ else if (strcasecmp ("Password", child->key) == 0)
+ cf_util_get_string (child, &conf->password);
+ else if (strcasecmp ("QoS", child->key) == 0)
+ {
+ int tmp = -1;
+ status = cf_util_get_int (child, &tmp);
+ if ((status != 0) || (tmp < 0) || (tmp > 2))
+ ERROR ("mqtt plugin: Not a valid QoS setting.");
+ else
+ conf->qos = tmp;
+ }
+ else if (strcasecmp ("Prefix", child->key) == 0)
+ cf_util_get_string (child, &conf->topic_prefix);
+ else if (strcasecmp ("StoreRates", child->key) == 0)
+ cf_util_get_boolean (child, &conf->store_rates);
+ else if (strcasecmp ("Retain", child->key) == 0)
+ cf_util_get_boolean (child, &conf->retain);
+ else if (strcasecmp ("CACert", child->key) == 0)
+ cf_util_get_string (child, &conf->cacertificatefile);
+ else if (strcasecmp ("CertificateFile", child->key) == 0)
+ cf_util_get_string (child, &conf->certificatefile);
+ else if (strcasecmp ("CertificateKeyFile", child->key) == 0)
+ cf_util_get_string (child, &conf->certificatekeyfile);
+ else if (strcasecmp ("TLSProtocol", child->key) == 0)
+ cf_util_get_string (child, &conf->tlsprotocol);
+ else if (strcasecmp ("CipherSuite", child->key) == 0)
+ cf_util_get_string (child, &conf->ciphersuite);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ ssnprintf (cb_name, sizeof (cb_name), "mqtt/%s", conf->name);
+ user_data_t user_data = {
+ .data = conf
+ };
+
+ plugin_register_write (cb_name, mqtt_write, &user_data);
+ return (0);
+} /* mqtt_config_publisher */
+
+/*
+ * <Subscribe "name">
+ * Host "example.com"
+ * Port 1883
+ * ClientId "collectd"
+ * User "guest"
+ * Password "secret"
+ * Topic "collectd/#"
+ * </Subscribe>
+ */
+static int mqtt_config_subscriber (oconfig_item_t *ci)
+{
+ mqtt_client_conf_t **tmp;
+ mqtt_client_conf_t *conf;
+ int status;
+
+ conf = calloc (1, sizeof (*conf));
+ if (conf == NULL)
+ {
+ ERROR ("mqtt plugin: calloc failed.");
+ return (-1);
+ }
+ conf->publish = 0;
+
+ conf->name = NULL;
+ status = cf_util_get_string (ci, &conf->name);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ conf->host = strdup (MQTT_DEFAULT_HOST);
+ conf->port = MQTT_DEFAULT_PORT;
+ conf->client_id = NULL;
+ conf->qos = 2;
+ conf->topic = strdup (MQTT_DEFAULT_TOPIC);
+ conf->clean_session = 1;
+
+ status = pthread_mutex_init (&conf->lock, NULL);
+ if (status != 0)
+ {
+ mqtt_free (conf);
+ return (status);
+ }
+
+ C_COMPLAIN_INIT (&conf->complaint_cantpublish);
+
+ for (int i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("Host", child->key) == 0)
+ cf_util_get_string (child, &conf->host);
+ else if (strcasecmp ("Port", child->key) == 0)
+ {
+ status = cf_util_get_port_number (child);
+ if (status < 0)
+ ERROR ("mqtt plugin: Invalid port number.");
+ else
+ conf->port = status;
+ }
+ else if (strcasecmp ("ClientId", child->key) == 0)
+ cf_util_get_string (child, &conf->client_id);
+ else if (strcasecmp ("User", child->key) == 0)
+ cf_util_get_string (child, &conf->username);
+ else if (strcasecmp ("Password", child->key) == 0)
+ cf_util_get_string (child, &conf->password);
+ else if (strcasecmp ("QoS", child->key) == 0)
+ {
+ int qos = -1;
+ status = cf_util_get_int (child, &qos);
+ if ((status != 0) || (qos < 0) || (qos > 2))
+ ERROR ("mqtt plugin: Not a valid QoS setting.");
+ else
+ conf->qos = qos;
+ }
+ else if (strcasecmp ("Topic", child->key) == 0)
+ cf_util_get_string (child, &conf->topic);
+ else if (strcasecmp ("CleanSession", child->key) == 0)
+ cf_util_get_boolean (child, &conf->clean_session);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ tmp = realloc (subscribers, sizeof (*subscribers) * (subscribers_num + 1) );
+ if (tmp == NULL)
+ {
+ ERROR ("mqtt plugin: realloc failed.");
+ mqtt_free (conf);
+ return (-1);
+ }
+ subscribers = tmp;
+ subscribers[subscribers_num] = conf;
+ subscribers_num++;
+
+ return (0);
+} /* mqtt_config_subscriber */
+
+/*
+ * <Plugin mqtt>
+ * <Publish "name">
+ * # ...
+ * </Publish>
+ * <Subscribe "name">
+ * # ...
+ * </Subscribe>
+ * </Plugin>
+ */
+static int mqtt_config (oconfig_item_t *ci)
+{
+ for (int i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("Publish", child->key) == 0)
+ mqtt_config_publisher (child);
+ else if (strcasecmp ("Subscribe", child->key) == 0)
+ mqtt_config_subscriber (child);
+ else
+ ERROR ("mqtt plugin: Unknown config option: %s", child->key);
+ }
+
+ return (0);
+} /* int mqtt_config */
+
+static int mqtt_init (void)
+{
+ mosquitto_lib_init ();
+
+ for (size_t i = 0; i < subscribers_num; i++)
+ {
+ int status;
+
+ if (subscribers[i]->loop)
+ continue;
+
+ status = plugin_thread_create (&subscribers[i]->thread,
+ /* attrs = */ NULL,
+ /* func = */ subscribers_thread,
+ /* args = */ subscribers[i]);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ ERROR ("mqtt plugin: pthread_create failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ continue;
+ }
+ }
+
+ return (0);
+} /* mqtt_init */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("mqtt", mqtt_config);
+ plugin_register_init ("mqtt", mqtt_init);
+} /* void module_register */
+
+/* vim: set sw=4 sts=4 et fdm=marker : */
diff --git a/src/multimeter.c b/src/multimeter.c
index 6953750525ce34cd2f4e50de26af4cfa6f6949e3..02fe1ad312f4be22a58982bb91f5ce033e29dd3f 100644 (file)
--- a/src/multimeter.c
+++ b/src/multimeter.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
static int multimeter_init (void)
{
- int i;
char device[] = "/dev/ttyS ";
- for (i = 0; i < 10; i++)
+ for (int i = 0; i < 10; i++)
{
device[strlen(device)-1] = i + '0';
if ((fd = open(device, O_RDWR | O_NOCTTY)) != -1)
{
- struct termios tios;
+ struct termios tios = { 0 };
int rts = TIOCM_RTS;
double value;
- memset (&tios, 0, sizeof (tios));
tios.c_cflag = B1200 | CS7 | CSTOPB | CREAD | CLOCAL;
tios.c_iflag = IGNBRK | IGNPAR;
tios.c_oflag = 0;
diff --git a/src/mysql.c b/src/mysql.c
index f6c710c0376e5fa85638f4675d46e635320c2313..32b72e286a0b0d08a4f8202ad17ac8296601504a 100644 (file)
--- a/src/mysql.c
+++ b/src/mysql.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#ifdef HAVE_MYSQL_H
#include <mysql.h>
char *user;
char *pass;
char *database;
+
+ /* mysql_ssl_set params */
+ char *key;
+ char *cert;
+ char *ca;
+ char *capath;
+ char *cipher;
+
char *socket;
int port;
int timeout;
_Bool master_stats;
_Bool slave_stats;
_Bool innodb_stats;
+ _Bool wsrep_stats;
_Bool slave_notif;
_Bool slave_io_running;
DEBUG ("mysql plugin: mysql_database_free (arg = %p);", arg);
- db = (mysql_database_t *) arg;
+ db = arg;
if (db == NULL)
return;
sfree (db->socket);
sfree (db->instance);
sfree (db->database);
+ sfree (db->key);
+ sfree (db->cert);
+ sfree (db->ca);
+ sfree (db->capath);
+ sfree (db->cipher);
sfree (db);
} /* }}} void mysql_database_free */
{
mysql_database_t *db;
int status = 0;
- int i;
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_STRING))
return (-1);
}
- db = (mysql_database_t *) malloc (sizeof (*db));
+ db = calloc (1, sizeof (*db));
if (db == NULL)
{
- ERROR ("mysql plugin: malloc failed.");
+ ERROR ("mysql plugin: calloc failed.");
return (-1);
}
- memset (db, 0, sizeof (*db));
/* initialize all the pointers */
db->alias = NULL;
db->user = NULL;
db->pass = NULL;
db->database = NULL;
+ db->key = NULL;
+ db->cert = NULL;
+ db->ca = NULL;
+ db->capath = NULL;
+ db->cipher = NULL;
+
db->socket = NULL;
db->con = NULL;
db->timeout = 0;
assert (db->instance != NULL);
/* Fill the `mysql_database_t' structure.. */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
status = cf_util_get_string (child, &db->socket);
else if (strcasecmp ("Database", child->key) == 0)
status = cf_util_get_string (child, &db->database);
+ else if (strcasecmp ("SSLKey", child->key) == 0)
+ status = cf_util_get_string (child, &db->key);
+ else if (strcasecmp ("SSLCert", child->key) == 0)
+ status = cf_util_get_string (child, &db->cert);
+ else if (strcasecmp ("SSLCA", child->key) == 0)
+ status = cf_util_get_string (child, &db->ca);
+ else if (strcasecmp ("SSLCAPath", child->key) == 0)
+ status = cf_util_get_string (child, &db->capath);
+ else if (strcasecmp ("SSLCipher", child->key) == 0)
+ status = cf_util_get_string (child, &db->cipher);
else if (strcasecmp ("ConnectTimeout", child->key) == 0)
status = cf_util_get_int (child, &db->timeout);
else if (strcasecmp ("MasterStats", child->key) == 0)
status = cf_util_get_boolean (child, &db->slave_notif);
else if (strcasecmp ("InnodbStats", child->key) == 0)
status = cf_util_get_boolean (child, &db->innodb_stats);
+ else if (strcasecmp ("WsrepStats", child->key) == 0)
+ status = cf_util_get_boolean (child, &db->wsrep_stats);
else
{
WARNING ("mysql plugin: Option `%s' not allowed here.", child->key);
/* If all went well, register this database for reading */
if (status == 0)
{
- user_data_t ud;
char cb_name[DATA_MAX_NAME_LEN];
DEBUG ("mysql plugin: Registering new read callback: %s",
(db->database != NULL) ? db->database : "<default>");
- memset (&ud, 0, sizeof (ud));
- ud.data = (void *) db;
- ud.free_func = mysql_database_free;
-
if (db->instance != NULL)
ssnprintf (cb_name, sizeof (cb_name), "mysql-%s",
db->instance);
else
sstrncpy (cb_name, "mysql", sizeof (cb_name));
+ user_data_t ud = {
+ .data = db,
+ .free_func = mysql_database_free
+ };
+
plugin_register_complex_read (/* group = */ NULL, cb_name,
mysql_read,
- /* interval = */ NULL, &ud);
+ /* interval = */ 0, &ud);
}
else
{
static int mysql_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
if (ci == NULL)
return (EINVAL);
/* Fill the `mysql_database_t' structure.. */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static MYSQL *getconnection (mysql_database_t *db)
{
+ const char *cipher;
+
if (db->is_connected)
{
int status;
/* Configure TCP connect timeout (default: 0) */
db->con->options.connect_timeout = db->timeout;
+ mysql_ssl_set (db->con, db->key, db->cert, db->ca, db->capath, db->cipher);
+
if (mysql_real_connect (db->con, db->host, db->user, db->pass,
db->database, db->port, db->socket, 0) == NULL)
{
return (NULL);
}
+ cipher = mysql_get_ssl_cipher (db->con);
+
INFO ("mysql plugin: Successfully connected to database %s "
- "at server %s (server version: %s, protocol version: %d)",
+ "at server %s with cipher %s "
+ "(server version: %s, protocol version: %d) ",
(db->database != NULL) ? db->database : "<none>",
mysql_get_host_info (db->con),
+ (cipher != NULL) ? cipher : "<none>",
mysql_get_server_info (db->con),
mysql_get_proto_info (db->con));
MYSQL_RES *res;
MYSQL_ROW row;
- char *query;
- int field_num;
+ const char *query;
+ int field_num;
unsigned long long position;
query = "SHOW MASTER STATUS";
MYSQL_RES *res;
MYSQL_ROW row;
- char *query;
- int field_num;
+ const char *query;
+ int field_num;
/* WTF? libmysqlclient does not seem to provide any means to
* translate a column name to a column index ... :-/ */
MYSQL_RES *res;
MYSQL_ROW row;
- char *query;
- struct {
- char *key;
- char *type;
- int ds_type;
- } metrics[] = {
- { "metadata_mem_pool_size", "bytes", DS_TYPE_GAUGE },
- { "lock_deadlocks", "mysql_locks", DS_TYPE_DERIVE },
- { "lock_timeouts", "mysql_locks", DS_TYPE_DERIVE },
- { "lock_row_lock_current_waits", "mysql_locks", DS_TYPE_DERIVE },
- { "buffer_pool_size", "bytes", DS_TYPE_GAUGE },
-
- { "buffer_pool_reads", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_read_requests", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_write_requests", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_wait_free", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_read_ahead", "operations", DS_TYPE_DERIVE },
- { "buffer_pool_read_ahead_evicted", "operations", DS_TYPE_DERIVE },
-
- { "buffer_pool_pages_total", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_pages_misc", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_pages_data", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_bytes_data", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_pages_dirty", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_bytes_dirty", "gauge", DS_TYPE_GAUGE },
- { "buffer_pool_pages_free", "gauge", DS_TYPE_GAUGE },
-
- { "buffer_pages_created", "operations", DS_TYPE_DERIVE },
- { "buffer_pages_written", "operations", DS_TYPE_DERIVE },
- { "buffer_pages_read", "operations", DS_TYPE_DERIVE },
- { "buffer_data_reads", "operations", DS_TYPE_DERIVE },
- { "buffer_data_written", "operations", DS_TYPE_DERIVE },
-
- { "os_data_reads", "operations", DS_TYPE_DERIVE },
- { "os_data_writes", "operations", DS_TYPE_DERIVE },
- { "os_data_fsyncs", "operations", DS_TYPE_DERIVE },
- { "os_log_bytes_written", "operations", DS_TYPE_DERIVE },
- { "os_log_fsyncs", "operations", DS_TYPE_DERIVE },
- { "os_log_pending_fsyncs", "operations", DS_TYPE_DERIVE },
- { "os_log_pending_writes", "operations", DS_TYPE_DERIVE },
-
- { "trx_rseg_history_len", "gauge", DS_TYPE_GAUGE },
-
- { "log_waits", "operations", DS_TYPE_DERIVE },
- { "log_write_requests", "operations", DS_TYPE_DERIVE },
- { "log_writes", "operations", DS_TYPE_DERIVE },
- { "adaptive_hash_searches", "operations", DS_TYPE_DERIVE },
-
- { "file_num_open_files", "gauge", DS_TYPE_GAUGE },
-
- { "ibuf_merges_insert", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_delete_mark", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_delete", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_discard_insert", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_discard_delete_mark","operations", DS_TYPE_DERIVE },
- { "ibuf_merges_discard_delete", "operations", DS_TYPE_DERIVE },
- { "ibuf_merges_discard_merges", "operations", DS_TYPE_DERIVE },
- { "ibuf_size", "bytes", DS_TYPE_GAUGE },
-
- { "innodb_activity_count", "gauge", DS_TYPE_GAUGE },
- { "innodb_dblwr_writes", "operations", DS_TYPE_DERIVE },
- { "innodb_dblwr_pages_written", "operations", DS_TYPE_DERIVE },
- { "innodb_dblwr_page_size", "gauge", DS_TYPE_GAUGE },
-
- { "innodb_rwlock_s_spin_waits", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_x_spin_waits", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_s_spin_rounds", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_x_spin_rounds", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_s_os_waits", "operations", DS_TYPE_DERIVE },
- { "innodb_rwlock_x_os_waits", "operations", DS_TYPE_DERIVE },
-
- { "dml_reads", "operations", DS_TYPE_DERIVE },
- { "dml_inserts", "operations", DS_TYPE_DERIVE },
- { "dml_deletes", "operations", DS_TYPE_DERIVE },
- { "dml_updates", "operations", DS_TYPE_DERIVE },
-
- { NULL, NULL, 0}
- };
+ const char *query;
+ struct {
+ const char *key;
+ const char *type;
+ int ds_type;
+ } metrics[] = {
+ { "metadata_mem_pool_size", "bytes", DS_TYPE_GAUGE },
+ { "lock_deadlocks", "mysql_locks", DS_TYPE_DERIVE },
+ { "lock_timeouts", "mysql_locks", DS_TYPE_DERIVE },
+ { "lock_row_lock_current_waits", "mysql_locks", DS_TYPE_DERIVE },
+ { "buffer_pool_size", "bytes", DS_TYPE_GAUGE },
+
+ { "os_log_bytes_written", "operations", DS_TYPE_DERIVE },
+ { "os_log_pending_fsyncs", "operations", DS_TYPE_DERIVE },
+ { "os_log_pending_writes", "operations", DS_TYPE_DERIVE },
+
+ { "trx_rseg_history_len", "gauge", DS_TYPE_GAUGE },
+
+ { "adaptive_hash_searches", "operations", DS_TYPE_DERIVE },
+
+ { "file_num_open_files", "gauge", DS_TYPE_GAUGE },
+
+ { "ibuf_merges_insert", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_delete_mark", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_delete", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_discard_insert", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_discard_delete_mark", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_discard_delete", "operations", DS_TYPE_DERIVE },
+ { "ibuf_merges_discard_merges", "operations", DS_TYPE_DERIVE },
+ { "ibuf_size", "bytes", DS_TYPE_GAUGE },
+
+ { "innodb_activity_count", "gauge", DS_TYPE_GAUGE },
+
+ { "innodb_rwlock_s_spin_waits", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_x_spin_waits", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_s_spin_rounds", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_x_spin_rounds", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_s_os_waits", "operations", DS_TYPE_DERIVE },
+ { "innodb_rwlock_x_os_waits", "operations", DS_TYPE_DERIVE },
+
+ { "dml_reads", "operations", DS_TYPE_DERIVE },
+ { "dml_inserts", "operations", DS_TYPE_DERIVE },
+ { "dml_deletes", "operations", DS_TYPE_DERIVE },
+ { "dml_updates", "operations", DS_TYPE_DERIVE },
+
+ { NULL, NULL, 0}
+ };
query = "SELECT name, count, type FROM information_schema.innodb_metrics WHERE status = 'enabled'";
while ((row = mysql_fetch_row (res)))
{
- int i;
+ int i;
char *key;
unsigned long long val;
key = row[0];
val = atoll (row[1]);
- for (i = 0;
- metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0;
- i++)
- ;
-
- if (metrics[i].key == NULL)
- continue;
-
- switch (metrics[i].ds_type) {
- case DS_TYPE_COUNTER:
- counter_submit(metrics[i].type, key, (counter_t)val, db);
- break;
- case DS_TYPE_GAUGE:
- gauge_submit(metrics[i].type, key, (gauge_t)val, db);
- break;
- case DS_TYPE_DERIVE:
- derive_submit(metrics[i].type, key, (derive_t)val, db);
- break;
- }
- }
-
- mysql_free_result(res);
- return (0);
+ for (i = 0; metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0; i++)
+ ;
+
+ if (metrics[i].key == NULL)
+ continue;
+
+ switch (metrics[i].ds_type) {
+ case DS_TYPE_COUNTER:
+ counter_submit(metrics[i].type, key, (counter_t)val, db);
+ break;
+ case DS_TYPE_GAUGE:
+ gauge_submit(metrics[i].type, key, (gauge_t)val, db);
+ break;
+ case DS_TYPE_DERIVE:
+ derive_submit(metrics[i].type, key, (derive_t)val, db);
+ break;
+ }
+ }
+
+ mysql_free_result(res);
+ return (0);
}
-static int mysql_read (user_data_t *ud)
+static int mysql_read_wsrep_stats (mysql_database_t *db, MYSQL *con)
{
- mysql_database_t *db;
- MYSQL *con;
MYSQL_RES *res;
MYSQL_ROW row;
- char *query;
+
+ const char *query;
+ struct {
+ const char *key;
+ const char *type;
+ int ds_type;
+ } metrics[] = {
+
+ { "wsrep_apply_oooe", "operations", DS_TYPE_DERIVE },
+ { "wsrep_apply_oool", "operations", DS_TYPE_DERIVE },
+ { "wsrep_causal_reads", "operations", DS_TYPE_DERIVE },
+ { "wsrep_commit_oooe", "operations", DS_TYPE_DERIVE },
+ { "wsrep_commit_oool", "operations", DS_TYPE_DERIVE },
+ { "wsrep_flow_control_recv", "operations", DS_TYPE_DERIVE },
+ { "wsrep_flow_control_sent", "operations", DS_TYPE_DERIVE },
+ { "wsrep_flow_control_paused", "operations", DS_TYPE_DERIVE },
+ { "wsrep_local_bf_aborts", "operations", DS_TYPE_DERIVE },
+ { "wsrep_local_cert_failures", "operations", DS_TYPE_DERIVE },
+ { "wsrep_local_commits", "operations", DS_TYPE_DERIVE },
+ { "wsrep_local_replays", "operations", DS_TYPE_DERIVE },
+ { "wsrep_received", "operations", DS_TYPE_DERIVE },
+ { "wsrep_replicated", "operations", DS_TYPE_DERIVE },
+
+ { "wsrep_received_bytes", "total_bytes", DS_TYPE_DERIVE },
+ { "wsrep_replicated_bytes", "total_bytes", DS_TYPE_DERIVE },
+
+ { "wsrep_apply_window", "gauge", DS_TYPE_GAUGE },
+ { "wsrep_commit_window", "gauge", DS_TYPE_GAUGE },
+
+ { "wsrep_cluster_size", "gauge", DS_TYPE_GAUGE },
+ { "wsrep_cert_deps_distance", "gauge", DS_TYPE_GAUGE },
+
+ { "wsrep_local_recv_queue", "queue_length", DS_TYPE_GAUGE },
+ { "wsrep_local_send_queue", "queue_length", DS_TYPE_GAUGE },
+
+ { NULL, NULL, 0}
+
+ };
+
+ query = "SHOW GLOBAL STATUS LIKE 'wsrep_%'";
+
+ res = exec_query (con, query);
+ if (res == NULL)
+ return (-1);
+
+ row = mysql_fetch_row (res);
+ if (row == NULL)
+ {
+ ERROR ("mysql plugin: Failed to get wsrep statistics: "
+ "`%s' did not return any rows.", query);
+ mysql_free_result (res);
+ return (-1);
+ }
+
+ while ((row = mysql_fetch_row (res)))
+ {
+ int i;
+ char *key;
+ unsigned long long val;
+
+ key = row[0];
+ val = atoll (row[1]);
+
+ for (i = 0; metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0; i++)
+ ;
+
+ if (metrics[i].key == NULL)
+ continue;
+
+ switch (metrics[i].ds_type) {
+ case DS_TYPE_GAUGE:
+ gauge_submit(metrics[i].type, key, (gauge_t)val, db);
+ break;
+ case DS_TYPE_DERIVE:
+ derive_submit(metrics[i].type, key, (derive_t)val, db);
+ break;
+ }
+ }
+
+ mysql_free_result(res);
+ return (0);
+} /* mysql_read_wsrep_stats */
+
+static int mysql_read (user_data_t *ud)
+{
+ mysql_database_t *db;
+ MYSQL *con;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ const char *query;
derive_t qcache_hits = 0;
derive_t qcache_inserts = 0;
unsigned long long traffic_incoming = 0ULL;
unsigned long long traffic_outgoing = 0ULL;
- unsigned long mysql_version = 0ULL;
+ unsigned long mysql_version = 0ULL;
if ((ud == NULL) || (ud->data == NULL))
{
if ((con = getconnection (db)) == NULL)
return (-1);
- mysql_version = mysql_get_server_version(con);
+ mysql_version = mysql_get_server_version(con);
query = "SHOW STATUS";
if (mysql_version >= 50002)
key = row[0];
val = atoll (row[1]);
- if (strncmp (key, "Com_",
+ if (strncmp (key, "Com_",
strlen ("Com_")) == 0)
{
if (val == 0ULL)
/* Ignore `prepared statements' */
if (strncmp (key, "Com_stmt_", strlen ("Com_stmt_")) != 0)
- counter_submit ("mysql_commands",
- key + strlen ("Com_"),
+ counter_submit ("mysql_commands",
+ key + strlen ("Com_"),
val, db);
}
- else if (strncmp (key, "Handler_",
+ else if (strncmp (key, "Handler_",
strlen ("Handler_")) == 0)
{
if (val == 0ULL)
continue;
- counter_submit ("mysql_handler",
- key + strlen ("Handler_"),
+ counter_submit ("mysql_handler",
+ key + strlen ("Handler_"),
val, db);
}
else if (strncmp (key, "Qcache_",
else if (strcmp (key, "Qcache_queries_in_cache") == 0)
qcache_queries_in_cache = (gauge_t) val;
}
- else if (strncmp (key, "Bytes_",
+ else if (strncmp (key, "Bytes_",
strlen ("Bytes_")) == 0)
{
if (strcmp (key, "Bytes_received") == 0)
else if (strcmp (key, "Bytes_sent") == 0)
traffic_outgoing += val;
}
- else if (strncmp (key, "Threads_",
+ else if (strncmp (key, "Threads_",
strlen ("Threads_")) == 0)
{
if (strcmp (key, "Threads_running") == 0)
counter_submit ("mysql_bpool_counters", "read_requests", val, db);
else if (strcmp (key, "Innodb_buffer_pool_reads") == 0)
counter_submit ("mysql_bpool_counters", "reads", val, db);
+ else if (strcmp (key, "Innodb_buffer_pool_wait_free") == 0)
+ counter_submit ("mysql_bpool_counters", "wait_free", val, db);
else if (strcmp (key, "Innodb_buffer_pool_write_requests") == 0)
counter_submit ("mysql_bpool_counters", "write_requests", val, db);
else if (strcmp (key, "Innodb_buffer_pool_bytes_data") == 0)
counter_submit ("mysql_innodb_dblwr", "writes", val, db);
else if (strcmp (key, "Innodb_dblwr_pages_written") == 0)
counter_submit ("mysql_innodb_dblwr", "written", val, db);
+ else if (strcmp (key, "Innodb_dblwr_page_size") == 0)
+ gauge_submit ("mysql_innodb_dblwr", "page_size", val, db);
/* log */
else if (strcmp (key, "Innodb_log_waits") == 0)
}
else if (strncmp (key, "Sort_", strlen ("Sort_")) == 0)
{
- counter_submit ("mysql_sort", key + strlen ("Sort_"),
- val, db);
+ if (strcmp (key, "Sort_merge_passes") == 0)
+ counter_submit ("mysql_sort_merge_passes", NULL, val, db);
+ else if (strcmp (key, "Sort_rows") == 0)
+ counter_submit ("mysql_sort_rows", NULL, val, db);
+ else if (strcmp (key, "Sort_range") == 0)
+ counter_submit ("mysql_sort", "range", val, db);
+ else if (strcmp (key, "Sort_scan") == 0)
+ counter_submit ("mysql_sort", "scan", val, db);
+
+ }
+ else if (strncmp (key, "Slow_queries", strlen ("Slow_queries")) == 0)
+ {
+ counter_submit ("mysql_slow_queries", NULL , val, db);
}
}
mysql_free_result (res); res = NULL;
traffic_submit (traffic_incoming, traffic_outgoing, db);
if (mysql_version >= 50600 && db->innodb_stats)
- mysql_read_innodb_stats (db, con);
+ mysql_read_innodb_stats (db, con);
if (db->master_stats)
mysql_read_master_stats (db, con);
if ((db->slave_stats) || (db->slave_notif))
mysql_read_slave_stats (db, con);
+ if (db->wsrep_stats)
+ mysql_read_wsrep_stats (db, con);
+
return (0);
} /* int mysql_read */
diff --git a/src/netapp.c b/src/netapp.c
index f761e290dfb509432f24fa6a2b5f6e517c2e5963..d73969646f7ca9be74c966fcd3da03d2754cc0a0 100644 (file)
--- a/src/netapp.c
+++ b/src/netapp.c
**/
#include "collectd.h"
+
#include "common.h"
#include "utils_ignorelist.h"
return d;
}
- d = malloc(sizeof(*d));
+ d = calloc (1, sizeof (*d));
if (d == NULL)
return (NULL);
- memset (d, 0, sizeof (*d));
d->next = NULL;
d->name = strdup(name);
@@ -513,10 +513,9 @@ static data_volume_usage_t *get_volume_usage (cfg_volume_usage_t *cvu, /* {{{ */
return (NULL);
/* Not found: allocate. */
- new = malloc (sizeof (*new));
+ new = calloc (1, sizeof (*new));
if (new == NULL)
return (NULL);
- memset (new, 0, sizeof (*new));
new->next = NULL;
new->name = strdup (name);
return (NULL);
/* Not found: allocate. */
- new = malloc (sizeof (*new));
+ new = calloc (1, sizeof (*new));
if (new == NULL)
return (NULL);
- memset (new, 0, sizeof (*new));
new->next = NULL;
new->name = strdup (name);
} /* }}} cdtime_t cna_child_get_cdtime */
-/*
+/*
* Query functions
*
* These functions are called with appropriate data returned by the libnetapp
static int cna_handle_wafl_data (const char *hostname, cfg_wafl_t *cfg_wafl, /* {{{ */
na_elem_t *data, cdtime_t interval)
{
- cfg_wafl_t perf_data;
+ cfg_wafl_t perf_data = { 0 };
const char *plugin_inst;
na_elem_t *instances;
- na_elem_t *counter;
na_elem_iter_t counter_iter;
- memset (&perf_data, 0, sizeof (perf_data));
-
perf_data.timestamp = cna_child_get_cdtime (data);
instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
/* Iterate over all counters */
counter_iter = na_child_iterator (na_elem_child (instances, "counters"));
- for (counter = na_iterator_next (&counter_iter);
+ for (na_elem_t *counter = na_iterator_next (&counter_iter);
counter != NULL;
counter = na_iterator_next (&counter_iter))
{
{
cdtime_t timestamp;
na_elem_t *instances;
- na_elem_t *instance;
na_elem_iter_t instance_iter;
disk_t *worst_disk = NULL;
if ((cfg_disk == NULL) || (data == NULL))
return (EINVAL);
-
+
timestamp = cna_child_get_cdtime (data);
instances = na_elem_child (data, "instances");
/* Iterate over all children */
instance_iter = na_child_iterator (instances);
- for (instance = na_iterator_next (&instance_iter);
+ for (na_elem_t *instance = na_iterator_next (&instance_iter);
instance != NULL;
instance = na_iterator_next(&instance_iter))
{
disk_t *old_data;
- disk_t new_data;
+ disk_t new_data = { 0 };
na_elem_iter_t counter_iterator;
- na_elem_t *counter;
- memset (&new_data, 0, sizeof (new_data));
new_data.timestamp = timestamp;
new_data.disk_busy_percent = NAN;
/* Look for the "disk_busy" and "base_for_disk_busy" counters */
counter_iterator = na_child_iterator(na_elem_child(instance, "counters"));
- for (counter = na_iterator_next(&counter_iterator);
+ for (na_elem_t *counter = na_iterator_next(&counter_iterator);
counter != NULL;
counter = na_iterator_next(&counter_iterator))
{
cdtime_t timestamp;
na_elem_t *elem_instances;
na_elem_iter_t iter_instances;
- na_elem_t *elem_instance;
-
+
timestamp = cna_child_get_cdtime (data);
elem_instances = na_elem_child(data, "instances");
}
iter_instances = na_child_iterator (elem_instances);
- for (elem_instance = na_iterator_next(&iter_instances);
+ for (na_elem_t *elem_instance = na_iterator_next(&iter_instances);
elem_instance != NULL;
elem_instance = na_iterator_next(&iter_instances))
{
const char *name;
- data_volume_perf_t perf_data;
+ data_volume_perf_t perf_data = { 0 };
data_volume_perf_t *v;
na_elem_t *elem_counters;
na_elem_iter_t iter_counters;
- na_elem_t *elem_counter;
- memset (&perf_data, 0, sizeof (perf_data));
perf_data.timestamp = timestamp;
name = na_child_get_string (elem_instance, "name");
continue;
iter_counters = na_child_iterator (elem_counters);
- for (elem_counter = na_iterator_next(&iter_counters);
+ for (na_elem_t *elem_counter = na_iterator_next(&iter_counters);
elem_counter != NULL;
elem_counter = na_iterator_next(&iter_counters))
{
static int cna_submit_volume_usage_data (const char *hostname, /* {{{ */
cfg_volume_usage_t *cfg_volume, int interval)
{
- data_volume_usage_t *v;
-
- for (v = cfg_volume->volumes; v != NULL; v = v->next)
+ for (data_volume_usage_t *v = cfg_volume->volumes; v != NULL; v = v->next)
{
char plugin_instance[DATA_MAX_NAME_LEN];
static int cna_change_volume_status (const char *hostname, /* {{{ */
data_volume_usage_t *v)
{
- notification_t n;
+ notification_t n = { 0 };
- memset (&n, 0, sizeof (n));
n.time = cdtime ();
sstrncpy (n.host, hostname, sizeof (n.host));
sstrncpy (n.plugin, "netapp", sizeof (n.plugin));
data_volume_usage_t *v)
{
uint64_t snap_used = 0, value;
- na_elem_t *data, *elem_snap, *elem_snapshots;
+ na_elem_t *data, *elem_snapshots;
na_elem_iter_t iter_snap;
data = na_server_invoke_elem(host->srv, v->snap_query);
}
iter_snap = na_child_iterator (elem_snapshots);
- for (elem_snap = na_iterator_next (&iter_snap);
+ for (na_elem_t *elem_snap = na_iterator_next (&iter_snap);
elem_snap != NULL;
elem_snap = na_iterator_next (&iter_snap))
{
static int cna_handle_volume_usage_data (const host_config_t *host, /* {{{ */
cfg_volume_usage_t *cfg_volume, na_elem_t *data)
{
- na_elem_t *elem_volume;
na_elem_t *elem_volumes;
na_elem_iter_t iter_volume;
}
iter_volume = na_child_iterator (elem_volumes);
- for (elem_volume = na_iterator_next (&iter_volume);
+ for (na_elem_t *elem_volume = na_iterator_next (&iter_volume);
elem_volume != NULL;
elem_volume = na_iterator_next (&iter_volume))
{
if ((v->flags & CFG_VOLUME_USAGE_SNAP) != 0)
cna_handle_volume_snap_usage(host, v);
-
+
if ((v->flags & CFG_VOLUME_USAGE_DF) == 0)
continue;
static int cna_handle_quota_data (const host_config_t *host, /* {{{ */
cfg_quota_t *cfg_quota, na_elem_t *data)
{
- na_elem_t *elem_quota;
na_elem_t *elem_quotas;
na_elem_iter_t iter_quota;
}
iter_quota = na_child_iterator (elem_quotas);
- for (elem_quota = na_iterator_next (&iter_quota);
+ for (na_elem_t *elem_quota = na_iterator_next (&iter_quota);
elem_quota != NULL;
elem_quota = na_iterator_next (&iter_quota))
{
static int cna_handle_snapvault_data (const char *hostname, /* {{{ */
cfg_snapvault_t *cfg_snapvault, na_elem_t *data, cdtime_t interval)
{
- na_elem_t *status;
na_elem_iter_t status_iter;
status = na_elem_child (data, "status-list");
}
status_iter = na_child_iterator (status);
- for (status = na_iterator_next (&status_iter);
+ for (na_elem_t *status = na_iterator_next (&status_iter);
status != NULL;
status = na_iterator_next (&status_iter))
{
const char *tag;
uint32_t records_count;
- uint32_t i;
records_count = na_child_get_uint32 (data, "records", UINT32_MAX);
if (records_count == UINT32_MAX)
DEBUG ("netapp plugin: Iterating %u SV records (tag = %s)", records_count, tag);
- for (i = 0; i < records_count; ++i) {
+ for (uint32_t i = 0; i < records_count; ++i) {
na_elem_t *elem;
elem = na_server_invoke (host->srv,
cfg_system_t *cfg_system, na_elem_t *data, int interval)
{
na_elem_t *instances;
- na_elem_t *counter;
na_elem_iter_t counter_iter;
derive_t disk_read = 0, disk_written = 0;
const char *instance;
cdtime_t timestamp;
-
+
timestamp = cna_child_get_cdtime (data);
instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
}
counter_iter = na_child_iterator (na_elem_child (instances, "counters"));
- for (counter = na_iterator_next (&counter_iter);
+ for (na_elem_t *counter = na_iterator_next (&counter_iter);
counter != NULL;
counter = na_iterator_next (&counter_iter))
{
&& (HAS_ALL_FLAGS (counter_flags, 0x01 | 0x02)))
submit_two_derive (hostname, instance, "disk_octets", NULL,
disk_read, disk_written, timestamp, interval);
-
+
if ((cfg_system->flags & CFG_SYSTEM_NET)
&& (HAS_ALL_FLAGS (counter_flags, 0x04 | 0x08)))
submit_two_derive (hostname, instance, "if_octets", NULL,
const oconfig_item_t *ci)
{
cfg_volume_perf_t *cfg_volume_perf;
- int i;
if ((host == NULL) || (ci == NULL))
return (EINVAL);
if (host->cfg_volume_perf == NULL)
{
- cfg_volume_perf = malloc (sizeof (*cfg_volume_perf));
+ cfg_volume_perf = calloc (1, sizeof (*cfg_volume_perf));
if (cfg_volume_perf == NULL)
return (ENOMEM);
- memset (cfg_volume_perf, 0, sizeof (*cfg_volume_perf));
/* Set default flags */
cfg_volume_perf->query = NULL;
host->cfg_volume_perf = cfg_volume_perf;
}
cfg_volume_perf = host->cfg_volume_perf;
-
- for (i = 0; i < ci->children_num; ++i) {
+
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *item = ci->children + i;
-
+
/* if (!item || !item->key || !*item->key) continue; */
if (strcasecmp(item->key, "Interval") == 0)
cna_config_get_interval (item, &cfg_volume_perf->interval);
@@ -2526,24 +2505,22 @@ static void cna_config_volume_usage_default (cfg_volume_usage_t *cvu, /* {{{ */
static int cna_config_quota (host_config_t *host, oconfig_item_t *ci) /* {{{ */
{
cfg_quota_t *cfg_quota;
- int i;
if ((host == NULL) || (ci == NULL))
return (EINVAL);
if (host->cfg_quota == NULL)
{
- cfg_quota = malloc (sizeof (*cfg_quota));
+ cfg_quota = calloc (1, sizeof (*cfg_quota));
if (cfg_quota == NULL)
return (ENOMEM);
- memset (cfg_quota, 0, sizeof (*cfg_quota));
cfg_quota->query = NULL;
host->cfg_quota = cfg_quota;
}
cfg_quota = host->cfg_quota;
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *item = ci->children + i;
if (strcasecmp (item->key, "Interval") == 0)
@@ -2559,17 +2536,15 @@ static int cna_config_quota (host_config_t *host, oconfig_item_t *ci) /* {{{ */
/* Corresponds to a <Disks /> block */
static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */
cfg_disk_t *cfg_disk;
- int i;
if ((host == NULL) || (ci == NULL))
return (EINVAL);
if (host->cfg_disk == NULL)
{
- cfg_disk = malloc (sizeof (*cfg_disk));
+ cfg_disk = calloc (1, sizeof (*cfg_disk));
if (cfg_disk == NULL)
return (ENOMEM);
- memset (cfg_disk, 0, sizeof (*cfg_disk));
/* Set default flags */
cfg_disk->flags = CFG_DISK_ALL;
@@ -2579,10 +2554,10 @@ static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */
host->cfg_disk = cfg_disk;
}
cfg_disk = host->cfg_disk;
-
- for (i = 0; i < ci->children_num; ++i) {
+
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *item = ci->children + i;
-
+
/* if (!item || !item->key || !*item->key) continue; */
if (strcasecmp(item->key, "Interval") == 0)
cna_config_get_interval (item, &cfg_disk->interval);
@@ -2605,17 +2580,15 @@ static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */
static int cna_config_wafl(host_config_t *host, oconfig_item_t *ci) /* {{{ */
{
cfg_wafl_t *cfg_wafl;
- int i;
if ((host == NULL) || (ci == NULL))
return (EINVAL);
if (host->cfg_wafl == NULL)
{
- cfg_wafl = malloc (sizeof (*cfg_wafl));
+ cfg_wafl = calloc (1, sizeof (*cfg_wafl));
if (cfg_wafl == NULL)
return (ENOMEM);
- memset (cfg_wafl, 0, sizeof (*cfg_wafl));
/* Set default flags */
cfg_wafl->flags = CFG_WAFL_ALL;
}
cfg_wafl = host->cfg_wafl;
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *item = ci->children + i;
-
+
if (strcasecmp(item->key, "Interval") == 0)
cna_config_get_interval (item, &cfg_wafl->interval);
else if (!strcasecmp(item->key, "GetNameCache"))
const oconfig_item_t *ci)
{
cfg_volume_usage_t *cfg_volume_usage;
- int i;
if ((host == NULL) || (ci == NULL))
return (EINVAL);
if (host->cfg_volume_usage == NULL)
{
- cfg_volume_usage = malloc (sizeof (*cfg_volume_usage));
+ cfg_volume_usage = calloc (1, sizeof (*cfg_volume_usage));
if (cfg_volume_usage == NULL)
return (ENOMEM);
- memset (cfg_volume_usage, 0, sizeof (*cfg_volume_usage));
/* Set default flags */
cfg_volume_usage->query = NULL;
host->cfg_volume_usage = cfg_volume_usage;
}
cfg_volume_usage = host->cfg_volume_usage;
-
- for (i = 0; i < ci->children_num; ++i) {
+
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *item = ci->children + i;
-
+
/* if (!item || !item->key || !*item->key) continue; */
if (strcasecmp(item->key, "Interval") == 0)
cna_config_get_interval (item, &cfg_volume_usage->interval);
const oconfig_item_t *ci)
{
cfg_snapvault_t *cfg_snapvault;
- int i;
if ((host == NULL) || (ci == NULL))
return EINVAL;
if (host->cfg_snapvault == NULL)
{
- cfg_snapvault = malloc (sizeof (*cfg_snapvault));
+ cfg_snapvault = calloc (1, sizeof (*cfg_snapvault));
if (cfg_snapvault == NULL)
return ENOMEM;
- memset (cfg_snapvault, 0, sizeof (*cfg_snapvault));
cfg_snapvault->query = NULL;
host->cfg_snapvault = cfg_snapvault;
cfg_snapvault = host->cfg_snapvault;
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *item = ci->children + i;
if (strcasecmp (item->key, "Interval") == 0)
oconfig_item_t *ci)
{
cfg_system_t *cfg_system;
- int i;
-
+
if ((host == NULL) || (ci == NULL))
return (EINVAL);
if (host->cfg_system == NULL)
{
- cfg_system = malloc (sizeof (*cfg_system));
+ cfg_system = calloc (1, sizeof (*cfg_system));
if (cfg_system == NULL)
return (ENOMEM);
- memset (cfg_system, 0, sizeof (*cfg_system));
/* Set default flags */
cfg_system->flags = CFG_SYSTEM_ALL;
}
cfg_system = host->cfg_system;
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *item = ci->children + i;
if (strcasecmp(item->key, "Interval") == 0) {
{
host_config_t *host;
- host = malloc(sizeof(*host));
- if (! host)
+ host = calloc (1, sizeof (*host));
+ if (host == NULL)
return (NULL);
- memset (host, 0, sizeof (*host));
host->name = NULL;
host->protocol = NA_SERVER_TRANSPORT_HTTPS;
static int cna_register_host (host_config_t *host) /* {{{ */
{
char cb_name[256];
- struct timespec interval;
- user_data_t ud;
if (host->vfiler)
ssnprintf (cb_name, sizeof (cb_name), "netapp-%s-%s",
else
ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
- CDTIME_T_TO_TIMESPEC (host->interval, &interval);
-
- memset (&ud, 0, sizeof (ud));
- ud.data = host;
- ud.free_func = (void (*) (void *)) free_host_config;
+ user_data_t ud = {
+ .data = host,
+ .free_func = (void (*) (void *)) free_host_config
+ };
plugin_register_complex_read (/* group = */ NULL, cb_name,
/* callback = */ cna_read,
- /* interval = */ (host->interval > 0) ? &interval : NULL,
+ /* interval = */ host->interval,
/* user data = */ &ud);
return (0);
oconfig_item_t *item;
_Bool is_vfiler = 0;
int status;
- int i;
if (! strcasecmp (ci->key, "VFiler"))
is_vfiler = 1;
if (status != 0)
return (1);
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
item = ci->children + i;
status = 0;
static int cna_init (void) /* {{{ */
{
- char err[256];
+ char err[256] = { 0 };
- memset (err, 0, sizeof (err));
if (!na_startup(err, sizeof(err))) {
err[sizeof (err) - 1] = 0;
ERROR("netapp plugin: Error initializing netapp API: %s", err);
} /* }}} int cna_read */
static int cna_config (oconfig_item_t *ci) { /* {{{ */
- int i;
oconfig_item_t *item;
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
item = ci->children + i;
if (strcasecmp(item->key, "Host") == 0)
diff --git a/src/netlink.c b/src/netlink.c
index aa9760f9328b78eb87e14f70501bc1622a57f12d..cfca46f7494084de4939288f72a95632c2fcdd44 100644 (file)
--- a/src/netlink.c
+++ b/src/netlink.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include <asm/types.h>
-#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
{
ir_ignorelist_t *entry;
- entry = (ir_ignorelist_t *) malloc (sizeof (ir_ignorelist_t));
+ entry = calloc (1, sizeof (*entry));
if (entry == NULL)
return (-1);
- memset (entry, '\0', sizeof (ir_ignorelist_t));
-
if (strcasecmp (dev, "All") != 0)
{
entry->device = strdup (dev);
static int check_ignorelist (const char *dev,
const char *type, const char *type_instance)
{
- ir_ignorelist_t *i;
-
assert ((dev != NULL) && (type != NULL));
if (ir_ignorelist_head == NULL)
return (ir_ignorelist_invert ? 0 : 1);
- for (i = ir_ignorelist_head; i != NULL; i = i->next)
+ for (ir_ignorelist_t *i = ir_ignorelist_head; i != NULL; i = i->next)
{
/* i->device == NULL => match all devices */
if ((i->device != NULL)
{
char **temp;
- temp = (char **) realloc (iflist, (msg->ifi_index + 1) * sizeof (char *));
+ temp = realloc (iflist, (msg->ifi_index + 1) * sizeof (char *));
if (temp == NULL)
{
ERROR ("netlink plugin: update_iflist: realloc failed.");
const char *kind = NULL;
/* char *type_instance; */
- char *tc_type;
+ const char *tc_type;
char tc_inst[DATA_MAX_NAME_LEN];
_Bool stats_submitted = 0;
int ret;
unsigned int seq, portid;
- size_t ifindex;
-
static const int type_id[] = { RTM_GETQDISC, RTM_GETTCLASS, RTM_GETTFILTER };
static const char *type_name[] = { "qdisc", "class", "filter" };
/* `link_filter_cb' will update `iflist' which is used here to iterate
* over all interfaces. */
- for (ifindex = 1; ifindex < iflist_len; ifindex++)
+ for (size_t ifindex = 1; ifindex < iflist_len; ifindex++)
{
struct tcmsg *tm;
- size_t type_index;
if (iflist[ifindex] == NULL)
continue;
- for (type_index = 0; type_index < STATIC_ARRAY_SIZE (type_id); type_index++)
+ for (size_t type_index = 0; type_index < STATIC_ARRAY_SIZE (type_id); type_index++)
{
if (check_ignorelist (iflist[ifindex], type_name[type_index], NULL))
{
diff --git a/src/network.c b/src/network.c
index f1140608851417958a0dfd9f1382e49d67684930..9a0f429aad88b64bca940484f107978c0f8d0016 100644 (file)
--- a/src/network.c
+++ b/src/network.c
#define _BSD_SOURCE /* For struct ip_mreq */
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
-#include "configfile.h"
#include "utils_fbhash.h"
-#include "utils_avltree.h"
#include "utils_cache.h"
#include "utils_complain.h"
#include "network.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
#endif
#if HAVE_LIBGCRYPT
-# include <pthread.h>
# if defined __APPLE__
/* default xcode compiler throws warnings even when deprecated functionality
* is not used. -Werror breaks the build because of erroneous warnings.
static int network_config_ttl = 0;
/* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */
static size_t network_config_packet_size = 1452;
-static int network_config_forward = 0;
-static int network_config_stats = 0;
+static _Bool network_config_forward = 0;
+static _Bool network_config_stats = 0;
static sockent_t *sending_sockets = NULL;
static char *send_buffer;
static char *send_buffer_ptr;
static int send_buffer_fill;
+static cdtime_t send_buffer_last_update;
static value_list_t send_buffer_vl = VALUE_LIST_STATIC;
static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
_Bool received = 0;
int status;
- if (network_config_forward != 0)
+ if (network_config_forward)
return (1);
if (vl->meta == NULL)
static _Bool check_notify_received (const notification_t *n) /* {{{ */
{
- notification_meta_t *ptr;
-
- for (ptr = n->meta; ptr != NULL; ptr = ptr->next)
+ for (notification_meta_t *ptr = n->meta; ptr != NULL; ptr = ptr->next)
if ((strcmp ("network:received", ptr->name) == 0)
&& (ptr->type == NM_TYPE_BOOLEAN))
return ((_Bool) ptr->nm_value.nm_boolean);
{
int status;
- if ((vl->time <= 0)
- || (strlen (vl->host) <= 0)
- || (strlen (vl->plugin) <= 0)
- || (strlen (vl->type) <= 0))
+ if ((vl->time == 0)
+ || (strlen (vl->host) == 0)
+ || (strlen (vl->plugin) == 0)
+ || (strlen (vl->type) == 0))
return (-EINVAL);
if (!check_receive_okay (vl))
} /* }}} int network_get_aes256_cypher */
#endif /* HAVE_LIBGCRYPT */
-static int write_part_values (char **ret_buffer, int *ret_buffer_len,
+static int write_part_values (char **ret_buffer, size_t *ret_buffer_len,
const data_set_t *ds, const value_list_t *vl)
{
char *packet_ptr;
- int packet_len;
+ size_t packet_len;
int num_values;
part_header_t pkg_ph;
uint8_t *pkg_values_types;
value_t *pkg_values;
- int offset;
- int i;
+ size_t offset;
num_values = vl->values_len;
packet_len = sizeof (part_header_t) + sizeof (uint16_t)
if (*ret_buffer_len < packet_len)
return (-1);
- pkg_values_types = (uint8_t *) malloc (num_values * sizeof (uint8_t));
+ pkg_values_types = malloc (num_values * sizeof (*pkg_values_types));
if (pkg_values_types == NULL)
{
ERROR ("network plugin: write_part_values: malloc failed.");
return (-1);
}
- pkg_values = (value_t *) malloc (num_values * sizeof (value_t));
+ pkg_values = malloc (num_values * sizeof (*pkg_values));
if (pkg_values == NULL)
{
free (pkg_values_types);
pkg_num_values = htons ((uint16_t) vl->values_len);
- for (i = 0; i < num_values; i++)
+ for (int i = 0; i < num_values; i++)
{
pkg_values_types[i] = (uint8_t) ds->ds[i].type;
switch (ds->ds[i].type)
return (0);
} /* int write_part_values */
-static int write_part_number (char **ret_buffer, int *ret_buffer_len,
+static int write_part_number (char **ret_buffer, size_t *ret_buffer_len,
int type, uint64_t value)
{
char *packet_ptr;
- int packet_len;
+ size_t packet_len;
part_header_t pkg_head;
uint64_t pkg_value;
- int offset;
+ size_t offset;
packet_len = sizeof (pkg_head) + sizeof (pkg_value);
return (0);
} /* int write_part_number */
-static int write_part_string (char **ret_buffer, int *ret_buffer_len,
- int type, const char *str, int str_len)
+static int write_part_string (char **ret_buffer, size_t *ret_buffer_len,
+ int type, const char *str, size_t str_len)
{
char *buffer;
- int buffer_len;
+ size_t buffer_len;
uint16_t pkg_type;
uint16_t pkg_length;
- int offset;
+ size_t offset;
buffer_len = 2 * sizeof (uint16_t) + str_len + 1;
if (*ret_buffer_len < buffer_len)
} /* int write_part_string */
static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
- value_t **ret_values, int *ret_num_values)
+ value_t **ret_values, size_t *ret_num_values)
{
char *buffer = *ret_buffer;
size_t buffer_len = *ret_buffer_len;
uint16_t tmp16;
size_t exp_size;
- int i;
uint16_t pkg_length;
uint16_t pkg_type;
- uint16_t pkg_numval;
+ size_t pkg_numval;
uint8_t *pkg_types;
value_t *pkg_values;
memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
buffer += sizeof (tmp16);
- pkg_numval = ntohs (tmp16);
+ pkg_numval = (size_t) ntohs (tmp16);
assert (pkg_type == TYPE_VALUES);
exp_size, buffer_len);
return (-1);
}
+ assert (pkg_numval <= ((buffer_len - 6) / 9));
if (pkg_length != exp_size)
{
return (-1);
}
- pkg_types = (uint8_t *) malloc (pkg_numval * sizeof (uint8_t));
- pkg_values = (value_t *) malloc (pkg_numval * sizeof (value_t));
+ pkg_types = calloc (pkg_numval, sizeof (*pkg_types));
+ pkg_values = calloc (pkg_numval, sizeof (*pkg_values));
if ((pkg_types == NULL) || (pkg_values == NULL))
{
sfree (pkg_types);
sfree (pkg_values);
- ERROR ("network plugin: parse_part_values: malloc failed.");
+ ERROR ("network plugin: parse_part_values: calloc failed.");
return (-1);
}
- memcpy ((void *) pkg_types, (void *) buffer, pkg_numval * sizeof (uint8_t));
- buffer += pkg_numval * sizeof (uint8_t);
- memcpy ((void *) pkg_values, (void *) buffer, pkg_numval * sizeof (value_t));
- buffer += pkg_numval * sizeof (value_t);
+ memcpy (pkg_types, buffer, pkg_numval * sizeof (*pkg_types));
+ buffer += pkg_numval * sizeof (*pkg_types);
+ memcpy (pkg_values, buffer, pkg_numval * sizeof (*pkg_values));
+ buffer += pkg_numval * sizeof (*pkg_values);
- for (i = 0; i < pkg_numval; i++)
+ for (size_t i = 0; i < pkg_numval; i++)
{
switch (pkg_types[i])
{
uint16_t pkg_length;
size_t payload_size;
- if (output_len <= 0)
+ if (output_len == 0)
return (EINVAL);
if (buffer_len < header_size)
if (memcmp (pss.hash, hash, sizeof (pss.hash)) != 0)
{
WARNING ("network plugin: Verifying HMAC-SHA-256 signature failed: "
- "Hash mismatch.");
+ "Hash mismatch. Username: %s", pss.username);
}
else
{
size_t buffer_offset;
uint16_t username_len;
part_encryption_aes256_t pea;
- unsigned char hash[sizeof (pea.hash)];
+ unsigned char hash[sizeof (pea.hash)] = { 0 };
gcry_cipher_hd_t cypher;
gcry_error_t err;
BUFFER_READ (&username_len, sizeof (username_len));
username_len = ntohs (username_len);
- if ((username_len <= 0)
+ if ((username_len == 0)
|| (username_len > (part_size - (PART_ENCRYPTION_AES256_SIZE + 1))))
{
NOTICE ("network plugin: parse_part_encr_aes256: "
pea.username);
if (cypher == NULL)
{
+ ERROR ("network plugin: Failed to get cypher. Username: %s", pea.username);
sfree (pea.username);
return (-1);
}
if (err != 0)
{
sfree (pea.username);
- ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
- gcry_strerror (err));
+ ERROR ("network plugin: gcry_cipher_decrypt returned: %s. Username: %s",
+ gcry_strerror (err), pea.username);
return (-1);
}
assert (buffer_offset == (part_size - payload_len));
/* Check hash sum */
- memset (hash, 0, sizeof (hash));
gcry_md_hash_buffer (GCRY_MD_SHA1, hash,
buffer + buffer_offset, payload_len);
if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
{
+ ERROR ("network plugin: Checksum mismatch. Username: %s", pea.username);
sfree (pea.username);
- ERROR ("network plugin: Decryption failed: Checksum mismatch.");
return (-1);
}
warning_has_been_printed = 1;
}
- *ret_buffer += ph_length;
+ *ret_buffer = (void *) (((char *) *ret_buffer) + ph_length);
*ret_buffer_size -= ph_length;
return (0);
int status;
value_list_t vl = VALUE_LIST_INIT;
- notification_t n;
+ notification_t n = { 0 };
#if HAVE_LIBGCRYPT
int packet_was_signed = (flags & PP_SIGNED);
- int packet_was_encrypted = (flags & PP_ENCRYPTED);
+ int packet_was_encrypted = (flags & PP_ENCRYPTED);
int printed_ignore_warning = 0;
#endif /* HAVE_LIBGCRYPT */
memset (&vl, '\0', sizeof (vl));
- memset (&n, '\0', sizeof (n));
status = 0;
while ((status == 0) && (0 < buffer_size)
(void *) buffer,
sizeof (pkg_type));
memcpy ((void *) &pkg_length,
- (void *) (buffer + sizeof (pkg_type)),
+ (void *) (((char *) buffer) + sizeof (pkg_type)),
sizeof (pkg_length));
pkg_length = ntohs (pkg_length);
"unknown severity %i.",
n.severity);
}
- else if (n.time <= 0)
+ else if (n.time == 0)
{
INFO ("network plugin: "
"Ignoring notification with "
"time == 0.");
}
- else if (strlen (n.message) <= 0)
+ else if (strlen (n.message) == 0)
{
INFO ("network plugin: "
"Ignoring notification with "
static void free_sockent_server (struct sockent_server *ses) /* {{{ */
{
- size_t i;
-
- for (i = 0; i < ses->fd_num; i++)
+ for (size_t i = 0; i < ses->fd_num; i++)
{
if (ses->fd[i] >= 0)
{
@@ -1786,18 +1773,16 @@ static int network_set_interface (const sockent_t *se, const struct addrinfo *ai
* index is preferred here, because of its similarity
* to the way IPv6 handles this. Unfortunately, it
* appears not to be portable. */
- struct ip_mreqn mreq;
-
- memset (&mreq, 0, sizeof (mreq));
- mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
- mreq.imr_address.s_addr = ntohl (INADDR_ANY);
- mreq.imr_ifindex = se->interface;
+ struct ip_mreqn mreq = {
+ .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+ .imr_address.s_addr = ntohl (INADDR_ANY),
+ .imr_ifindex = se->interface
+ };
#else
- struct ip_mreq mreq;
-
- memset (&mreq, 0, sizeof (mreq));
- mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
- mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+ struct ip_mreq mreq = {
+ .imr_multiaddr.s_addr = addr->sin_addr.s_addr,
+ .imr_interface.s_addr = ntohl (INADDR_ANY)
+ };
#endif
if (setsockopt (se->data.client.fd, IPPROTO_IP, IP_MULTICAST_IF,
if ((type != SOCKENT_TYPE_CLIENT) && (type != SOCKENT_TYPE_SERVER))
return (NULL);
- se = malloc (sizeof (*se));
+ se = calloc (1, sizeof (*se));
if (se == NULL)
return (NULL);
- memset (se, 0, sizeof (*se));
se->type = type;
se->node = NULL;
static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
struct sockent_client *client;
- struct addrinfo ai_hints;
- struct addrinfo *ai_list = NULL, *ai_ptr;
+ struct addrinfo *ai_list;
int status;
_Bool reconnect = 0;
cdtime_t now;
if (client->fd >= 0 && !reconnect) /* already connected and not stale*/
return (0);
- memset (&ai_hints, 0, sizeof (ai_hints));
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_DGRAM;
- ai_hints.ai_protocol = IPPROTO_UDP;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_protocol = IPPROTO_UDP,
+ .ai_socktype = SOCK_DGRAM
+ };
status = getaddrinfo (se->node,
(se->service != NULL) ? se->service : NET_DEFAULT_PORT,
se->node);
}
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
if (client->fd >= 0) /* when we reconnect */
sockent_client_disconnect(se);
continue;
}
- client->addr = malloc (sizeof (*client->addr));
+ client->addr = calloc (1, sizeof (*client->addr));
if (client->addr == NULL)
{
- ERROR ("network plugin: malloc failed.");
+ ERROR ("network plugin: calloc failed.");
close (client->fd);
client->fd = -1;
continue;
}
- memset (client->addr, 0, sizeof (*client->addr));
assert (sizeof (*client->addr) >= ai_ptr->ai_addrlen);
memcpy (client->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
client->addrlen = ai_ptr->ai_addrlen;
/* Open the file descriptors for a initialized sockent structure. */
static int sockent_server_listen (sockent_t *se) /* {{{ */
{
- struct addrinfo ai_hints;
- struct addrinfo *ai_list, *ai_ptr;
+ struct addrinfo *ai_list;
int status;
const char *node;
DEBUG ("network plugin: sockent_server_listen: node = %s; service = %s;",
node, service);
- memset (&ai_hints, 0, sizeof (ai_hints));
- ai_hints.ai_flags = 0;
-#ifdef AI_PASSIVE
- ai_hints.ai_flags |= AI_PASSIVE;
-#endif
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_DGRAM;
- ai_hints.ai_protocol = IPPROTO_UDP;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG | AI_PASSIVE,
+ .ai_protocol = IPPROTO_UDP,
+ .ai_socktype = SOCK_DGRAM
+ };
status = getaddrinfo (node, service, &ai_hints, &ai_list);
if (status != 0)
return (-1);
}
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
int *tmp;
freeaddrinfo (ai_list);
- if (se->data.server.fd_num <= 0)
+ if (se->data.server.fd_num == 0)
return (-1);
return (0);
} /* }}} int sockent_server_listen */
if (se->type == SOCKENT_TYPE_SERVER)
{
struct pollfd *tmp;
- size_t i;
tmp = realloc (listen_sockets_pollfd,
sizeof (*tmp) * (listen_sockets_num
listen_sockets_pollfd = tmp;
tmp = listen_sockets_pollfd + listen_sockets_num;
- for (i = 0; i < se->data.server.fd_num; i++)
+ for (size_t i = 0; i < se->data.server.fd_num; i++)
{
memset (tmp + i, 0, sizeof (*tmp));
tmp[i].fd = se->data.server.fd[i];
char buffer[network_config_packet_size];
int buffer_len;
- int i;
int status = 0;
receive_list_entry_t *private_list_head;
break;
}
- for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
+ for (size_t i = 0; (i < listen_sockets_num) && (status > 0); i++)
{
receive_list_entry_t *ent;
* these entries in the dispatch thread but put them in
* another list, so we don't have to allocate more and
* more of these structures. */
- ent = malloc (sizeof (receive_list_entry_t));
+ ent = calloc (1, sizeof (*ent));
if (ent == NULL)
{
- ERROR ("network plugin: malloc failed.");
+ ERROR ("network plugin: calloc failed.");
status = ENOMEM;
break;
}
- memset (ent, 0, sizeof (receive_list_entry_t));
+
ent->data = malloc (network_config_packet_size);
if (ent->data == NULL)
{
memset (send_buffer, 0, network_config_packet_size);
send_buffer_ptr = send_buffer;
send_buffer_fill = 0;
+ send_buffer_last_update = 0;
memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
} /* int network_init_buffer */
-static void networt_send_buffer_plain (sockent_t *se, /* {{{ */
+static void network_send_buffer_plain (sockent_t *se, /* {{{ */
const char *buffer, size_t buffer_size)
{
int status;
break;
} /* while (42) */
-} /* }}} void networt_send_buffer_plain */
+} /* }}} void network_send_buffer_plain */
#if HAVE_LIBGCRYPT
#define BUFFER_ADD(p,s) do { \
buffer_offset += (s); \
} while (0)
-static void networt_send_buffer_signed (sockent_t *se, /* {{{ */
+static void network_send_buffer_signed (sockent_t *se, /* {{{ */
const char *in_buffer, size_t in_buffer_size)
{
- part_signature_sha256_t ps;
char buffer[BUFF_SIG_SIZE + in_buffer_size];
size_t buffer_offset;
size_t username_len;
in_buffer, in_buffer_size);
/* Initialize the `ps' structure. */
- memset (&ps, 0, sizeof (ps));
- ps.head.type = htons (TYPE_SIGN_SHA256);
- ps.head.length = htons (PART_SIGNATURE_SHA256_SIZE + username_len);
+ part_signature_sha256_t ps = {
+ .head.type = htons (TYPE_SIGN_SHA256),
+ .head.length = htons (PART_SIGNATURE_SHA256_SIZE + username_len)
+ };
/* Calculate the hash value. */
gcry_md_write (hd, buffer + PART_SIGNATURE_SHA256_SIZE,
hd = NULL;
buffer_offset = PART_SIGNATURE_SHA256_SIZE + username_len + in_buffer_size;
- networt_send_buffer_plain (se, buffer, buffer_offset);
-} /* }}} void networt_send_buffer_signed */
+ network_send_buffer_plain (se, buffer, buffer_offset);
+} /* }}} void network_send_buffer_signed */
-static void networt_send_buffer_encrypted (sockent_t *se, /* {{{ */
+static void network_send_buffer_encrypted (sockent_t *se, /* {{{ */
const char *in_buffer, size_t in_buffer_size)
{
- part_encryption_aes256_t pea;
char buffer[BUFF_SIG_SIZE + in_buffer_size];
size_t buffer_size;
size_t buffer_offset;
gcry_cipher_hd_t cypher;
/* Initialize the header fields */
- memset (&pea, 0, sizeof (pea));
- pea.head.type = htons (TYPE_ENCR_AES256);
-
- pea.username = se->data.client.username;
+ part_encryption_aes256_t pea = {
+ .head.type = htons (TYPE_ENCR_AES256),
+ .username = se->data.client.username
+ };
username_len = strlen (pea.username);
if ((PART_ENCRYPTION_AES256_SIZE + username_len) > BUFF_SIG_SIZE)
- sizeof (pea.hash);
assert (buffer_size <= sizeof (buffer));
- DEBUG ("network plugin: networt_send_buffer_encrypted: "
+ DEBUG ("network plugin: network_send_buffer_encrypted: "
"buffer_size = %zu;", buffer_size);
pea.head.length = htons ((uint16_t) (PART_ENCRYPTION_AES256_SIZE
}
/* Send it out without further modifications */
- networt_send_buffer_plain (se, buffer, buffer_size);
-} /* }}} void networt_send_buffer_encrypted */
+ network_send_buffer_plain (se, buffer, buffer_size);
+} /* }}} void network_send_buffer_encrypted */
#undef BUFFER_ADD
#endif /* HAVE_LIBGCRYPT */
static void network_send_buffer (char *buffer, size_t buffer_len) /* {{{ */
{
- sockent_t *se;
-
DEBUG ("network plugin: network_send_buffer: buffer_len = %zu", buffer_len);
- for (se = sending_sockets; se != NULL; se = se->next)
+ for (sockent_t *se = sending_sockets; se != NULL; se = se->next)
{
#if HAVE_LIBGCRYPT
if (se->data.client.security_level == SECURITY_LEVEL_ENCRYPT)
- networt_send_buffer_encrypted (se, buffer, buffer_len);
+ network_send_buffer_encrypted (se, buffer, buffer_len);
else if (se->data.client.security_level == SECURITY_LEVEL_SIGN)
- networt_send_buffer_signed (se, buffer, buffer_len);
+ network_send_buffer_signed (se, buffer, buffer_len);
else /* if (se->data.client.security_level == SECURITY_LEVEL_NONE) */
#endif /* HAVE_LIBGCRYPT */
- networt_send_buffer_plain (se, buffer, buffer_len);
+ network_send_buffer_plain (se, buffer, buffer_len);
} /* for (sending_sockets) */
} /* }}} void network_send_buffer */
-static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */
+static int add_to_buffer (char *buffer, size_t buffer_size, /* {{{ */
value_list_t *vl_def,
const data_set_t *ds, const value_list_t *vl)
{
/* status == bytes added to the buffer */
send_buffer_fill += status;
send_buffer_ptr += status;
+ send_buffer_last_update = cdtime();
stats_values_sent++;
}
return ((status < 0) ? -1 : 0);
} /* int network_write */
-static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
- int *retval)
-{
- if ((ci->values_num != 1)
- || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
- && (ci->values[0].type != OCONFIG_TYPE_STRING)))
- {
- ERROR ("network plugin: The `%s' config option needs "
- "exactly one boolean argument.", ci->key);
- return (-1);
- }
-
- if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
- {
- if (ci->values[0].value.boolean)
- *retval = 1;
- else
- *retval = 0;
- }
- else
- {
- char *str = ci->values[0].value.string;
-
- if (IS_TRUE (str))
- *retval = 1;
- else if (IS_FALSE (str))
- *retval = 0;
- else
- {
- ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
- "option as boolean value.",
- str, ci->key);
- return (-1);
- }
- }
-
- return (0);
-} /* }}} int network_config_set_boolean */
-
static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
{
- int tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
- {
- WARNING ("network plugin: The `TimeToLive' config option needs exactly "
- "one numeric argument.");
- return (-1);
- }
+ int tmp = 0;
- tmp = (int) ci->values[0].value.number;
- if ((tmp > 0) && (tmp <= 255))
+ if (cf_util_get_int (ci, &tmp) != 0)
+ return (-1);
+ else if ((tmp > 0) && (tmp <= 255))
network_config_ttl = tmp;
else {
WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
static int network_config_set_interface (const oconfig_item_t *ci, /* {{{ */
int *interface)
{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("network plugin: The `Interface' config option needs exactly "
- "one string argument.");
- return (-1);
- }
+ char if_name[256];
- if (interface == NULL)
+ if (cf_util_get_string_buffer (ci, if_name, sizeof (if_name)) != 0)
return (-1);
- *interface = if_nametoindex (ci->values[0].value.string);
-
+ *interface = if_nametoindex (if_name);
return (0);
} /* }}} int network_config_set_interface */
static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
{
- int tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
- {
- WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
- "one numeric argument.");
- return (-1);
- }
+ int tmp = 0;
- tmp = (int) ci->values[0].value.number;
- if ((tmp >= 1024) && (tmp <= 65535))
+ if (cf_util_get_int (ci, &tmp) != 0)
+ return (-1);
+ else if ((tmp >= 1024) && (tmp <= 65535))
network_config_packet_size = tmp;
-
- return (0);
-} /* }}} int network_config_set_buffer_size */
-
-#if HAVE_LIBGCRYPT
-static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
- char **ret_string)
-{
- char *tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("network plugin: The `%s' config option needs exactly "
- "one string argument.", ci->key);
+ else {
+ WARNING ("network plugin: The `MaxPacketSize' must be between 1024 and 65535.");
return (-1);
}
- tmp = strdup (ci->values[0].value.string);
- if (tmp == NULL)
- return (-1);
-
- sfree (*ret_string);
- *ret_string = tmp;
-
return (0);
-} /* }}} int network_config_set_string */
-#endif /* HAVE_LIBGCRYPT */
+} /* }}} int network_config_set_buffer_size */
#if HAVE_LIBGCRYPT
static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
{
sockent_t *se;
int status;
- int i;
if ((ci->values_num < 1) || (ci->values_num > 2)
|| (ci->values[0].type != OCONFIG_TYPE_STRING)
if (ci->values_num >= 2)
se->service = strdup (ci->values[1].value.string);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
#if HAVE_LIBGCRYPT
if (strcasecmp ("AuthFile", child->key) == 0)
- network_config_set_string (child, &se->data.server.auth_file);
+ cf_util_get_string (child, &se->data.server.auth_file);
else if (strcasecmp ("SecurityLevel", child->key) == 0)
network_config_set_security_level (child,
&se->data.server.security_level);
else
#endif /* HAVE_LIBGCRYPT */
if (strcasecmp ("Interface", child->key) == 0)
- network_config_set_interface (child,
- &se->interface);
+ network_config_set_interface (child, &se->interface);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
status = sockent_server_listen (se);
if (status != 0)
{
- ERROR ("network plugin: network_config_add_server: sockent_server_listen failed.");
+ ERROR ("network plugin: network_config_add_listen: sockent_server_listen failed.");
sockent_destroy (se);
return (-1);
}
{
sockent_t *se;
int status;
- int i;
if ((ci->values_num < 1) || (ci->values_num > 2)
|| (ci->values[0].type != OCONFIG_TYPE_STRING)
if (ci->values_num >= 2)
se->service = strdup (ci->values[1].value.string);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
#if HAVE_LIBGCRYPT
if (strcasecmp ("Username", child->key) == 0)
- network_config_set_string (child, &se->data.client.username);
+ cf_util_get_string (child, &se->data.client.username);
else if (strcasecmp ("Password", child->key) == 0)
- network_config_set_string (child, &se->data.client.password);
+ cf_util_get_string (child, &se->data.client.password);
else if (strcasecmp ("SecurityLevel", child->key) == 0)
network_config_set_security_level (child,
&se->data.client.security_level);
else
#endif /* HAVE_LIBGCRYPT */
if (strcasecmp ("Interface", child->key) == 0)
- network_config_set_interface (child,
- &se->interface);
- else if (strcasecmp ("ResolveInterval", child->key) == 0)
- cf_util_get_cdtime(child, &se->data.client.resolve_interval);
+ network_config_set_interface (child, &se->interface);
+ else if (strcasecmp ("ResolveInterval", child->key) == 0)
+ cf_util_get_cdtime(child, &se->data.client.resolve_interval);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
}
/* No call to sockent_client_connect() here -- it is called from
- * networt_send_buffer_plain(). */
+ * network_send_buffer_plain(). */
status = sockent_add (se);
if (status != 0)
static int network_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
/* The options need to be applied first */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("TimeToLive", child->key) == 0)
network_config_set_ttl (child);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
else if (strcasecmp ("MaxPacketSize", child->key) == 0)
network_config_set_buffer_size (child);
else if (strcasecmp ("Forward", child->key) == 0)
- network_config_set_boolean (child, &network_config_forward);
+ cf_util_get_boolean (child, &network_config_forward);
else if (strcasecmp ("ReportStats", child->key) == 0)
- network_config_set_boolean (child, &network_config_stats);
+ cf_util_get_boolean (child, &network_config_stats);
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
static int network_notification (const notification_t *n,
user_data_t __attribute__((unused)) *user_data)
{
- char buffer[network_config_packet_size];
- char *buffer_ptr = buffer;
- int buffer_free = sizeof (buffer);
- int status;
+ char buffer[network_config_packet_size];
+ char *buffer_ptr = buffer;
+ size_t buffer_free = sizeof (buffer);
+ int status;
if (!check_send_notify_okay (n))
return (0);
static int network_shutdown (void)
{
- sockent_t *se;
-
listen_loop++;
/* Kill the listening thread */
sfree (send_buffer);
- for (se = sending_sockets; se != NULL; se = se->next)
+ for (sockent_t *se = sending_sockets; se != NULL; se = se->next)
sockent_client_disconnect (se);
sockent_destroy (sending_sockets);
return (0);
have_init = 1;
- if (network_config_stats != 0)
+ if (network_config_stats)
plugin_register_read ("network", network_stats_read);
plugin_register_shutdown ("network", network_shutdown);
* 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 (__attribute__((unused)) cdtime_t timeout,
+static int network_flush (cdtime_t timeout,
__attribute__((unused)) const char *identifier,
__attribute__((unused)) user_data_t *user_data)
{
pthread_mutex_lock (&send_buffer_lock);
if (send_buffer_fill > 0)
- flush_buffer ();
-
+ {
+ if (timeout > 0)
+ {
+ cdtime_t now = cdtime ();
+ if ((send_buffer_last_update + timeout) > now)
+ {
+ pthread_mutex_unlock (&send_buffer_lock);
+ return (0);
+ }
+ }
+ flush_buffer ();
+ }
pthread_mutex_unlock (&send_buffer_lock);
return (0);
diff --git a/src/nfs.c b/src/nfs.c
index be823720b489ec3ddd8f1f75d7976b28469fd5ab..c128c8173fea1a494333da877765ab8f9bf208fb 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
@@ -221,7 +222,7 @@ static size_t nfs4_server40_procedures_names_num = STATIC_ARRAY_SIZE (nfs4_serve
static const char *nfs4_server41_procedures_names[] =
{
"backchannel_ctl",
- "bind_conn_to_session",
+ "bind_conn_to_session",
"exchange_id",
"create_session",
"destroy_session",
#elif HAVE_LIBKSTAT
static int nfs_init (void)
{
- kstat_t *ksp_chain = NULL;
-
nfs2_ksp_client = NULL;
nfs2_ksp_server = NULL;
nfs3_ksp_client = NULL;
if (kc == NULL)
return (-1);
- for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
+ for (kstat_t *ksp_chain = kc->kc_chain; ksp_chain != NULL;
ksp_chain = ksp_chain->ks_next)
{
if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
value_t *values, size_t values_num)
{
value_list_t vl = VALUE_LIST_INIT;
- size_t i;
vl.values_len = 1;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sizeof (vl.plugin_instance));
sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type));
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
{
vl.values = values + i;
sstrncpy (vl.type_instance, type_instances[i],
} /* void nfs_procedures_submit */
#if KERNEL_LINUX
-static void nfs_submit_fields (int nfs_version, const char *instance,
+static void nfs_submit_fields (int nfs_version, const char *instance,
char **fields, size_t fields_num, const char **proc_names)
{
char plugin_instance[DATA_MAX_NAME_LEN];
value_t values[fields_num];
- size_t i;
ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s",
nfs_version, instance);
- for (i = 0; i < fields_num; i++)
+ for (size_t i = 0; i < fields_num; i++)
(void) parse_value (fields[i], &values[i], DS_TYPE_DERIVE);
nfs_procedures_submit (plugin_instance, proc_names, values,
return (EINVAL);
}
- nfs_submit_fields (nfs_version, instance, fields, fields_num,
+ nfs_submit_fields (nfs_version, instance, fields, fields_num,
proc_names);
return (0);
}
-static int nfs_submit_nfs4_server (const char *instance, char **fields,
+static int nfs_submit_nfs4_server (const char *instance, char **fields,
size_t fields_num)
{
static int suppress_warning = 0;
if (fields_num != NFS4_SERVER40_NUM_PROC &&
- fields_num != NFS4_SERVER41_NUM_PROC)
+ fields_num != NFS4_SERVER41_NUM_PROC)
{
if (!suppress_warning)
{
}
}
- nfs_submit_fields (4, instance, fields,
+ nfs_submit_fields (4, instance, fields,
nfs4_server40_procedures_names_num,
nfs4_server40_procedures_names);
{
fields += nfs4_server40_procedures_names_num;
- nfs_submit_fields (4, instance, fields,
- nfs4_server41_procedures_names_num,
+ nfs_submit_fields (4, instance, fields,
+ nfs4_server41_procedures_names_num,
nfs4_server41_procedures_names);
}
return (0);
}
-static int nfs_submit_nfs4_client (const char *instance, char **fields,
+static int nfs_submit_nfs4_client (const char *instance, char **fields,
size_t fields_num)
{
size_t proc40_names_num, proc41_names_num;
return (0);
}
-static void nfs_read_linux (FILE *fh, char *inst)
+static void nfs_read_linux (FILE *fh, const char *inst)
{
char buffer[1024];
else if (strcmp (fields[0], "proc4ops") == 0)
{
if (inst[0] == 's')
- nfs_submit_nfs4_server (inst, fields + 2,
+ nfs_submit_nfs4_server (inst, fields + 2,
(size_t) (fields_num - 2));
}
else if (strcmp (fields[0], "proc4") == 0)
{
if (inst[0] == 'c')
nfs_submit_nfs4_client (inst, fields + 2,
- (size_t) (fields_num - 2));
+ (size_t) (fields_num - 2));
}
} /* while (fgets) */
} /* void nfs_read_linux */
#endif /* KERNEL_LINUX */
#if HAVE_LIBKSTAT
-static int nfs_read_kstat (kstat_t *ksp, int nfs_version, char *inst,
+static int nfs_read_kstat (kstat_t *ksp, int nfs_version, const char *inst,
char const **proc_names, size_t proc_names_num)
{
char plugin_instance[DATA_MAX_NAME_LEN];
value_t values[proc_names_num];
- size_t i;
if (ksp == NULL)
return (EINVAL);
nfs_version, inst);
kstat_read(kc, ksp, NULL);
- for (i = 0; i < proc_names_num; i++)
+ for (size_t i = 0; i < proc_names_num; i++)
{
/* The name passed to kstat_data_lookup() doesn't have the
* "const" modifier, so we need to copy the name here. */
diff --git a/src/nginx.c b/src/nginx.c
index 4e4ce3bbc6115572873668a76507f80ccd82b316..16ce3d5f6ba33d5207b0cbf44f0e0673ea539925 100644 (file)
--- a/src/nginx.c
+++ b/src/nginx.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include <curl/curl.h>
len = (sizeof (nginx_buffer) - 1) - nginx_buffer_len;
}
- if (len <= 0)
+ if (len == 0)
return (len);
memcpy (&nginx_buffer[nginx_buffer_len], buf, len);
}
else
{
- curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
- CDTIME_T_TO_MS(plugin_get_interval()));
+ curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long) CDTIME_T_TO_MS(plugin_get_interval()));
}
#endif
return (0);
} /* void init */
-static void submit (char *type, char *inst, long long value)
+static void submit (const char *type, const char *inst, long long value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
static int nginx_read (void)
{
- int i;
-
char *ptr;
char *lines[16];
int lines_num = 0;
* 16630948 16630948 31070465
* Reading: 6 Writing: 179 Waiting: 106
*/
- for (i = 0; i < lines_num; i++)
+ for (int i = 0; i < lines_num; i++)
{
fields_num = strsplit (lines[i], fields,
(sizeof (fields) / sizeof (fields[0])));
diff --git a/src/notify_desktop.c b/src/notify_desktop.c
index c2d97520ed99c9bcbb8839900ea1858ba39731bf..5cab1190d0789a90ce969ae53657904eb3ec9bc3 100644 (file)
--- a/src/notify_desktop.c
+++ b/src/notify_desktop.c
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include <glib.h>
#include <libnotify/notify.h>
static int c_notify_config (oconfig_item_t *ci)
{
- int i = 0;
-
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
if (0 == strcasecmp (c->key, "OkayTimeout"))
diff --git a/src/notify_email.c b/src/notify_email.c
index 76d48d445825c83834d93095ed35420ce288b7d1..cefeb22f4717d6b53695b123099ca570491d47f8 100644 (file)
--- a/src/notify_email.c
+++ b/src/notify_email.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <auth-client.h>
#include <libesmtp.h>
-#include <pthread.h>
#define MAXSTRING 256
/* Callback to get username and password */
static int authinteract (auth_client_request_t request, char **result,
int fields, void __attribute__((unused)) *arg)
-{
- int i;
- for (i = 0; i < fields; i++)
+{
+ for (int i = 0; i < fields; i++)
{
if (request[i].flags & AUTH_USER)
result[i] = smtp_user;
if ( !smtp_auth_set_context (session, authctx)) {
pthread_mutex_unlock (&session_lock);
ERROR ("notify_email plugin: cannot set SMTP auth context");
- return (-1);
+ return (-1);
}
pthread_mutex_unlock (&session_lock);
{
char **tmp;
- tmp = (char **) realloc ((void *) recipients, (recipients_len + 1) * sizeof (char *));
+ tmp = realloc (recipients, (recipients_len + 1) * sizeof (char *));
if (tmp == NULL) {
ERROR ("notify_email: realloc failed.");
return (-1);
if (!(message = smtp_add_message (session))) {
pthread_mutex_unlock (&session_lock);
ERROR ("notify_email plugin: cannot set SMTP message");
- return (-1);
+ return (-1);
}
smtp_set_reverse_path (message, email_from);
smtp_set_header (message, "To", NULL, NULL);
diff --git a/src/notify_nagios.c b/src/notify_nagios.c
--- /dev/null
+++ b/src/notify_nagios.c
@@ -0,0 +1,165 @@
+/**
+ * collectd - src/notify_nagios.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "collectd.h"
+
+#include "plugin.h"
+#include "common.h"
+
+#define NAGIOS_OK 0
+#define NAGIOS_WARNING 1
+#define NAGIOS_CRITICAL 2
+#define NAGIOS_UNKNOWN 3
+
+#ifndef NAGIOS_COMMAND_FILE
+# define NAGIOS_COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd"
+#endif
+
+static char *nagios_command_file;
+
+static int nagios_config (oconfig_item_t *ci) /* {{{ */
+{
+ for (int i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("CommandFile", child->key) == 0)
+ cf_util_get_string (child, &nagios_command_file);
+ else
+ WARNING ("notify_nagios plugin: Ignoring unknown config option \"%s\".",
+ child->key);
+ }
+
+ return 0;
+} /* }}} nagios_config */
+
+static int nagios_print (char const *buffer) /* {{{ */
+{
+ char const *file = NAGIOS_COMMAND_FILE;
+ int fd;
+ int status;
+ struct flock lock = { 0 };
+
+ if (nagios_command_file != NULL)
+ file = nagios_command_file;
+
+ fd = open (file, O_WRONLY | O_APPEND);
+ if (fd < 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Opening \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ return status;
+ }
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_END;
+
+ status = fcntl (fd, F_GETLK, &lock);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Failed to acquire write lock on \"%s\": %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ status = (int) lseek (fd, 0, SEEK_END);
+ if (status == -1)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Seeking to end of \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ status = (int) swrite (fd, buffer, strlen (buffer));
+ if (status != 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Writing to \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ close (fd);
+ return status;
+} /* }}} int nagios_print */
+
+static int nagios_notify (const notification_t *n, /* {{{ */
+ __attribute__((unused)) user_data_t *user_data)
+{
+ char svc_description[4 * DATA_MAX_NAME_LEN];
+ char buffer[4096];
+ int code;
+ int status;
+
+ status = format_name (svc_description, (int) sizeof (svc_description),
+ /* host */ "", n->plugin, n->plugin_instance, n->type, n->type_instance);
+ if (status != 0)
+ {
+ ERROR ("notify_nagios plugin: Formatting service name failed.");
+ return status;
+ }
+
+ switch (n->severity)
+ {
+ case NOTIF_OKAY:
+ code = NAGIOS_OK;
+ break;
+ case NOTIF_WARNING:
+ code = NAGIOS_WARNING;
+ break;
+ case NOTIF_FAILURE:
+ code = NAGIOS_CRITICAL;
+ break;
+ default:
+ code = NAGIOS_UNKNOWN;
+ break;
+ }
+
+ ssnprintf (buffer, sizeof (buffer),
+ "[%.0f] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
+ CDTIME_T_TO_DOUBLE (n->time), n->host, &svc_description[1], code,
+ n->message);
+
+ return nagios_print (buffer);
+} /* }}} int nagios_notify */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("notify_nagios", nagios_config);
+ plugin_register_notification ("notify_nagios", nagios_notify, NULL);
+} /* void module_register (void) */
+
+/* vim: set sw=2 sts=2 ts=8 et : */
diff --git a/src/ntpd.c b/src/ntpd.c
index ce54e029e7124c673cddcc9a6293ded9e71e9bf7..30f29c97dbfcef7f50afbb8daa1a5d2b67f305e8 100644 (file)
--- a/src/ntpd.c
+++ b/src/ntpd.c
#define _BSD_SOURCE /* For NI_MAXHOST */
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#if HAVE_STDINT_H
# include <stdint.h>
#if HAVE_NETDB_H
# include <netdb.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# include <poll.h>
#endif
+#ifndef STA_NANO
+# define STA_NANO 0x2000
+#endif
+
static const char *config_keys[] =
{
"Host",
};
/* List of reference clock names */
-static char *refclock_names[] =
+static const char *refclock_names[] =
{
"UNKNOWN", "LOCAL", "GPS_TRAK", "WWV_PST", /* 0- 3 */
"SPECTRACOM", "TRUETIME", "IRIG_AUDIO", "CHU_AUDIO", /* 4- 7 */
"JJY", "TT_IRIG", "GPS_ZYFER", "GPS_RIPENCC", /* 40-43 */
"NEOCLK4X" /* 44 */
};
-static int refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
+static size_t refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* End of the copied stuff.. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
return (0);
}
-static void ntpd_submit (char *type, char *type_inst, gauge_t value)
+static void ntpd_submit (const char *type, const char *type_inst, gauge_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
/* Each time a peer is polled, ntpd shifts the reach register to the left and
* sets the LSB based on whether the peer was reachable. If the LSB is zero,
* the values are out of date. */
-static void ntpd_submit_reach (char *type, char *type_inst, uint8_t reach,
- gauge_t value)
+static void ntpd_submit_reach (const char *type, const char *type_inst,
+ uint8_t reach, gauge_t value)
{
if (!(reach & 1))
value = NAN;
static int ntpd_connect (void)
{
- char *host;
- char *port;
+ const char *host;
+ const char *port;
- struct addrinfo ai_hints;
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
int status;
if (sock_descr >= 0)
if (strlen (port) == 0)
port = NTPD_DEFAULT_PORT;
- memset (&ai_hints, '\0', sizeof (ai_hints));
- ai_hints.ai_flags = 0;
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = PF_UNSPEC;
- ai_hints.ai_socktype = SOCK_DGRAM;
- ai_hints.ai_protocol = IPPROTO_UDP;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_protocol = IPPROTO_UDP,
+ .ai_socktype = SOCK_DGRAM
+ };
if ((status = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
{
return (-1);
}
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
/* create our socket descriptor */
if ((sock_descr = socket (ai_ptr->ai_family,
struct resp_pkt res;
int status;
int done;
- int i;
char *items;
size_t items_num;
struct timeval time_now;
int timeout;
- int pkt_item_num; /* items in this packet */
- int pkt_item_len; /* size of the items in this packet */
+ int pkt_item_num; /* items in this packet */
+ int pkt_item_len; /* size of the items in this packet */
int pkt_sequence;
- char pkt_recvd[MAXSEQ+1]; /* sequence numbers that have been received */
- int pkt_recvd_num; /* number of packets that have been received */
- int pkt_lastseq; /* the last sequence number */
- ssize_t pkt_padding; /* Padding in this packet */
+ char pkt_recvd[MAXSEQ+1] = { 0 }; /* sequence numbers that have been received */
+ int pkt_recvd_num; /* number of packets that have been received */
+ int pkt_lastseq; /* the last sequence number */
+ ssize_t pkt_padding; /* Padding in this packet */
if ((sd = ntpd_connect ()) < 0)
return (-1);
items = NULL;
items_num = 0;
- memset (pkt_recvd, '\0', sizeof (pkt_recvd));
pkt_recvd_num = 0;
pkt_lastseq = -1;
break;
}
- memset ((void *) &res, '\0', sizeof (res));
+ memset (&res, '\0', sizeof (res));
status = recv (sd, (void *) &res, sizeof (res), 0 /* no flags */);
if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
*/
DEBUG ("realloc (%p, %zu)", (void *) *res_data,
(items_num + pkt_item_num) * res_item_size);
- items = realloc ((void *) *res_data,
+ items = realloc (*res_data,
(items_num + pkt_item_num) * res_item_size);
if (items == NULL)
{
items_num += pkt_item_num;
*res_data = items;
- for (i = 0; i < pkt_item_num; i++)
+ for (int i = 0; i < pkt_item_num; i++)
{
/* dst: There are already `*res_items' items with
* res_item_size bytes each in in `*res_data'. Set
static int ntpd_send_request (int req_code, int req_items, int req_size, char *req_data)
{
int sd;
- struct req_pkt req;
+ struct req_pkt req = { 0 };
size_t req_data_len;
int status;
@@ -723,7 +718,6 @@ static int ntpd_send_request (int req_code, int req_items, int req_size, char *r
if ((sd = ntpd_connect ()) < 0)
return (-1);
- memset ((void *) &req, '\0', sizeof (req));
req.rm_vn_mode = RM_VN_MODE(0, 0, 0);
req.auth_seq = AUTH_SEQ (0, 0);
req.implementation = IMPL_XNTPD;
@@ -804,20 +798,17 @@ static uint32_t ntpd_get_refclock_id (struct info_peer_summary const *peer_info)
static int ntpd_get_name_from_address (char *buffer, size_t buffer_size,
struct info_peer_summary const *peer_info, _Bool do_reverse_lookup)
{
- struct sockaddr_storage sa;
+ struct sockaddr_storage sa = { 0 };
socklen_t sa_len;
int flags = 0;
int status;
- memset (&sa, 0, sizeof (sa));
-
if (peer_info->v6_flag)
{
- struct sockaddr_in6 sa6;
+ struct sockaddr_in6 sa6 = { 0 };
assert (sizeof (sa) >= sizeof (sa6));
- memset (&sa6, 0, sizeof (sa6));
sa6.sin6_family = AF_INET6;
sa6.sin6_port = htons (123);
memcpy (&sa6.sin6_addr, &peer_info->srcadr6,
}
else
{
- struct sockaddr_in sa4;
+ struct sockaddr_in sa4 = { 0 };
assert (sizeof (sa) >= sizeof (sa4));
- memset (&sa4, 0, sizeof (sa4));
sa4.sin_family = AF_INET;
sa4.sin_port = htons (123);
memcpy (&sa4.sin_addr, &peer_info->srcadr,
uint32_t refclock_id = ntpd_get_refclock_id (peer_info);
uint32_t unit_id = ntohl (peer_info->srcadr) & 0x00FF;
- if (refclock_id >= refclock_names_num)
+ if (((size_t) refclock_id) >= refclock_names_num)
return (ntpd_get_name_from_address (buffer, buffer_size,
peer_info,
/* do_reverse_lookup = */ 0));
gauge_t offset_error;
int status;
- int i;
/* On Linux, if the STA_NANO bit is set in ik->status, then ik->offset
- * is is nanoseconds, otherwise it's microseconds.
- * TODO(octo): STA_NANO is defined in the Linux specific <sys/timex.h> header. */
+ * is is nanoseconds, otherwise it's microseconds. */
double scale_loop = 1e-6;
double scale_error = 1e-6;
return (-1);
}
+ if (ntohs(ik->status) & STA_NANO) {
+ scale_loop = 1e-9;
+ scale_error = 1e-9;
+ }
+
/* kerninfo -> estimated error */
offset_loop = scale_loop * ((gauge_t) ntohl (ik->offset));
freq_loop = ntpd_read_fp (ik->freq);
return (-1);
}
- for (i = 0; i < ps_num; i++)
+ for (int i = 0; i < ps_num; i++)
{
struct info_peer_summary *ptr;
double offset;
diff --git a/src/numa.c b/src/numa.c
index a87a17e9df7c7c0780aa730a280b30c984a94995..8f5bf4803821c9fe40be370f4c5c5ee0d4cd4520 100644 (file)
--- a/src/numa.c
+++ b/src/numa.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
while (42)
{
char path[PATH_MAX];
- struct stat statbuf;
+ struct stat statbuf = { 0 };
int status;
ssnprintf (path, sizeof (path), NUMA_ROOT_DIR "/node%i", max_node + 1);
- memset (&statbuf, 0, sizeof (statbuf));
status = stat (path, &statbuf);
if (status == 0)
diff --git a/src/nut.c b/src/nut.c
index d5ecc98de12b13a811f7e36fc131eaf36dfb6c19..b5c6b41b6522142aba73716ed36b5a05e4886608 100644 (file)
--- a/src/nut.c
+++ b/src/nut.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include <pthread.h>
#include <upsclient.h>
#if HAVE_UPSCONN_T
DEBUG ("nut plugin: nut_add_ups (name = %s);", name);
- ups = (nut_ups_t *) malloc (sizeof (nut_ups_t));
+ ups = calloc (1, sizeof (*ups));
if (ups == NULL)
{
- ERROR ("nut plugin: nut_add_ups: malloc failed.");
+ ERROR ("nut plugin: nut_add_ups: calloc failed.");
return (1);
}
- memset (ups, '\0', sizeof (nut_ups_t));
status = upscli_splitname (name, &ups->upsname, &ups->hostname,
&ups->port);
/* (Re-)Connect if we have no connection */
if (ups->conn == NULL)
{
- ups->conn = (collectd_upsconn_t *) malloc (sizeof (collectd_upsconn_t));
+ ups->conn = malloc (sizeof (*ups->conn));
if (ups->conn == NULL)
{
ERROR ("nut plugin: malloc failed.");
static int nut_read (void)
{
- nut_ups_t *ups;
int success = 0;
pthread_mutex_lock (&read_lock);
if (success != 0)
return (0);
- for (ups = upslist_head; ups != NULL; ups = ups->next)
+ for (nut_ups_t *ups = upslist_head; ups != NULL; ups = ups->next)
if (nut_read_one (ups) == 0)
success++;
diff --git a/src/olsrd.c b/src/olsrd.c
index 6d0576cf7bc7d26e39567646f40fa1ebd49262cc..899ad3e8f2ef4e565cb782c4290f8cfbf08f39cf 100644 (file)
--- a/src/olsrd.c
+++ b/src/olsrd.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <sys/types.h>
#include <netdb.h>
-#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -150,22 +150,18 @@ static size_t strtabsplit (char *string, char **fields, size_t size) /* {{{ */
static FILE *olsrd_connect (void) /* {{{ */
{
- struct addrinfo ai_hints;
- struct addrinfo *ai_list, *ai_ptr;
+ struct addrinfo *ai_list;
int ai_return;
FILE *fh;
- memset (&ai_hints, 0, sizeof (ai_hints));
- ai_hints.ai_flags = 0;
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = PF_UNSPEC;
- ai_hints.ai_socktype = SOCK_STREAM;
- ai_hints.ai_protocol = IPPROTO_TCP;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_protocol = IPPROTO_TCP,
+ .ai_socktype = SOCK_STREAM
+ };
- ai_list = NULL;
ai_return = getaddrinfo (olsrd_get_node (), olsrd_get_service (),
&ai_hints, &ai_list);
if (ai_return != 0)
}
fh = NULL;
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
int fd;
int status;
if (config_want_topology == OLSRD_WANT_DETAIL)
{
- char type_instance[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN] = { 0 };
- memset (type_instance, 0, sizeof (type_instance));
ssnprintf (type_instance, sizeof (type_instance), "%s-%s-lq",
fields[0], fields[1]);
DEBUG ("olsrd plugin: type_instance = %s; lq = %g;", type_instance, lq);
}
else
{
- char type_instance[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN] = { 0 };
- memset (type_instance, 0, sizeof (type_instance));
ssnprintf (type_instance, sizeof (type_instance), "%s-%s-nlq",
fields[0], fields[1]);
DEBUG ("olsrd plugin: type_instance = %s; nlq = %g;", type_instance, nlq);
{
/* An empty line ends the table. */
buffer_len = strchomp (buffer);
- if (buffer_len <= 0)
+ if (buffer_len == 0)
{
(*callback) (lineno, /* fields_num = */ 0, /* fields = */ NULL);
break;
(*callback) (lineno, fields_num, fields);
lineno++;
} /* while (fgets) */
-
+
return (0);
} /* }}} int olsrd_read_table */
while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
buffer_len = strchomp (buffer);
- if (buffer_len <= 0)
+ if (buffer_len == 0)
continue;
-
+
if (strcmp ("Table: Links", buffer) == 0)
olsrd_read_table (fh, olsrd_cb_links);
else if (strcmp ("Table: Neighbors", buffer) == 0)
} /* while (fgets) */
fclose (fh);
-
+
return (0);
} /* }}} int olsrd_read */
diff --git a/src/onewire.c b/src/onewire.c
index 51e6407137b0f2c8bc64598f822cac804c5a9fab..235eff80a8d4663b5e479627db39f3183f99aa21 100644 (file)
--- a/src/onewire.c
+++ b/src/onewire.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_ignorelist.h"
{
regmatch_t pmatch[3];
size_t nmatch = 3;
- direct_access_element_t *element = NULL;
+ direct_access_element_t *element;
DEBUG ("onewire plugin: direct_list_insert <%s>", config);
- element = (direct_access_element_t *) malloc (sizeof(*element));
+ element = malloc (sizeof (*element));
if (element == NULL)
{
ERROR ("onewire plugin: direct_list_insert - cannot allocate element");
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
int success = 0;
- size_t i;
if (sensor_list != NULL)
{
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++)
+ for (size_t i = 0; i < family_info->features_num; i++)
{
char *buffer;
size_t buffer_size;
int status;
status = ssnprintf (subpath, sizeof (subpath), "%s/main", path);
- if ((status > 0) && (status < sizeof (subpath)))
+ if ((status > 0) && (status < (int) sizeof (subpath)))
cow_read_bus (subpath);
status = ssnprintf (subpath, sizeof (subpath), "%s/aux", path);
- if ((status > 0) && (status < sizeof (subpath)))
+ if ((status > 0) && (status < (int) sizeof (subpath)))
cow_read_bus (subpath);
return (0);
else
status = ssnprintf (subpath, sizeof (subpath), "%s/%s",
path, buffer_ptr);
- if ((status <= 0) || (status >= sizeof (subpath)))
+ if ((status <= 0) || (status >= (int) sizeof (subpath)))
continue;
for (i = 0; i < ow_family_features_num; i++)
static int cow_init (void)
{
int status;
- struct timespec cb_interval;
if (device_g == NULL)
{
return (1);
}
- CDTIME_T_TO_TIMESPEC (ow_interval, &cb_interval);
-
plugin_register_complex_read (/* group = */ NULL, "onewire", cow_read,
- (ow_interval != 0) ? &cb_interval : NULL,
- /* user data = */ NULL);
+ ow_interval, /* user data = */ NULL);
plugin_register_shutdown ("onewire", cow_shutdown);
return (0);
diff --git a/src/openldap.c b/src/openldap.c
index bd79b26b7312bf076c95a247f9d3331688e5f550..d424cb457557fe563ebc4cf997604d42a19ada53 100644 (file)
--- a/src/openldap.c
+++ b/src/openldap.c
/**
* collectd - src/openldap.c
* Copyright (C) 2011 Kimo Rosenbaum
- * Copyright (C) 2014 Marc Fournier
+ * Copyright (C) 2014-2015 Marc Fournier
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#if defined(__APPLE__)
#pragma clang diagnostic push
{
char *name;
+ char *binddn;
+ char *password;
char *cacert;
char *host;
int state;
};
typedef struct cldap_s cldap_t; /* }}} */
+static cldap_t **databases = NULL;
+static size_t databases_num = 0;
+
static void cldap_free (cldap_t *st) /* {{{ */
{
if (st == NULL)
return;
+ sfree (st->binddn);
+ sfree (st->password);
sfree (st->cacert);
sfree (st->host);
sfree (st->name);
{
LDAP *ld;
int rc;
+
+ if (st->state && st->ld)
+ {
+ DEBUG ("openldap plugin: Already connected to %s", st->url);
+ return (0);
+ }
+
rc = ldap_initialize (&ld, st->url);
if (rc != LDAP_SUCCESS)
{
ldap_set_option (st->ld, LDAP_OPT_TIMEOUT,
&(const struct timeval){st->timeout, 0});
+ ldap_set_option (st->ld, LDAP_OPT_RESTART, LDAP_OPT_ON);
+
if (st->cacert != NULL)
ldap_set_option (st->ld, LDAP_OPT_X_TLS_CACERTFILE, st->cacert);
}
struct berval cred;
- cred.bv_val = "";
- cred.bv_len = 0;
+ if (st->password != NULL)
+ {
+ cred.bv_val = st->password;
+ cred.bv_len = strlen (st->password);
+ }
+ else
+ {
+ cred.bv_val = "";
+ cred.bv_len = 0;
+ }
- rc = ldap_sasl_bind_s (st->ld, NULL, NULL, &cred, NULL, NULL, NULL);
+ rc = ldap_sasl_bind_s (st->ld, st->binddn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, NULL);
if (rc != LDAP_SUCCESS)
{
ERROR ("openldap plugin: Failed to bind to %s: %s",
@@ -147,13 +172,9 @@ static void cldap_submit_value (const char *type, const char *type_instance, /*
if ((st->host == NULL)
|| (strcmp ("", st->host) == 0)
|| (strcmp ("localhost", st->host) == 0))
- {
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
- }
else
- {
sstrncpy (vl.host, st->host, sizeof (vl.host));
- }
sstrncpy (vl.plugin, "openldap", sizeof (vl.plugin));
if (st->name != NULL)
static int cldap_read_host (user_data_t *ud) /* {{{ */
{
cldap_t *st;
- LDAPMessage *e, *result;
+ LDAPMessage *result;
char *dn;
int rc;
int status;
ERROR ("openldap plugin: Failed to execute search: %s",
ldap_err2string (rc));
ldap_msgfree (result);
+ st->state = 0;
ldap_unbind_ext_s (st->ld, NULL, NULL);
return (-1);
}
- for (e = ldap_first_entry (st->ld, result); e != NULL;
+ for (LDAPMessage *e = ldap_first_entry (st->ld, result); e != NULL;
e = ldap_next_entry (st->ld, e))
{
if ((dn = ldap_get_dn (st->ld, e)) != NULL)
}
ldap_msgfree (result);
- ldap_unbind_ext_s (st->ld, NULL, NULL);
return (0);
} /* }}} int cldap_read_host */
static int cldap_config_add (oconfig_item_t *ci) /* {{{ */
{
cldap_t *st;
- int i;
int status;
- st = malloc (sizeof (*st));
+ st = calloc (1, sizeof (*st));
if (st == NULL)
{
- ERROR ("openldap plugin: malloc failed.");
+ ERROR ("openldap plugin: calloc failed.");
return (-1);
}
- memset (st, 0, sizeof (*st));
status = cf_util_get_string (ci, &st->name);
if (status != 0)
}
st->starttls = 0;
- st->timeout = -1;
+ st->timeout = (long) (CDTIME_T_TO_MS(plugin_get_interval()) / 1000);
st->verifyhost = 1;
st->version = LDAP_VERSION3;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
- if (strcasecmp ("CACert", child->key) == 0)
+ if (strcasecmp ("BindDN", child->key) == 0)
+ status = cf_util_get_string (child, &st->binddn);
+ else if (strcasecmp ("Password", child->key) == 0)
+ status = cf_util_get_string (child, &st->password);
+ else if (strcasecmp ("CACert", child->key) == 0)
status = cf_util_get_string (child, &st->cacert);
else if (strcasecmp ("StartTLS", child->key) == 0)
status = cf_util_get_boolean (child, &st->starttls);
if ((status == 0) && (st->url != NULL))
{
LDAPURLDesc *ludpp;
- int rc;
- if ((rc = ldap_url_parse (st->url, &ludpp)) != 0)
+ if (ldap_url_parse (st->url, &ludpp) != 0)
{
ERROR ("openldap plugin: Instance `%s': "
"Invalid URL: `%s'",
}
if ((status == 0) && (ludpp->lud_host != NULL))
- {
st->host = strdup (ludpp->lud_host);
- }
ldap_free_urldesc (ludpp);
}
if (status == 0)
{
- user_data_t ud;
- char callback_name[3*DATA_MAX_NAME_LEN];
-
- memset (&ud, 0, sizeof (ud));
- ud.data = st;
-
- memset (callback_name, 0, sizeof (callback_name));
- ssnprintf (callback_name, sizeof (callback_name),
- "openldap/%s/%s",
- (st->host != NULL) ? st->host : hostname_g,
- (st->name != NULL) ? st->name : "default"),
-
- status = plugin_register_complex_read (/* group = */ NULL,
- /* name = */ callback_name,
- /* callback = */ cldap_read_host,
- /* interval = */ NULL,
- /* user_data = */ &ud);
+ cldap_t **temp;
+
+ temp = (cldap_t **) realloc (databases,
+ sizeof (*databases) * (databases_num + 1));
+
+ if (temp == NULL)
+ {
+ ERROR ("openldap plugin: realloc failed");
+ status = -1;
+ }
+ else
+ {
+ char callback_name[3*DATA_MAX_NAME_LEN] = { 0 };
+
+ databases = temp;
+ databases[databases_num] = st;
+ databases_num++;
+
+ ssnprintf (callback_name, sizeof (callback_name),
+ "openldap/%s/%s",
+ (st->host != NULL) ? st->host : hostname_g,
+ (st->name != NULL) ? st->name : "default");
+
+ user_data_t ud = {
+ .data = st
+ };
+
+ status = plugin_register_complex_read (/* group = */ NULL,
+ /* name = */ callback_name,
+ /* callback = */ cldap_read_host,
+ /* interval = */ 0,
+ /* user_data = */ &ud);
+ }
}
if (status != 0)
static int cldap_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
int status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
return (0);
} /* }}} int cldap_init */
+static int cldap_shutdown (void) /* {{{ */
+{
+ for (size_t i = 0; i < databases_num; i++)
+ if (databases[i]->ld != NULL)
+ ldap_unbind_ext_s (databases[i]->ld, NULL, NULL);
+ sfree (databases);
+ databases_num = 0;
+
+ return (0);
+} /* }}} int cldap_shutdown */
+
void module_register (void) /* {{{ */
{
plugin_register_complex_config ("openldap", cldap_config);
plugin_register_init ("openldap", cldap_init);
+ plugin_register_shutdown ("openldap", cldap_shutdown);
} /* }}} void module_register */
#if defined(__APPLE__)
diff --git a/src/openvpn.c b/src/openvpn.c
index 93c8f1b58363fbf8f7a27f4f03a5b4077f74fee8..be9a4dc863e383ca006660faeb3501c7020436b1 100644 (file)
--- a/src/openvpn.c
+++ b/src/openvpn.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
} /* int openvpn_strsplit */
/* dispatches number of users */
-static void numusers_submit (char *pinst, char *tinst, gauge_t value)
+static void numusers_submit (const char *pinst, const char *tinst,
+ gauge_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
plugin_dispatch_values (&vl);
} /* void numusers_submit */
-/* dispatches stats about traffic (TCP or UDP) generated by the tunnel per single endpoint */
-static void iostats_submit (char *pinst, char *tinst, derive_t rx, derive_t tx)
+/* dispatches stats about traffic (TCP or UDP) generated by the tunnel
+ * per single endpoint */
+static void iostats_submit (const char *pinst, const char *tinst,
+ derive_t rx, derive_t tx)
{
value_t values[2];
value_list_t vl = VALUE_LIST_INIT;
} /* void traffic_submit */
/* dispatches stats about data compression shown when in single mode */
-static void compression_submit (char *pinst, char *tinst,
+static void compression_submit (const char *pinst, const char *tinst,
derive_t uncompressed, derive_t compressed)
{
value_t values[2];
plugin_dispatch_values (&vl);
} /* void compression_submit */
-static int single_read (char *name, FILE *fh)
+static int single_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[4];
} /* int single_read */
/* for reading status version 1 */
-static int multi1_read (char *name, FILE *fh)
+static int multi1_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[10];
} /* int multi1_read */
/* for reading status version 2 */
-static int multi2_read (char *name, FILE *fh)
+static int multi2_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[10];
} /* int multi2_read */
/* for reading status version 3 */
-static int multi3_read (char *name, FILE *fh)
+static int multi3_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[15];
} /* int multi3_read */
/* for reading status version 4 */
-static int multi4_read (char *name, FILE *fh)
+static int multi4_read (const char *name, FILE *fh)
{
char buffer[1024];
char *fields[11];
static int openvpn_read (void)
{
FILE *fh;
- int i, read;
+ int read;
read = 0;
+
+ if (vpn_num == 0)
+ return (0);
/* call the right read function for every status entry in the list */
- for (i = 0; i < vpn_num; i++)
+ for (int i = 0; i < vpn_num; i++)
{
int vpn_read = 0;
if (strcasecmp ("StatusFile", key) == 0)
{
char *status_file, *status_name, *filename;
- int status_version, i;
+ int status_version;
vpn_status_t *temp;
/* try to detect the status file format */
if (status_version == 0)
{
- WARNING ("openvpn plugin: unable to detect status version, \
- discarding status file \"%s\".", value);
+ WARNING ("openvpn plugin: unable to detect status version, "
+ "discarding status file \"%s\".", value);
return (1);
}
}
/* scan the list looking for a clone */
- for (i = 0; i < vpn_num; i++)
+ for (int i = 0; i < vpn_num; i++)
{
if (strcasecmp (vpn_list[i]->name, status_name) == 0)
{
}
/* create a new vpn element since file, version and name are ok */
- temp = (vpn_status_t *) malloc (sizeof (vpn_status_t));
+ temp = malloc (sizeof (*temp));
if (temp == NULL)
{
char errbuf[1024];
temp->version = status_version;
temp->name = status_name;
- vpn_list = (vpn_status_t **) realloc (vpn_list, (vpn_num + 1) * sizeof (vpn_status_t *));
- if (vpn_list == NULL)
+ vpn_status_t **tmp_list = realloc (vpn_list, (vpn_num + 1) * sizeof (*vpn_list));
+ if (tmp_list == NULL)
{
char errbuf[1024];
ERROR ("openvpn plugin: realloc failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
+ sfree (vpn_list);
sfree (temp->file);
sfree (temp);
return (1);
}
+ vpn_list = tmp_list;
vpn_list[vpn_num] = temp;
vpn_num++;
/* shutdown callback */
static int openvpn_shutdown (void)
{
- int i;
-
- for (i = 0; i < vpn_num; i++)
+ for (int i = 0; i < vpn_num; i++)
{
sfree (vpn_list[i]->file);
sfree (vpn_list[i]);
diff --git a/src/oracle.c b/src/oracle.c
index ab0812b703ec441c745d4afbe2bcdaf2ca79025f..c0f2fa4121919738bd772090fb1ec652aa162d22 100644 (file)
--- a/src/oracle.c
+++ b/src/oracle.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_db_query.h"
#include <oci.h>
char buffer[2048];
sb4 error_code;
int status;
- unsigned int record_number;
if (db_name == NULL)
db_name = "(none)";
/* An operation may cause / return multiple errors. Loop until we have
* handled all errors available (with a fail-save limit of 16). */
- for (record_number = 1; record_number <= 16; record_number++)
+ for (unsigned int record_number = 1; record_number <= 16; record_number++)
{
memset (buffer, 0, sizeof (buffer));
error_code = -1;
static void o_database_free (o_database_t *db) /* {{{ */
{
- size_t i;
-
if (db == NULL)
return;
sfree (db->queries);
if (db->q_prep_areas != NULL)
- for (i = 0; i < db->queries_num; ++i)
+ for (size_t i = 0; i < db->queries_num; ++i)
udb_query_delete_preparation_area (db->q_prep_areas[i]);
free (db->q_prep_areas);
* ValuesFrom "value"
* </Result>
* </Query>
- *
+ *
* <Database "plugin_instance1">
* ConnectID "db01"
* Username "oracle"
{
o_database_t *db;
int status;
- int i;
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_STRING))
return (-1);
}
- db = (o_database_t *) malloc (sizeof (*db));
+ db = calloc (1, sizeof (*db));
if (db == NULL)
{
- ERROR ("oracle plugin: malloc failed.");
+ ERROR ("oracle plugin: calloc failed.");
return (-1);
}
- memset (db, 0, sizeof (*db));
db->name = NULL;
db->host = NULL;
db->connect_id = NULL;
}
/* Fill the `o_database_t' structure.. */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (db->q_prep_areas == NULL)
{
- WARNING ("oracle plugin: malloc failed");
+ WARNING ("oracle plugin: calloc failed");
status = -1;
break;
}
- for (i = 0; i < db->queries_num; ++i)
+ for (int i = 0; i < db->queries_num; ++i)
{
db->q_prep_areas[i]
= udb_query_allocate_preparation_area (db->queries[i]);
{
o_database_t **temp;
- temp = (o_database_t **) realloc (databases,
+ temp = realloc (databases,
sizeof (*databases) * (databases_num + 1));
if (temp == NULL)
{
static int o_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("Query", child->key) == 0)
OCIDefine **oci_defines;
int status;
- size_t i;
oci_statement = udb_query_get_user_data (q);
{
ub4 param_counter = 0;
status = OCIAttrGet (oci_statement, OCI_HTYPE_STMT, /* {{{ */
- ¶m_counter, /* size pointer = */ NULL,
+ ¶m_counter, /* size pointer = */ NULL,
OCI_ATTR_PARAM_COUNT, oci_error);
if (status != OCI_SUCCESS)
{
} while (0); /* }}} */
/* Allocate the following buffers:
- *
+ *
* +---------------+-----------------------------------+
* ! Name ! Size !
* +---------------+-----------------------------------+
#define ALLOC_OR_FAIL(ptr, ptr_size) \
do { \
size_t alloc_size = (size_t) ((ptr_size)); \
- (ptr) = malloc (alloc_size); \
+ (ptr) = calloc (1, alloc_size); \
if ((ptr) == NULL) { \
FREE_ALL; \
- ERROR ("oracle plugin: o_read_database_query: malloc failed."); \
+ ERROR ("oracle plugin: o_read_database_query: calloc failed."); \
return (-1); \
} \
- memset ((ptr), 0, alloc_size); \
} while (0)
/* Initialize everything to NULL so the above works. */
ALLOC_OR_FAIL (column_names, column_num * sizeof (char *));
ALLOC_OR_FAIL (column_names[0], column_num * DATA_MAX_NAME_LEN
* sizeof (char));
- for (i = 1; i < column_num; i++)
+ for (size_t i = 1; i < column_num; i++)
column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;
ALLOC_OR_FAIL (column_values, column_num * sizeof (char *));
ALLOC_OR_FAIL (column_values[0], column_num * DATA_MAX_NAME_LEN
* sizeof (char));
- for (i = 1; i < column_num; i++)
+ for (size_t i = 1; i < column_num; i++)
column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
ALLOC_OR_FAIL (oci_defines, column_num * sizeof (OCIDefine *));
/* ``Define'' the returned data, i. e. bind the columns to the buffers
* allocated above. */
- for (i = 0; i < column_num; i++) /* {{{ */
+ for (size_t i = 0; i < column_num; i++) /* {{{ */
{
char *column_name;
ub4 column_name_length;
static int o_read_database (o_database_t *db) /* {{{ */
{
- size_t i;
int status;
if (db->oci_service_context != NULL)
ub4 connection_status;
server_handle = NULL;
- status = OCIAttrGet ((void *) db->oci_service_context, OCI_HTYPE_SVCCTX,
+ status = OCIAttrGet ((void *) db->oci_service_context, OCI_HTYPE_SVCCTX,
(void *) &server_handle, /* size pointer = */ NULL,
OCI_ATTR_SERVER, oci_error);
if (status != OCI_SUCCESS)
DEBUG ("oracle plugin: o_read_database: db->connect_id = %s; db->oci_service_context = %p;",
db->connect_id, db->oci_service_context);
- for (i = 0; i < db->queries_num; i++)
+ for (size_t i = 0; i < db->queries_num; i++)
o_read_database_query (db, db->queries[i], db->q_prep_areas[i]);
return (0);
OCIHandleFree (databases[i]->oci_service_context, OCI_HTYPE_SVCCTX);
databases[i]->oci_service_context = NULL;
}
-
+
for (i = 0; i < queries_num; i++)
{
OCIStmt *oci_statement;
udb_query_set_user_data (queries[i], NULL);
}
}
-
+
OCIHandleFree (oci_env, OCI_HTYPE_ENV);
oci_env = NULL;
diff --git a/src/perl.c b/src/perl.c
index 82b9b8c1454262ab0e1c7709718edebee2624908..9eef6c1ad1c88c99798cb2b8e8857c77e42658eb 100644 (file)
--- a/src/perl.c
+++ b/src/perl.c
#define DONT_POISON_SPRINTF_YET 1
#include "collectd.h"
-#undef DONT_POISON_SPRINTF_YET
-#include "configfile.h"
+#undef DONT_POISON_SPRINTF_YET
#if HAVE_STDBOOL_H
# include <stdbool.h>
#include "filter_chain.h"
-#include <pthread.h>
-
#if !defined(USE_ITHREADS)
# error "Perl does not support ithreads!"
#endif /* !defined(USE_ITHREADS) */
return 0;
} /* static int hv2data_source (HV *, data_source_t *) */
-static int av2value (pTHX_ char *name, AV *array, value_t *value, int len)
+/* av2value converts at most "len" elements from "array" to "value". Returns the
+ * number of elements converted or zero on error. */
+static size_t av2value (pTHX_ char *name, AV *array, value_t *value, size_t array_len)
{
const data_set_t *ds;
- int i = 0;
-
- if ((NULL == name) || (NULL == array) || (NULL == value))
- return -1;
-
- if (av_len (array) < len - 1)
- len = av_len (array) + 1;
-
- if (0 >= len)
- return -1;
+ if ((NULL == name) || (NULL == array) || (NULL == value) || (array_len == 0))
+ return 0;
ds = plugin_get_ds (name);
if (NULL == ds) {
log_err ("av2value: Unknown dataset \"%s\"", name);
- return -1;
+ return 0;
}
- if (ds->ds_num < len) {
- log_warn ("av2value: Value length exceeds data set length.");
- len = ds->ds_num;
+ if (array_len < ds->ds_num) {
+ log_warn ("av2value: array does not contain enough elements for type \"%s\": got %zu, want %zu",
+ name, array_len, ds->ds_num);
+ return 0;
+ } else if (array_len > ds->ds_num) {
+ log_warn ("av2value: array contains excess elements for type \"%s\": got %zu, want %zu",
+ name, array_len, ds->ds_num);
}
- for (i = 0; i < len; ++i) {
+ for (size_t i = 0; i < ds->ds_num; ++i) {
SV **tmp = av_fetch (array, i, 0);
if (NULL != tmp) {
value[i].absolute = SvIV (*tmp);
}
else {
- return -1;
+ return 0;
}
}
- return len;
-} /* static int av2value (char *, AV *, value_t *, int) */
+
+ return ds->ds_num;
+} /* static size_t av2value (char *, AV *, value_t *, size_t) */
/*
* value list:
{
AV *array = (AV *)SvRV (*tmp);
- int len = av_len (array) + 1;
-
- if (len <= 0)
+ /* av_len returns the highest index, not the actual length. */
+ size_t array_len = (size_t) (av_len (array) + 1);
+ if (array_len == 0)
return -1;
- vl->values = (value_t *)smalloc (len * sizeof (value_t));
- vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp),
- vl->values, len);
-
- if (-1 == vl->values_len) {
+ vl->values = calloc (array_len, sizeof (*vl->values));
+ vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp), vl->values, array_len);
+ if (vl->values_len == 0) {
sfree (vl->values);
return -1;
}
static int av2data_set (pTHX_ AV *array, char *name, data_set_t *ds)
{
- int len, i;
+ int len;
if ((NULL == array) || (NULL == name) || (NULL == ds))
return -1;
return -1;
}
- ds->ds = (data_source_t *)smalloc ((len + 1) * sizeof (data_source_t));
+ ds->ds = smalloc ((len + 1) * sizeof (*ds->ds));
ds->ds_num = len + 1;
- for (i = 0; i <= len; ++i) {
+ for (int i = 0; i <= len; ++i) {
SV **elem = av_fetch (array, i, 0);
if (NULL == elem) {
notification_meta_t **m = meta;
int len = av_len (array);
- int i;
- for (i = 0; i <= len; ++i) {
+ for (int i = 0; i <= len; ++i) {
SV **tmp = av_fetch (array, i, 0);
HV *hash;
hash = (HV *)SvRV (*tmp);
- *m = (notification_meta_t *)smalloc (sizeof (**m));
+ *m = smalloc (sizeof (**m));
if (NULL == (tmp = hv_fetch (hash, "name", 4, 0))) {
log_warn ("av2notification_meta: Skipping invalid "
static int data_set2av (pTHX_ data_set_t *ds, AV *array)
{
- int i = 0;
-
if ((NULL == ds) || (NULL == array))
return -1;
av_extend (array, ds->ds_num);
- for (i = 0; i < ds->ds_num; ++i) {
+ for (size_t i = 0; i < ds->ds_num; ++i) {
HV *source = newHV ();
if (NULL == hv_store (source, "name", 4,
static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash)
{
AV *values = NULL;
-
- int i = 0;
- int len = 0;
+ size_t i;
if ((NULL == vl) || (NULL == ds) || (NULL == hash))
return -1;
- len = vl->values_len;
-
- if (ds->ds_num < len) {
- log_warn ("value2av: Value length exceeds data set length.");
- len = ds->ds_num;
- }
-
values = newAV ();
- av_extend (values, len - 1);
+ /* av_extend takes the last *index* to which the array should be extended. */
+ av_extend (values, vl->values_len - 1);
- for (i = 0; i < len; ++i) {
+ assert (ds->ds_num == vl->values_len);
+ for (i = 0; i < vl->values_len; ++i) {
SV *val = NULL;
if (DS_TYPE_COUNTER == ds->ds[i].type)
static int notification_meta2av (pTHX_ notification_meta_t *meta, AV *array)
{
int meta_num = 0;
- int i;
while (meta) {
++meta_num;
av_extend (array, meta_num);
- for (i = 0; NULL != meta; meta = meta->next, ++i) {
+ for (int i = 0; NULL != meta; meta = meta->next, ++i) {
HV *m = newHV ();
SV *value;
static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash)
{
- int i;
-
AV *values;
AV *children;
return -1;
}
- for (i = 0; i < ci->values_num; ++i) {
+ for (int i = 0; i < ci->values_num; ++i) {
SV *value;
switch (ci->values[i].type) {
return -1;
}
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
HV *child = newHV ();
if (0 != oconfig_item2hv (aTHX_ ci->children + i, child)) {
*/
static int pplugin_dispatch_notification (pTHX_ HV *notif)
{
- notification_t n;
+ notification_t n = { 0 };
int ret;
if (NULL == notif)
return -1;
- memset (&n, 0, sizeof (n));
-
if (0 != hv2notification (aTHX_ notif, &n))
return -1;
assert (NULL != perl_threads);
- t = (c_ithread_t *)smalloc (sizeof (c_ithread_t));
+ t = smalloc (sizeof (*t));
memset (t, 0, sizeof (c_ithread_t));
t->interp = (NULL == base)
return -1;
}
- data = (pfc_user_data_t *)smalloc (sizeof (*data));
+ data = smalloc (sizeof (*data));
data->name = sstrdup (ci->values[0].value.string);
data->user_data = newSV (0);
static int perl_shutdown (void)
{
- c_ithread_t *t = NULL;
-
- int ret = 0;
+ c_ithread_t *t;
+ int ret;
dTHX;
return 0;
if (NULL == aTHX) {
- t = NULL;
-
pthread_mutex_lock (&perl_threads->mutex);
t = c_ithread_create (perl_threads->head->interp);
pthread_mutex_unlock (&perl_threads->mutex);
SV *tmp = NULL;
char *file = __FILE__;
- int i = 0;
-
dXSUB_SYS;
/* enable usage of Perl modules using shared libraries */
newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
/* register API */
- for (i = 0; NULL != api[i].f; ++i)
+ for (int i = 0; NULL != api[i].f; ++i)
newXS (api[i].name, api[i].f, file);
stash = gv_stashpv ("Collectd", 1);
/* export "constants" */
- for (i = 0; '\0' != constants[i].name[0]; ++i)
+ for (int i = 0; '\0' != constants[i].name[0]; ++i)
newCONSTSUB (stash, constants[i].name, newSViv (constants[i].value));
/* export global variables
* accessing any such variable (this is basically the same as using
* tie() in Perl) */
/* global strings */
- for (i = 0; '\0' != g_strings[i].name[0]; ++i) {
+ for (int i = 0; '\0' != g_strings[i].name[0]; ++i) {
tmp = get_sv (g_strings[i].name, 1);
sv_magicext (tmp, NULL, PERL_MAGIC_ext, &g_pv_vtbl,
g_strings[i].var, 0);
log_info ("Initializing Perl interpreter...");
#if COLLECT_DEBUG
{
- int i = 0;
-
- for (i = 0; i < argc; ++i)
+ for (int i = 0; i < argc; ++i)
log_debug ("argv[%i] = \"%s\"", i, argv[i]);
}
#endif /* COLLECT_DEBUG */
#endif
PERL_SYS_INIT3 (&argc, &argv, &environ);
- perl_threads = (c_ithread_list_t *)smalloc (sizeof (c_ithread_list_t));
+ perl_threads = smalloc (sizeof (*perl_threads));
memset (perl_threads, 0, sizeof (c_ithread_list_t));
pthread_mutexattr_init(&perl_threads->mutexattr);
value = ci->values[0].value.string;
- perl_argv = (char **)realloc (perl_argv,
+ perl_argv = realloc (perl_argv,
(++perl_argc + 1) * sizeof (char *));
if (NULL == perl_argv) {
perl_argv[perl_argc - 1] = "-d";
}
else {
- perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 4);
+ perl_argv[perl_argc - 1] = smalloc (strlen (value) + 4);
sstrncpy (perl_argv[perl_argc - 1], "-d:", 4);
sstrncpy (perl_argv[perl_argc - 1] + 3, value, strlen (value) + 1);
}
value = ci->values[0].value.string;
if (NULL == aTHX) {
- perl_argv = (char **)realloc (perl_argv,
+ perl_argv = realloc (perl_argv,
(++perl_argc + 1) * sizeof (char *));
if (NULL == perl_argv) {
exit (3);
}
- perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 3);
+ perl_argv[perl_argc - 1] = smalloc (strlen (value) + 3);
sstrncpy(perl_argv[perl_argc - 1], "-I", 3);
sstrncpy(perl_argv[perl_argc - 1] + 2, value, strlen (value) + 1);
static int perl_config (oconfig_item_t *ci)
{
int status = 0;
- int i = 0;
dTHXa (NULL);
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
int current_status = 0;
void module_register (void)
{
perl_argc = 4;
- perl_argv = (char **)smalloc ((perl_argc + 1) * sizeof (char *));
+ perl_argv = smalloc ((perl_argc + 1) * sizeof (*perl_argv));
/* default options for the Perl interpreter */
perl_argv[0] = "";
diff --git a/src/pf.c b/src/pf.c
index 112e28f3554dee66efb5dd5dcd3fb15843ad4e85..d7a5a15cff11b4cd3d2baf07297161fcc56867f3 100644 (file)
--- a/src/pf.c
+++ b/src/pf.c
*/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#if HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NET_IF_H
# include <net/if.h>
#endif
struct pf_status state;
int fd;
int status;
- int i;
fd = open (pf_device, O_RDONLY);
if (fd < 0)
return (-1);
}
- memset (&state, 0, sizeof (state));
status = ioctl (fd, DIOCGETSTATUS, &state);
if (status != 0)
{
}
close (fd);
- fd = -1;
if (!state.running)
{
return (-1);
}
- for (i = 0; i < PFRES_MAX; i++)
+ for (int i = 0; i < PFRES_MAX; i++)
pf_submit ("pf_counters", pf_reasons[i], state.counters[i],
/* is gauge = */ 0);
- for (i = 0; i < LCNT_MAX; i++)
+ for (int i = 0; i < LCNT_MAX; i++)
pf_submit ("pf_limits", pf_lcounters[i], state.lcounters[i],
/* is gauge = */ 0);
- for (i = 0; i < FCNT_MAX; i++)
+ for (int i = 0; i < FCNT_MAX; i++)
pf_submit ("pf_state", pf_fcounters[i], state.fcounters[i],
/* is gauge = */ 0);
- for (i = 0; i < SCNT_MAX; i++)
+ for (int i = 0; i < SCNT_MAX; i++)
pf_submit ("pf_source", pf_scounters[i], state.scounters[i],
/* is gauge = */ 0);
diff --git a/src/pinba.c b/src/pinba.c
index e94ad8f61b667b0728085bff1c5a7129f9dcd802..8a0902aa9c0136a0b6b4dce87498bd55f67b087e 100644 (file)
--- a/src/pinba.c
+++ b/src/pinba.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
-#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
const char *script)
{
pinba_statnode_t *node;
-
+
node = realloc (stat_nodes,
sizeof (*stat_nodes) * (stat_nodes_num + 1));
if (node == NULL)
node = stat_nodes + stat_nodes_num;
memset (node, 0, sizeof (*node));
-
+
/* reset strings */
node->name = NULL;
node->host = NULL;
node->script = NULL;
node->mem_peak = NAN;
-
+
/* fill query data */
strset (&node->name, name);
strset (&node->host, host);
strset (&node->server, server);
strset (&node->script, script);
-
+
/* increment counter */
stat_nodes_num++;
} /* }}} void service_statnode_add */
@@ -210,14 +208,14 @@ static unsigned int service_statnode_collect (pinba_statnode_t *res, /* {{{ */
unsigned int index)
{
pinba_statnode_t *node;
-
+
if (stat_nodes_num == 0)
return 0;
-
+
/* begin collecting */
if (index == 0)
pthread_mutex_lock (&stat_nodes_lock);
-
+
/* end collecting */
if (index >= stat_nodes_num)
{
/* reset node */
node->mem_peak = NAN;
-
+
return (index + 1);
} /* }}} unsigned int service_statnode_collect */
static void service_process_request (Pinba__Request *request) /* {{{ */
{
- unsigned int i;
-
pthread_mutex_lock (&stat_nodes_lock);
-
- for (i = 0; i < stat_nodes_num; i++)
+
+ for (unsigned int i = 0; i < stat_nodes_num; i++)
{
if ((stat_nodes[i].host != NULL)
&& (strcmp (request->hostname, stat_nodes[i].host) != 0))
service_statnode_process(&stat_nodes[i], request);
}
-
+
pthread_mutex_unlock(&stat_nodes_lock);
} /* }}} void service_process_request */
{
pinba_socket_t *s;
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
- struct addrinfo ai_hints;
int status;
- memset (&ai_hints, 0, sizeof (ai_hints));
- ai_hints.ai_flags = AI_PASSIVE;
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_DGRAM;
- ai_hints.ai_addr = NULL;
- ai_hints.ai_canonname = NULL;
- ai_hints.ai_next = NULL;
-
if (node == NULL)
node = PINBA_DEFAULT_NODE;
if (service == NULL)
service = PINBA_DEFAULT_SERVICE;
- ai_list = NULL;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_PASSIVE,
+ .ai_socktype = SOCK_DGRAM
+ };
+
status = getaddrinfo (node, service,
&ai_hints, &ai_list);
if (status != 0)
}
assert (ai_list != NULL);
- s = malloc (sizeof (*s));
+ s = calloc (1, sizeof (*s));
if (s == NULL)
{
freeaddrinfo (ai_list);
- ERROR ("pinba plugin: malloc failed.");
+ ERROR ("pinba plugin: calloc failed.");
return (NULL);
}
- memset (s, 0, sizeof (*s));
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
status = pb_add_socket (s, ai_ptr);
if (status != 0)
break;
} /* for (ai_list) */
-
+
freeaddrinfo (ai_list);
if (s->fd_num < 1)
static void pinba_socket_free (pinba_socket_t *socket) /* {{{ */
{
- nfds_t i;
-
if (!socket)
return;
-
- for (i = 0; i < socket->fd_num; i++)
+
+ for (nfds_t i = 0; i < socket->fd_num; i++)
{
if (socket->fd[i].fd < 0)
continue;
close (socket->fd[i].fd);
socket->fd[i].fd = -1;
}
-
+
sfree(socket);
} /* }}} void pinba_socket_free */
static int pinba_process_stats_packet (const uint8_t *buffer, /* {{{ */
size_t buffer_size)
{
- Pinba__Request *request;
-
+ Pinba__Request *request;
+
request = pinba__request__unpack (NULL, buffer_size, buffer);
-
+
if (!request)
return (-1);
service_process_request(request);
pinba__request__free_unpacked (request, NULL);
-
+
return (0);
} /* }}} int pinba_process_stats_packet */
while (!collector_thread_do_shutdown)
{
int status;
- nfds_t i;
if (s->fd_num < 1)
break;
return (-1);
}
- for (i = 0; i < s->fd_num; i++)
+ for (nfds_t i = 0; i < s->fd_num; i++)
{
if (s->fd[i].revents & (POLLERR | POLLHUP | POLLNVAL))
{
char *server = NULL;
char *script = NULL;
int status;
- int i;
status = cf_util_get_string (ci, &name);
if (status != 0)
return (status);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
static int plugin_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
/* The lock should not be necessary in the config callback, but let's be
* sure.. */
pthread_mutex_lock (&stat_nodes_lock);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
}
pthread_mutex_unlock(&stat_nodes_lock);
-
+
return (0);
} /* }}} int pinba_config */
{
value_t value;
value_list_t vl = VALUE_LIST_INIT;
-
+
vl.values = &value;
vl.values_len = 1;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin_instance, res->name, sizeof (vl.plugin_instance));
value.derive = res->req_count;
- sstrncpy (vl.type, "total_requests", sizeof (vl.type));
+ sstrncpy (vl.type, "total_requests", sizeof (vl.type));
plugin_dispatch_values (&vl);
value.derive = float_counter_get (&res->req_time, /* factor = */ 1000);
- sstrncpy (vl.type, "total_time_in_ms", sizeof (vl.type));
+ sstrncpy (vl.type, "total_time_in_ms", sizeof (vl.type));
plugin_dispatch_values (&vl);
value.derive = res->doc_size;
- sstrncpy (vl.type, "total_bytes", sizeof (vl.type));
+ sstrncpy (vl.type, "total_bytes", sizeof (vl.type));
plugin_dispatch_values (&vl);
value.derive = float_counter_get (&res->ru_utime, /* factor = */ 100);
{
unsigned int i=0;
pinba_statnode_t data;
-
+
while ((i = service_statnode_collect (&data, i)) != 0)
{
plugin_submit (&data);
}
-
+
return 0;
} /* }}} int plugin_read */
diff --git a/src/pinba.proto b/src/pinba.proto
index 5fd5439a11a0d501a5a127041c36710325a1d72e..22e61c6a4f06dd185bcc6ac792cd773e09b4fa04 100644 (file)
--- a/src/pinba.proto
+++ b/src/pinba.proto
+syntax = "proto2";
+
package Pinba;
option optimize_for = SPEED;
diff --git a/src/ping.c b/src/ping.c
index 5df82f475cb935383d629a23186bee2754382979..5f66aab341f552cadb2d786bde09784d2272b2be 100644 (file)
--- a/src/ping.c
+++ b/src/ping.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_complain.h"
-#include <pthread.h>
#include <netinet/in.h>
#if HAVE_NETDB_H
# include <netdb.h> /* NI_MAXHOST */
#endif
+#ifdef HAVE_SYS_CAPABILITY_H
+# include <sys/capability.h>
+#endif
+
#include <oping.h>
#ifndef NI_MAXHOST
#ifdef HAVE_OPING_1_3
static char *ping_device = NULL;
#endif
+static char *ping_data = NULL;
static int ping_ttl = PING_DEF_TTL;
static double ping_interval = 1.0;
static double ping_timeout = 0.9;
#ifdef HAVE_OPING_1_3
"Device",
#endif
+ "Size",
"TTL",
"Interval",
"Timeout",
static int ping_dispatch_all (pingobj_t *pingobj) /* {{{ */
{
- pingobj_iter_t *iter;
hostlist_t *hl;
int status;
- for (iter = ping_iterator_get (pingobj);
+ for (pingobj_iter_t *iter = ping_iterator_get (pingobj);
iter != NULL;
iter = ping_iterator_next (iter))
{ /* {{{ */
hl->pkg_missed++;
/* if the host did not answer our last N packages, trigger a resolv. */
- if (ping_max_missed >= 0 && hl->pkg_missed >= ping_max_missed)
+ if ((ping_max_missed >= 0)
+ && (hl->pkg_missed >= ((uint32_t) ping_max_missed)))
{ /* {{{ */
/* we reset the missed package counter here, since we only want to
* trigger a resolv every N packages and not every package _AFTER_ N
struct timespec ts_wait;
struct timespec ts_int;
- hostlist_t *hl;
int count;
c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
ping_setopt (pingobj, PING_OPT_TIMEOUT, (void *) &ping_timeout);
ping_setopt (pingobj, PING_OPT_TTL, (void *) &ping_ttl);
+ if (ping_data != NULL)
+ ping_setopt (pingobj, PING_OPT_DATA, (void *) ping_data);
+
/* Add all the hosts to the ping object. */
count = 0;
- for (hl = hostlist_head; hl != NULL; hl = hl->next)
+ for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next)
{
int tmp_status;
tmp_status = ping_host_add (pingobj, hl->host);
"Will use a timeout of %gs.", ping_timeout);
}
+#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_NET_RAW)
+ if (check_capability (CAP_NET_RAW) != 0)
+ {
+ if (getuid () == 0)
+ WARNING ("ping plugin: Running collectd as root, but the CAP_NET_RAW "
+ "capability is missing. The plugin's read function will probably "
+ "fail. Is your init system dropping capabilities?");
+ else
+ WARNING ("ping plugin: collectd doesn't have the CAP_NET_RAW capability. "
+ "If you don't want to run collectd as root, try running \"setcap "
+ "cap_net_raw=ep\" on the collectd binary.");
+ }
+#endif
+
return (start_thread ());
} /* }}} int ping_init */
hostlist_t *hl;
char *host;
- hl = (hostlist_t *) malloc (sizeof (hostlist_t));
+ hl = malloc (sizeof (*hl));
if (hl == NULL)
{
char errbuf[1024];
WARNING ("ping plugin: Ignoring invalid interval %g (%s)",
tmp, value);
}
+ else if (strcasecmp (key, "Size") == 0) {
+ size_t size = (size_t) atoi (value);
+
+ /* Max IP packet size - (IPv6 + ICMP) = 65535 - (40 + 8) = 65487 */
+ if (size <= 65487)
+ {
+ sfree (ping_data);
+ ping_data = malloc (size + 1);
+ if (ping_data == NULL)
+ {
+ ERROR ("ping plugin: malloc failed.");
+ return (1);
+ }
+
+ /* Note: By default oping is using constant string
+ * "liboping -- ICMP ping library <http://octo.it/liboping/>"
+ * which is exactly 56 bytes.
+ *
+ * Optimally we would follow the ping(1) behaviour, but we
+ * cannot use byte 00 or start data payload at exactly same
+ * location, due to oping library limitations. */
+ for (size_t i = 0; i < size; i++) /* {{{ */
+ {
+ /* This restricts data pattern to be only composed of easily
+ * printable characters, and not NUL character. */
+ ping_data[i] = ('0' + i % 64);
+ } /* }}} for (i = 0; i < size; i++) */
+ ping_data[size] = 0;
+ } else
+ WARNING ("ping plugin: Ignoring invalid Size %zu.", size);
+ }
else if (strcasecmp (key, "Timeout") == 0)
{
double tmp;
static int ping_read (void) /* {{{ */
{
- hostlist_t *hl;
-
if (ping_thread_error != 0)
{
ERROR ("ping plugin: The ping thread had a problem. Restarting it.");
stop_thread ();
- for (hl = hostlist_head; hl != NULL; hl = hl->next)
+ for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next)
{
hl->pkg_sent = 0;
hl->pkg_recv = 0;
return (-1);
} /* if (ping_thread_error != 0) */
- for (hl = hostlist_head; hl != NULL; hl = hl->next) /* {{{ */
+ for (hostlist_t *hl = hostlist_head; hl != NULL; hl = hl->next) /* {{{ */
{
uint32_t pkg_sent;
uint32_t pkg_recv;
hl = hl_next;
}
+ if (ping_data != NULL) {
+ free (ping_data);
+ ping_data = NULL;
+ }
+
return (0);
} /* }}} int ping_shutdown */
diff --git a/src/postgresql.c b/src/postgresql.c
index 23c4af31e0909de86cb135fba2d8d3c41c9f33ca..084eae453393a3bb86c0766966d2e45b5a514e5f 100644 (file)
--- a/src/postgresql.c
+++ b/src/postgresql.c
*/
#include "collectd.h"
+
#include "common.h"
-#include "configfile.h"
#include "plugin.h"
#include "utils_cache.h"
#include "utils_db_query.h"
#include "utils_complain.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
#include <pg_config_manual.h>
#include <libpq-fe.h>
int ref_cnt;
} c_psql_database_t;
-static char *def_queries[] = {
+static const char *const def_queries[] = {
"backends",
"transactions",
"queries",
c_psql_database_t **tmp;
c_psql_database_t *db;
- db = (c_psql_database_t *)malloc (sizeof(*db));
+ db = malloc (sizeof(*db));
if (NULL == db) {
log_err ("Out of memory.");
return NULL;
}
- tmp = (c_psql_database_t **)realloc (databases,
+ tmp = realloc (databases,
(databases_num + 1) * sizeof (*databases));
if (NULL == tmp) {
log_err ("Out of memory.");
static void c_psql_database_delete (void *data)
{
- size_t i;
-
c_psql_database_t *db = data;
--db->ref_cnt;
db->conn = NULL;
if (db->q_prep_areas)
- for (i = 0; i < db->queries_num; ++i)
+ for (size_t i = 0; i < db->queries_num; ++i)
udb_query_delete_preparation_area (db->q_prep_areas[i]);
free (db->q_prep_areas);
static PGresult *c_psql_exec_query_params (c_psql_database_t *db,
udb_query_t *q, c_psql_user_data_t *data)
{
- char *params[db->max_params_num];
- char interval[64];
- int i;
+ const char *params[db->max_params_num];
+ char interval[64];
if ((data == NULL) || (data->params_num == 0))
return (c_psql_exec_query_noparams (db, q));
assert (db->max_params_num >= data->params_num);
- for (i = 0; i < data->params_num; ++i) {
+ for (int i = 0; i < data->params_num; ++i) {
switch (data->params[i]) {
case C_PSQL_PARAM_HOST:
params[i] = C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
int rows_num;
int status;
- int row, col;
/* The user data may hold parameter information, but may be NULL. */
data = udb_query_get_user_data (q);
log_err ("calloc failed.");
BAIL_OUT (-1);
}
-
- for (col = 0; col < column_num; ++col) {
+
+ for (int col = 0; col < column_num; ++col) {
/* Pointers returned by `PQfname' are freed by `PQclear' via
* `BAIL_OUT'. */
column_names[col] = PQfname (res, col);
BAIL_OUT (-1);
}
- for (row = 0; row < rows_num; ++row) {
+ for (int row = 0; row < rows_num; ++row) {
+ int col;
for (col = 0; col < column_num; ++col) {
/* Pointers returned by `PQgetvalue' are freed by `PQclear' via
* `BAIL_OUT'. */
c_psql_database_t *db;
int success = 0;
- int i;
if ((ud == NULL) || (ud->data == NULL)) {
log_err ("c_psql_read: Invalid user data.");
return -1;
}
- for (i = 0; i < db->queries_num; ++i)
+ for (size_t i = 0; i < db->queries_num; ++i)
{
udb_query_preparation_area_t *prep_area;
udb_query_t *q;
char *str_ptr;
size_t str_len;
- int i;
-
str_ptr = string;
str_len = string_len;
- for (i = 0; i < ds->ds_num; ++i) {
+ for (size_t i = 0; i < ds->ds_num; ++i) {
int status = ssnprintf (str_ptr, str_len, ",'%s'", ds->ds[i].name);
if (status < 1)
char *str_ptr;
size_t str_len;
- int i;
-
str_ptr = string;
str_len = string_len;
- for (i = 0; i < ds->ds_num; ++i) {
+ for (size_t i = 0; i < ds->ds_num; ++i) {
int status;
if (store_rates)
@@ -752,12 +740,10 @@ static char *values_to_sqlarray (const data_set_t *ds, const value_list_t *vl,
gauge_t *rates = NULL;
- int i;
-
str_ptr = string;
str_len = string_len;
- for (i = 0; i < vl->values_len; ++i) {
+ for (size_t i = 0; i < vl->values_len; ++i) {
int status = 0;
if ((ds->ds[i].type != DS_TYPE_GAUGE)
{
c_psql_database_t *db;
- char time_str[32];
+ char time_str[RFC3339NANO_SIZE];
char values_name_str[1024];
char values_type_str[1024];
char values_str[1024];
const char *params[9];
int success = 0;
- int i;
if ((ud == NULL) || (ud->data == NULL)) {
log_err ("c_psql_write: Invalid user data.");
assert (db->database != NULL);
assert (db->writers != NULL);
- if (cdtime_to_iso8601 (time_str, sizeof (time_str), vl->time) == 0) {
- log_err ("c_psql_write: Failed to convert time to ISO 8601 format");
+ if (rfc3339nano (time_str, sizeof (time_str), vl->time) != 0) {
+ log_err ("c_psql_write: Failed to convert time to RFC 3339 format");
return -1;
}
#undef VALUE_OR_NULL
if( db->expire_delay > 0 && vl->time < (cdtime() - vl->interval - db->expire_delay) ) {
- log_info ("c_psql_write: Skipped expired value @ %s - %s/%s-%s/%s-%s/%s",
+ log_info ("c_psql_write: Skipped expired value @ %s - %s/%s-%s/%s-%s/%s",
params[0], params[1], params[2], params[3], params[4], params[5], params[6] );
return 0;
}
&& (db->next_commit == 0))
c_psql_begin (db);
- for (i = 0; i < db->writers_num; ++i) {
+ for (size_t i = 0; i < db->writers_num; ++i) {
c_psql_writer_t *writer;
PGresult *res;
{
c_psql_database_t **dbs = databases;
size_t dbs_num = databases_num;
- size_t i;
if ((ud != NULL) && (ud->data != NULL)) {
dbs = (void *)&ud->data;
dbs_num = 1;
}
- for (i = 0; i < dbs_num; ++i) {
+ for (size_t i = 0; i < dbs_num; ++i) {
c_psql_database_t *db = dbs[i];
/* don't commit if the timeout is larger than the regular commit
static int c_psql_shutdown (void)
{
- size_t i = 0;
-
_Bool had_flush = 0;
plugin_unregister_read_group ("postgresql");
- for (i = 0; i < databases_num; ++i) {
+ for (size_t i = 0; i < databases_num; ++i) {
c_psql_database_t *db = databases[i];
if (db->writers_num > 0) {
data = udb_query_get_user_data (q);
if (NULL == data) {
- data = malloc (sizeof (*data));
+ data = calloc (1, sizeof (*data));
if (NULL == data) {
log_err ("Out of memory.");
return -1;
}
- memset (data, 0, sizeof (*data));
data->params = NULL;
data->params_num = 0;
if (strcasecmp (name, src_writers[i].name) != 0)
continue;
- tmp = (c_psql_writer_t **)realloc (*dst_writers,
+ tmp = realloc (*dst_writers,
sizeof (**dst_writers) * (*dst_writers_num + 1));
if (tmp == NULL) {
log_err ("Out of memory.");
c_psql_writer_t *tmp;
int status = 0;
- int i;
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_STRING)) {
return 1;
}
- tmp = (c_psql_writer_t *)realloc (writers,
+ tmp = realloc (writers,
sizeof (*writers) * (writers_num + 1));
if (tmp == NULL) {
log_err ("Out of memory.");
writer->statement = NULL;
writer->store_rates = 1;
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
if (strcasecmp ("Statement", c->key) == 0)
c_psql_database_t *db;
char cb_name[DATA_MAX_NAME_LEN];
- struct timespec cb_interval = { 0, 0 };
- user_data_t ud;
-
static _Bool have_flush = 0;
- int i;
-
if ((1 != ci->values_num)
|| (OCONFIG_TYPE_STRING != ci->values[0].type)) {
log_err ("<Database> expects a single string argument.");
return 1;
}
- memset (&ud, 0, sizeof (ud));
-
db = c_psql_database_new (ci->values[0].value.string);
if (db == NULL)
return -1;
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
if (0 == strcasecmp (c->key, "Host"))
/* If no `Query' options were given, add the default queries.. */
if ((db->queries_num == 0) && (db->writers_num == 0)){
- for (i = 0; i < def_queries_num; i++)
+ for (int i = 0; i < def_queries_num; i++)
udb_query_pick_from_list_by_name (def_queries[i],
queries, queries_num,
&db->queries, &db->queries_num);
}
}
- for (i = 0; (size_t)i < db->queries_num; ++i) {
+ for (int i = 0; (size_t)i < db->queries_num; ++i) {
c_psql_user_data_t *data;
data = udb_query_get_user_data (db->queries[i]);
if ((data != NULL) && (data->params_num > db->max_params_num))
}
}
- ud.data = db;
- ud.free_func = c_psql_database_delete;
-
ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->instance);
- if (db->queries_num > 0) {
- CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval);
+ user_data_t ud = {
+ .data = db,
+ .free_func = c_psql_database_delete
+ };
+ if (db->queries_num > 0) {
++db->ref_cnt;
plugin_register_complex_read ("postgresql", cb_name, c_psql_read,
- /* interval = */ (db->interval > 0) ? &cb_interval : NULL,
- &ud);
+ /* interval = */ db->interval, &ud);
}
if (db->writers_num > 0) {
++db->ref_cnt;
{
static int have_def_config = 0;
- int i;
-
if (0 == have_def_config) {
oconfig_item_t *c;
"any queries - please check your installation.");
}
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
if (0 == strcasecmp (c->key, "Query"))
diff --git a/src/powerdns.c b/src/powerdns.c
index 1d2516efbc980786e02752018e167a67ea4804da..c392f0f64e128970f5f52ed9977c309f1a9054d3 100644 (file)
--- a/src/powerdns.c
+++ b/src/powerdns.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_llist.h"
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <sys/un.h>
#ifndef UNIX_PATH_MAX
struct statname_lookup_s
{
- char *name;
- char *type;
- char *type_instance;
+ const char *name;
+ const char *type;
+ const char *type_instance;
};
typedef struct statname_lookup_s statname_lookup_t;
/* Description of statistics returned by the recursor: {{{
-all-outqueries counts the number of outgoing UDP queries since starting
-answers0-1 counts the number of queries answered within 1 millisecond
-answers100-1000 counts the number of queries answered within 1 second
-answers10-100 counts the number of queries answered within 100 milliseconds
-answers1-10 counts the number of queries answered within 10 milliseconds
-answers-slow counts the number of queries answered after 1 second
-cache-entries shows the number of entries in the cache
-cache-hits counts the number of cache hits since starting
-cache-misses counts the number of cache misses since starting
-chain-resends number of queries chained to existing outstanding query
-client-parse-errors counts number of client packets that could not be parsed
-concurrent-queries shows the number of MThreads currently running
-dlg-only-drops number of records dropped because of delegation only setting
-negcache-entries shows the number of entries in the Negative answer cache
-noerror-answers counts the number of times it answered NOERROR since starting
-nsspeeds-entries shows the number of entries in the NS speeds map
-nsset-invalidations number of times an nsset was dropped because it no longer worked
-nxdomain-answers counts the number of times it answered NXDOMAIN since starting
-outgoing-timeouts counts the number of timeouts on outgoing UDP queries since starting
-qa-latency shows the current latency average
-questions counts all End-user initiated queries with the RD bit set
-resource-limits counts number of queries that could not be performed because of resource limits
-server-parse-errors counts number of server replied packets that could not be parsed
-servfail-answers counts the number of times it answered SERVFAIL since starting
-spoof-prevents number of times PowerDNS considered itself spoofed, and dropped the data
-sys-msec number of CPU milliseconds spent in 'system' mode
-tcp-client-overflow number of times an IP address was denied TCP access because it already had too many connections
-tcp-outqueries counts the number of outgoing TCP queries since starting
-tcp-questions counts all incoming TCP queries (since starting)
-throttled-out counts the number of throttled outgoing UDP queries since starting
-throttle-entries shows the number of entries in the throttle map
-unauthorized-tcp number of TCP questions denied because of allow-from restrictions
-unauthorized-udp number of UDP questions denied because of allow-from restrictions
-unexpected-packets number of answers from remote servers that were unexpected (might point to spoofing)
-uptime number of seconds process has been running (since 3.1.5)
-user-msec number of CPU milliseconds spent in 'user' mode
+all-outqueries counts the number of outgoing UDP queries since starting
+answers-slow counts the number of queries answered after 1 second
+answers0-1 counts the number of queries answered within 1 millisecond
+answers1-10 counts the number of queries answered within 10 milliseconds
+answers10-100 counts the number of queries answered within 100 milliseconds
+answers100-1000 counts the number of queries answered within 1 second
+cache-bytes size of the cache in bytes (since 3.3.1)
+cache-entries shows the number of entries in the cache
+cache-hits counts the number of cache hits since starting, this does not include hits that got answered from the packet-cache
+cache-misses counts the number of cache misses since starting
+case-mismatches counts the number of mismatches in character case since starting
+chain-resends number of queries chained to existing outstanding query
+client-parse-errors counts number of client packets that could not be parsed
+concurrent-queries shows the number of MThreads currently running
+dlg-only-drops number of records dropped because of delegation only setting
+dont-outqueries number of outgoing queries dropped because of 'dont-query' setting (since 3.3)
+edns-ping-matches number of servers that sent a valid EDNS PING respons
+edns-ping-mismatches number of servers that sent an invalid EDNS PING response
+failed-host-entries number of servers that failed to resolve
+ipv6-outqueries number of outgoing queries over IPv6
+ipv6-questions counts all End-user initiated queries with the RD bit set, received over IPv6 UDP
+malloc-bytes returns the number of bytes allocated by the process (broken, always returns 0)
+max-mthread-stack maximum amount of thread stack ever used
+negcache-entries shows the number of entries in the Negative answer cache
+no-packet-error number of errorneous received packets
+noedns-outqueries number of queries sent out without EDNS
+noerror-answers counts the number of times it answered NOERROR since starting
+noping-outqueries number of queries sent out without ENDS PING
+nsset-invalidations number of times an nsset was dropped because it no longer worked
+nsspeeds-entries shows the number of entries in the NS speeds map
+nxdomain-answers counts the number of times it answered NXDOMAIN since starting
+outgoing-timeouts counts the number of timeouts on outgoing UDP queries since starting
+over-capacity-drops questions dropped because over maximum concurrent query limit (since 3.2)
+packetcache-bytes size of the packet cache in bytes (since 3.3.1)
+packetcache-entries size of packet cache (since 3.2)
+packetcache-hits packet cache hits (since 3.2)
+packetcache-misses packet cache misses (since 3.2)
+policy-drops packets dropped because of (Lua) policy decision
+qa-latency shows the current latency average
+questions counts all end-user initiated queries with the RD bit set
+resource-limits counts number of queries that could not be performed because of resource limits
+security-status security status based on security polling
+server-parse-errors counts number of server replied packets that could not be parsed
+servfail-answers counts the number of times it answered SERVFAIL since starting
+spoof-prevents number of times PowerDNS considered itself spoofed, and dropped the data
+sys-msec number of CPU milliseconds spent in 'system' mode
+tcp-client-overflow number of times an IP address was denied TCP access because it already had too many connections
+tcp-clients counts the number of currently active TCP/IP clients
+tcp-outqueries counts the number of outgoing TCP queries since starting
+tcp-questions counts all incoming TCP queries (since starting)
+throttle-entries shows the number of entries in the throttle map
+throttled-out counts the number of throttled outgoing UDP queries since starting
+throttled-outqueries idem to throttled-out
+unauthorized-tcp number of TCP questions denied because of allow-from restrictions
+unauthorized-udp number of UDP questions denied because of allow-from restrictions
+unexpected-packets number of answers from remote servers that were unexpected (might point to spoofing)
+unreachables number of times nameservers were unreachable since starting
+uptime number of seconds process has been running (since 3.1.5)
+user-msec number of CPU milliseconds spent in 'user' mode
}}} */
-const char* const default_server_fields[] = /* {{{ */
+static const char* const default_server_fields[] = /* {{{ */
{
"latency",
"packetcache-hit",
"udp-answers",
"udp-queries",
}; /* }}} */
-int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields);
+static int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields);
-statname_lookup_t lookup_table[] = /* {{{ */
+static statname_lookup_t lookup_table[] = /* {{{ */
{
/*********************
* Server statistics *
{"udp-answers-bytes", "total_bytes", "udp-answers-bytes"},
/* Cache stuff */
+ {"cache-bytes", "cache_size", "cache-bytes"},
+ {"packetcache-bytes", "cache_size", "packet-bytes"},
+ {"packetcache-entries", "cache_size", "packet-entries"},
{"packetcache-hit", "cache_result", "packet-hit"},
+ {"packetcache-hits", "cache_result", "packet-hit"},
{"packetcache-miss", "cache_result", "packet-miss"},
+ {"packetcache-misses", "cache_result", "packet-miss"},
{"packetcache-size", "cache_size", "packet"},
{"key-cache-size", "cache_size", "key"},
{"meta-cache-size", "cache_size", "meta"},
{"corrupt-packets", "ipt_packets", "corrupt"},
{"deferred-cache-inserts", "counter", "cache-deferred_insert"},
{"deferred-cache-lookup", "counter", "cache-deferred_lookup"},
+ {"dont-outqueries", "dns_question", "dont-outqueries"},
{"qsize-a", "cache_size", "answers"},
{"qsize-q", "cache_size", "questions"},
{"servfail-packets", "ipt_packets", "servfail"},
* Recursor statistics *
***********************/
/* Answers by return code */
- {"noerror-answers", "dns_rcode", "NOERROR"},
- {"nxdomain-answers", "dns_rcode", "NXDOMAIN"},
- {"servfail-answers", "dns_rcode", "SERVFAIL"},
+ {"noerror-answers", "dns_rcode", "NOERROR"},
+ {"nxdomain-answers", "dns_rcode", "NXDOMAIN"},
+ {"servfail-answers", "dns_rcode", "SERVFAIL"},
/* CPU utilization */
- {"sys-msec", "cpu", "system"},
- {"user-msec", "cpu", "user"},
+ {"sys-msec", "cpu", "system"},
+ {"user-msec", "cpu", "user"},
/* Question-to-answer latency */
- {"qa-latency", "latency", NULL},
+ {"qa-latency", "latency", NULL},
/* Cache */
- {"cache-entries", "cache_size", NULL},
- {"cache-hits", "cache_result", "hit"},
- {"cache-misses", "cache_result", "miss"},
+ {"cache-entries", "cache_size", NULL},
+ {"cache-hits", "cache_result", "hit"},
+ {"cache-misses", "cache_result", "miss"},
/* Total number of questions.. */
- {"questions", "dns_qtype", "total"},
+ {"questions", "dns_qtype", "total"},
/* All the other stuff.. */
- {"all-outqueries", "dns_question", "outgoing"},
- {"answers0-1", "dns_answer", "0_1"},
- {"answers1-10", "dns_answer", "1_10"},
- {"answers10-100", "dns_answer", "10_100"},
- {"answers100-1000", "dns_answer", "100_1000"},
- {"answers-slow", "dns_answer", "slow"},
- {"chain-resends", "dns_question", "chained"},
- {"client-parse-errors", "counter", "drops-client_parse_error"},
- {"concurrent-queries", "dns_question", "concurrent"},
- {"dlg-only-drops", "counter", "drops-delegation_only"},
- {"negcache-entries", "cache_size", "negative"},
- {"nsspeeds-entries", "gauge", "entries-ns_speeds"},
- {"nsset-invalidations", "counter", "ns_set_invalidation"},
- {"outgoing-timeouts", "counter", "drops-timeout_outgoing"},
- {"resource-limits", "counter", "drops-resource_limit"},
- {"server-parse-errors", "counter", "drops-server_parse_error"},
- {"spoof-prevents", "counter", "drops-spoofed"},
- {"tcp-client-overflow", "counter", "denied-client_overflow_tcp"},
- {"tcp-outqueries", "dns_question", "outgoing-tcp"},
- {"tcp-questions", "dns_question", "incoming-tcp"},
- {"throttled-out", "dns_question", "outgoing-throttled"},
- {"throttle-entries", "gauge", "entries-throttle"},
- {"unauthorized-tcp", "counter", "denied-unauthorized_tcp"},
- {"unauthorized-udp", "counter", "denied-unauthorized_udp"},
- {"unexpected-packets", "dns_answer", "unexpected"},
- {"uptime", "uptime", NULL}
+ {"all-outqueries", "dns_question", "outgoing"},
+ {"answers0-1", "dns_answer", "0_1"},
+ {"answers1-10", "dns_answer", "1_10"},
+ {"answers10-100", "dns_answer", "10_100"},
+ {"answers100-1000", "dns_answer", "100_1000"},
+ {"answers-slow", "dns_answer", "slow"},
+ {"case-mismatches", "counter", "case_mismatches"},
+ {"chain-resends", "dns_question", "chained"},
+ {"client-parse-errors", "counter", "drops-client_parse_error"},
+ {"concurrent-queries", "dns_question", "concurrent"},
+ {"dlg-only-drops", "counter", "drops-delegation_only"},
+ {"edns-ping-matches", "counter", "edns-ping_matches"},
+ {"edns-ping-mismatches", "counter", "edns-ping_mismatches"},
+ {"failed-host-entries", "counter", "entries-failed_host"},
+ {"ipv6-outqueries", "dns_question", "outgoing-ipv6"},
+ {"ipv6-questions", "dns_question", "incoming-ipv6"},
+ {"malloc-bytes", "gauge", "malloc_bytes"},
+ {"max-mthread-stack", "gauge", "max_mthread_stack"},
+ {"no-packet-error", "gauge", "no_packet_error"},
+ {"noedns-outqueries", "dns_question", "outgoing-noedns"},
+ {"noping-outqueries", "dns_question", "outgoing-noping"},
+ {"over-capacity-drops", "dns_question", "incoming-over_capacity"},
+ {"negcache-entries", "cache_size", "negative"},
+ {"nsspeeds-entries", "gauge", "entries-ns_speeds"},
+ {"nsset-invalidations", "counter", "ns_set_invalidation"},
+ {"outgoing-timeouts", "counter", "drops-timeout_outgoing"},
+ {"policy-drops", "counter", "drops-policy"},
+ {"resource-limits", "counter", "drops-resource_limit"},
+ {"server-parse-errors", "counter", "drops-server_parse_error"},
+ {"spoof-prevents", "counter", "drops-spoofed"},
+ {"tcp-client-overflow", "counter", "denied-client_overflow_tcp"},
+ {"tcp-clients", "gauge", "clients-tcp"},
+ {"tcp-outqueries", "dns_question", "outgoing-tcp"},
+ {"tcp-questions", "dns_question", "incoming-tcp"},
+ {"throttled-out", "dns_question", "outgoing-throttled"},
+ {"throttle-entries", "gauge", "entries-throttle"},
+ {"throttled-outqueries", "dns_question", "outgoing-throttle"},
+ {"unauthorized-tcp", "counter", "denied-unauthorized_tcp"},
+ {"unauthorized-udp", "counter", "denied-unauthorized_udp"},
+ {"unexpected-packets", "dns_answer", "unexpected"},
+ {"uptime", "uptime", NULL}
}; /* }}} */
-int lookup_table_length = STATIC_ARRAY_SIZE (lookup_table);
+static int lookup_table_length = STATIC_ARRAY_SIZE (lookup_table);
static llist_t *list = NULL;
static char *local_sockpath = NULL;
/* TODO: Do this before 4.4:
- * - Recursor:
- * - Complete list of known pdns -> collectd mappings.
* - Update the collectd.conf(5) manpage.
*
* -octo
*/
-/* <http://doc.powerdns.com/recursor-stats.html> */
+/* <https://doc.powerdns.com/md/recursor/stats/> */
static void submit (const char *plugin_instance, /* {{{ */
const char *pdns_type, const char *value)
{
if (ds->ds_num != 1)
{
- ERROR ("powerdns plugin: type `%s' has %i data sources, "
+ ERROR ("powerdns plugin: type `%s' has %zu data sources, "
"but I can only handle one.",
type, ds->ds_num);
return;
char *buffer = NULL;
size_t buffer_size = 0;
- struct sockaddr_un sa_unix;
+ struct sockaddr_un sa_unix = { 0 };
struct timeval stv_timeout;
cdtime_t cdt_timeout;
return (-1);
}
- memset (&sa_unix, 0, sizeof (sa_unix));
sa_unix.sun_family = AF_UNIX;
sstrncpy (sa_unix.sun_path,
(local_sockpath != NULL) ? local_sockpath : PDNS_LOCAL_SOCKPATH,
return (-1);
assert (buffer_size > 0);
- buffer = (char *) malloc (buffer_size);
+ buffer = malloc (buffer_size);
if (buffer == NULL)
{
FUNC_ERROR ("malloc");
else if (status == 0)
break;
- buffer_new = (char *) realloc (buffer, buffer_size + status + 1);
+ buffer_new = realloc (buffer, buffer_size + status + 1);
if (buffer_new == NULL)
{
FUNC_ERROR ("realloc");
saveptr = NULL;
while ((key = strtok_r (dummy, ",", &saveptr)) != NULL)
{
- int i;
-
dummy = NULL;
value = strchr (key, '=');
continue;
/* Check if this item was requested. */
+ int i;
for (i = 0; i < fields_num; i++)
if (strcasecmp (key, fields[i]) == 0)
break;
return (-1);
}
buffer[sizeof (buffer) - 1] = 0;
- int i = strlen (buffer);
- if (i < sizeof (buffer) - 2)
+ size_t len = strlen (buffer);
+ if (len < sizeof (buffer) - 2)
{
- buffer[i++] = ' ';
- buffer[i++] = '\n';
- buffer[i++] = '\0';
+ buffer[len++] = ' ';
+ buffer[len++] = '\n';
+ buffer[len++] = '\0';
}
}
static int powerdns_config_add_collect (list_item_t *li, /* {{{ */
oconfig_item_t *ci)
{
- int i;
char **temp;
if (ci->values_num < 1)
return (-1);
}
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
if (ci->values[i].type != OCONFIG_TYPE_STRING)
{
WARNING ("powerdns plugin: Only string arguments are allowed to "
return (-1);
}
- temp = (char **) realloc (li->fields,
+ temp = realloc (li->fields,
sizeof (char *) * (li->fields_num + ci->values_num));
if (temp == NULL)
{
}
li->fields = temp;
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
li->fields[li->fields_num] = strdup (ci->values[i].value.string);
if (li->fields[li->fields_num] == NULL)
list_item_t *item;
int status;
- int i;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
return (-1);
}
- item = (list_item_t *) malloc (sizeof (list_item_t));
+ item = calloc (1, sizeof (*item));
if (item == NULL)
{
- ERROR ("powerdns plugin: malloc failed.");
+ ERROR ("powerdns plugin: calloc failed.");
return (-1);
}
- memset (item, '\0', sizeof (list_item_t));
item->instance = strdup (ci->values[0].value.string);
if (item->instance == NULL)
}
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
static int powerdns_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
DEBUG ("powerdns plugin: powerdns_config (ci = %p);", (void *) ci);
if (list == NULL)
}
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
static int powerdns_read (void)
{
- llentry_t *e;
-
- for (e = llist_head (list); e != NULL; e = e->next)
+ for (llentry_t *e = llist_head (list); e != NULL; e = e->next)
{
list_item_t *item = e->value;
item->func (item);
static int powerdns_shutdown (void)
{
- llentry_t *e;
-
if (list == NULL)
return (0);
- for (e = llist_head (list); e != NULL; e = e->next)
+ for (llentry_t *e = llist_head (list); e != NULL; e = e->next)
{
list_item_t *item = (list_item_t *) e->value;
e->value = NULL;
diff --git a/src/processes.c b/src/processes.c
index 7a3c0e9b7f6bf4faa72f2486ff5b41e781b446c7..0513a156a999d4330ca63599b176abc31b68682d 100644 (file)
--- a/src/processes.c
+++ b/src/processes.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
/* Include header files for the mach system, if they exist.. */
#if HAVE_THREAD_INFO
derive_t io_syscr;
derive_t io_syscw;
+ derive_t cswitch_vol;
+ derive_t cswitch_invol;
+
struct procstat_entry_s *next;
} procstat_entry_t;
derive_t io_syscr;
derive_t io_syscw;
+ derive_t cswitch_vol;
+ derive_t cswitch_invol;
+
struct procstat *next;
struct procstat_entry_s *instances;
} procstat_t;
static procstat_t *list_head_g = NULL;
+static _Bool report_ctx_switch = 0;
+
#if HAVE_THREAD_INFO
static mach_port_t port_host_self;
static mach_port_t port_task_self;
procstat_t *ptr;
int status;
- new = (procstat_t *) malloc (sizeof (procstat_t));
+ new = calloc (1, sizeof (*new));
if (new == NULL)
{
- ERROR ("processes plugin: ps_list_register: malloc failed.");
+ ERROR ("processes plugin: ps_list_register: calloc failed.");
return;
}
- memset (new, 0, sizeof (procstat_t));
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));
+ new->re = malloc (sizeof (*new->re));
if (new->re == NULL)
{
ERROR ("processes plugin: ps_list_register: malloc failed.");
if (status != 0)
{
DEBUG ("ProcessMatch: compiling the regular expression \"%s\" failed.", regexp);
- sfree(new->re);
- sfree(new);
+ sfree (new->re);
+ sfree (new);
return;
}
}
@@ -359,17 +366,39 @@ static int ps_list_match (const char *name, const char *cmdline, procstat_t *ps)
return (0);
} /* int ps_list_match */
+static void ps_update_counter (_Bool init, derive_t *group_counter,
+ derive_t *curr_counter, unsigned long *curr_value,
+ derive_t new_counter, unsigned long new_value)
+{
+ if (init)
+ {
+ *curr_value = new_value;
+ *curr_counter += new_value;
+ *group_counter += new_value;
+ return;
+ }
+
+ if (new_counter < *curr_counter)
+ *curr_value = new_counter + (ULONG_MAX - *curr_counter);
+ else
+ *curr_value = new_counter - *curr_counter;
+
+ *curr_counter = new_counter;
+ *group_counter += *curr_value;
+}
+
/* 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;
- for (ps = list_head_g; ps != NULL; ps = ps->next)
+ for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
{
+ _Bool want_init;
+
if ((ps_list_match (name, cmdline, ps)) == 0)
continue;
@@ -381,10 +410,9 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
{
procstat_entry_t *new;
- new = (procstat_entry_t *) malloc (sizeof (procstat_entry_t));
+ new = calloc (1, sizeof (*new));
if (new == NULL)
return;
- memset (new, 0, sizeof (procstat_entry_t));
new->id = entry->id;
if (pse == NULL)
@@ -407,6 +435,8 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
pse->io_wchar = entry->io_wchar;
pse->io_syscr = entry->io_syscr;
pse->io_syscw = entry->io_syscw;
+ pse->cswitch_vol = entry->cswitch_vol;
+ pse->cswitch_invol = entry->cswitch_invol;
ps->num_proc += pse->num_proc;
ps->num_lwp += pse->num_lwp;
@@ -421,90 +451,40 @@ static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t
ps->io_syscr += ((pse->io_syscr == -1)?0:pse->io_syscr);
ps->io_syscw += ((pse->io_syscw == -1)?0:pse->io_syscw);
- if ((entry->vmem_minflt_counter == 0)
- && (entry->vmem_majflt_counter == 0))
- {
- pse->vmem_minflt_counter += entry->vmem_minflt;
- pse->vmem_minflt = entry->vmem_minflt;
-
- pse->vmem_majflt_counter += entry->vmem_majflt;
- pse->vmem_majflt = entry->vmem_majflt;
- }
- else
- {
- 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;
- }
-
- 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;
-
- pse->cpu_system_counter += entry->cpu_system;
- pse->cpu_system = entry->cpu_system;
- }
- else
- {
- 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;
- }
-
- ps->cpu_user_counter += pse->cpu_user;
- ps->cpu_system_counter += pse->cpu_system;
+ ps->cswitch_vol += ((pse->cswitch_vol == -1)?0:pse->cswitch_vol);
+ ps->cswitch_invol += ((pse->cswitch_invol == -1)?0:pse->cswitch_invol);
+
+ want_init = (entry->vmem_minflt_counter == 0)
+ && (entry->vmem_majflt_counter == 0);
+ ps_update_counter (want_init,
+ &ps->vmem_minflt_counter,
+ &pse->vmem_minflt_counter, &pse->vmem_minflt,
+ entry->vmem_minflt_counter, entry->vmem_minflt);
+ ps_update_counter (want_init,
+ &ps->vmem_majflt_counter,
+ &pse->vmem_majflt_counter, &pse->vmem_majflt,
+ entry->vmem_majflt_counter, entry->vmem_majflt);
+
+ want_init = (entry->cpu_user_counter == 0)
+ && (entry->cpu_system_counter == 0);
+ ps_update_counter (want_init,
+ &ps->cpu_user_counter,
+ &pse->cpu_user_counter, &pse->cpu_user,
+ entry->cpu_user_counter, entry->cpu_user);
+ ps_update_counter (want_init,
+ &ps->cpu_system_counter,
+ &pse->cpu_system_counter, &pse->cpu_system,
+ entry->cpu_system_counter, entry->cpu_system);
}
}
/* remove old entries from instances of processes in list_head_g */
static void ps_list_reset (void)
{
- procstat_t *ps;
procstat_entry_t *pse;
procstat_entry_t *pse_prev;
- for (ps = list_head_g; ps != NULL; ps = ps->next)
+ for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
{
ps->num_proc = 0;
ps->num_lwp = 0;
ps->io_wchar = -1;
ps->io_syscr = -1;
ps->io_syscw = -1;
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
pse_prev = NULL;
pse = ps->instances;
/* put all pre-defined 'Process' names from config to list_head_g tree */
static int ps_config (oconfig_item_t *ci)
{
- int i;
-
#if KERNEL_LINUX
const size_t max_procname_len = 15;
#elif KERNEL_SOLARIS || KERNEL_FREEBSD
const size_t max_procname_len = MAXCOMLEN -1;
#endif
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
if (strcasecmp (c->key, "Process") == 0)
ps_list_register (c->values[0].value.string,
c->values[1].value.string);
}
+ else if (strcasecmp (c->key, "CollectContextSwitch") == 0)
+ {
+ cf_util_get_boolean (c, &report_ctx_switch);
+ }
else
{
ERROR ("processes plugin: The `%s' configuration option is not "
plugin_dispatch_values (&vl);
}
+ if ( report_ctx_switch )
+ {
+ sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "voluntary", sizeof (vl.type_instance));
+ vl.values[0].derive = ps->cswitch_vol;
+ vl.values_len = 1;
+ plugin_dispatch_values (&vl);
+
+ sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "involuntary", sizeof (vl.type_instance));
+ vl.values[0].derive = ps->cswitch_invol;
+ vl.values_len = 1;
+ plugin_dispatch_values (&vl);
+ }
+
DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
"vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
"vmem_code = %lu; "
"vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
"cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
"io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; "
- "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";",
+ "io_syscr = %"PRIi64"; io_syscw = %"PRIi64"; "
+ "cswitch_vol = %"PRIi64"; cswitch_invol = %"PRIi64";",
ps->name, ps->num_proc, ps->num_lwp,
ps->vmem_size, ps->vmem_rss,
ps->vmem_data, ps->vmem_code,
ps->vmem_minflt_counter, ps->vmem_majflt_counter,
ps->cpu_user_counter, ps->cpu_system_counter,
- ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw);
+ ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw,
+ ps->cswitch_vol, ps->cswitch_invol);
} /* void ps_submit_proc_list */
#if KERNEL_LINUX || KERNEL_SOLARIS
/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
#if KERNEL_LINUX
-static int ps_read_tasks (long pid)
+static procstat_t *ps_read_tasks_status (long pid, procstat_t *ps)
{
char dirname[64];
DIR *dh;
+ char filename[64];
+ FILE *fh;
struct dirent *ent;
- int count = 0;
+ derive_t cswitch_vol = 0;
+ derive_t cswitch_invol = 0;
+ char buffer[1024];
+ char *fields[8];
+ int numfields;
ssnprintf (dirname, sizeof (dirname), "/proc/%li/task", pid);
if ((dh = opendir (dirname)) == NULL)
{
DEBUG ("Failed to open directory `%s'", dirname);
- return (-1);
+ return (NULL);
}
while ((ent = readdir (dh)) != NULL)
{
+ char *tpid;
+
if (!isdigit ((int) ent->d_name[0]))
continue;
- else
- count++;
+
+ tpid = ent->d_name;
+
+ ssnprintf (filename, sizeof (filename), "/proc/%li/task/%s/status", pid, tpid);
+ if ((fh = fopen (filename, "r")) == NULL)
+ {
+ DEBUG ("Failed to open file `%s'", filename);
+ continue;
+ }
+
+ while (fgets (buffer, sizeof(buffer), fh) != NULL)
+ {
+ derive_t tmp;
+ char *endptr;
+
+ if (strncmp (buffer, "voluntary_ctxt_switches", 23) != 0
+ && strncmp (buffer, "nonvoluntary_ctxt_switches", 26) != 0)
+ continue;
+
+ numfields = strsplit (buffer, fields,
+ STATIC_ARRAY_SIZE (fields));
+
+ if (numfields < 2)
+ continue;
+
+ errno = 0;
+ endptr = NULL;
+ tmp = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10);
+ if ((errno == 0) && (endptr != fields[1]))
+ {
+ if (strncmp (buffer, "voluntary_ctxt_switches", 23) == 0)
+ {
+ cswitch_vol += tmp;
+ }
+ else if (strncmp (buffer, "nonvoluntary_ctxt_switches", 26) == 0)
+ {
+ cswitch_invol += tmp;
+ }
+ }
+ } /* while (fgets) */
+
+ if (fclose (fh))
+ {
+ char errbuf[1024];
+ WARNING ("processes: fclose: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
}
closedir (dh);
- return ((count >= 1) ? count : 1);
-} /* int *ps_read_tasks */
+ ps->cswitch_vol = cswitch_vol;
+ ps->cswitch_invol = cswitch_invol;
-/* Read advanced virtual memory data from /proc/pid/status */
-static procstat_t *ps_read_vmem (long pid, procstat_t *ps)
+ return (ps);
+} /* int *ps_read_tasks_status */
+
+/* Read data from /proc/pid/status */
+static procstat_t *ps_read_status (long pid, procstat_t *ps)
{
FILE *fh;
char buffer[1024];
char filename[64];
- unsigned long long lib = 0;
- unsigned long long exe = 0;
- unsigned long long data = 0;
+ unsigned long lib = 0;
+ unsigned long exe = 0;
+ unsigned long data = 0;
+ unsigned long threads = 0;
char *fields[8];
int numfields;
while (fgets (buffer, sizeof(buffer), fh) != NULL)
{
- long long tmp;
+ unsigned long tmp;
char *endptr;
- if (strncmp (buffer, "Vm", 2) != 0)
+ if (strncmp (buffer, "Vm", 2) != 0
+ && strncmp (buffer, "Threads", 7) != 0)
continue;
numfields = strsplit (buffer, fields,
errno = 0;
endptr = NULL;
- tmp = strtoll (fields[1], &endptr, /* base = */ 10);
+ tmp = strtoul (fields[1], &endptr, /* base = */ 10);
if ((errno == 0) && (endptr != fields[1]))
{
if (strncmp (buffer, "VmData", 6) == 0)
{
exe = tmp;
}
+ else if (strncmp(buffer, "Threads", 7) == 0)
+ {
+ threads = tmp;
+ }
}
} /* while (fgets) */
ps->vmem_data = data * 1024;
ps->vmem_code = (exe + lib) * 1024;
+ if (threads != 0)
+ ps->num_lwp = threads;
return (ps);
} /* procstat_t *ps_read_vmem */
char *fields[64];
char fields_len;
- int buffer_len;
+ size_t buffer_len;
- char *buffer_ptr;
+ char *buffer_ptr;
size_t name_start_pos;
size_t name_end_pos;
size_t name_len;
long long unsigned vmem_rss;
long long unsigned stack_size;
+ ssize_t status;
+
memset (ps, 0, sizeof (procstat_t));
ssnprintf (filename, sizeof (filename), "/proc/%li/stat", pid);
- buffer_len = read_file_contents (filename,
- buffer, sizeof(buffer) - 1);
- if (buffer_len <= 0)
+ status = read_file_contents (filename, buffer, sizeof(buffer) - 1);
+ if (status <= 0)
return (-1);
+ buffer_len = (size_t) status;
buffer[buffer_len] = 0;
/* The name of the process is enclosed in parens. Since the name can
* strchr(3) and strrchr(3) to avoid pointer arithmetic which would
* otherwise be required to determine name_len. */
name_start_pos = 0;
- while ((buffer[name_start_pos] != '(')
- && (name_start_pos < buffer_len))
+ while (name_start_pos < buffer_len && buffer[name_start_pos] != '(')
name_start_pos++;
name_end_pos = buffer_len;
- while ((buffer[name_end_pos] != ')')
- && (name_end_pos > 0))
+ while (name_end_pos > 0 && buffer[name_end_pos] != ')')
name_end_pos--;
/* Either '(' or ')' is not found or they are in the wrong order.
}
else
{
- if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 )
+ ps->num_lwp = strtoul (fields[17], /* endptr = */ NULL, /* base = */ 10);
+ if ((ps_read_status(pid, ps)) == NULL)
{
- /* returns -1 => kernel 2.4 */
- ps->num_lwp = 1;
+ /* No VMem data */
+ ps->vmem_data = -1;
+ ps->vmem_code = -1;
+ DEBUG("ps_read_process: did not get vmem data for pid %li", pid);
}
+ if (ps->num_lwp == 0)
+ ps->num_lwp = 1;
ps->num_proc = 1;
}
cpu_system_counter = cpu_system_counter * 1000000 / CONFIG_HZ;
vmem_rss = vmem_rss * pagesize_g;
- if ( (ps_read_vmem(pid, ps)) == NULL)
- {
- /* No VMem data */
- ps->vmem_data = -1;
- ps->vmem_code = -1;
- DEBUG("ps_read_process: did not get vmem data for pid %li", pid);
- }
-
ps->cpu_user_counter = cpu_user_counter;
ps->cpu_system_counter = cpu_system_counter;
ps->vmem_size = (unsigned long) vmem_size;
DEBUG("ps_read_process: not get io data for pid %li", pid);
}
+ if ( report_ctx_switch )
+ {
+ if ( (ps_read_tasks_status(pid, ps)) == NULL)
+ {
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
+
+ DEBUG("ps_read_tasks_status: not get context "
+ "switch data for pid %li", pid);
+ }
+ }
+
/* success */
return (0);
} /* int ps_read_process (...) */
buf_ptr += status;
len -= status;
- if (len <= 0)
+ if (len == 0)
break;
}
@@ -1242,16 +1316,16 @@ static char *ps_get_cmdline (long pid, char *name __attribute__((unused)), /* {{
{
char path[PATH_MAX];
psinfo_t info;
- int status;
+ ssize_t status;
snprintf(path, sizeof (path), "/proc/%li/psinfo", pid);
status = read_file_contents (path, (void *) &info, sizeof (info));
- if (status != sizeof (info))
+ if ((status < 0) || (((size_t) status) != sizeof (info)))
{
ERROR ("processes plugin: Unexpected return value "
"while reading \"%s\": "
- "Returned %i but expected %zu.",
+ "Returned %zd but expected %zu.",
path, status, buffer_size);
return (NULL);
}
snprintf(f_usage, sizeof (f_usage), "/proc/%li/usage", pid);
- buffer = malloc(sizeof (pstatus_t));
- memset(buffer, 0, sizeof (pstatus_t));
+ buffer = calloc(1, sizeof (pstatus_t));
read_file_contents(filename, buffer, sizeof (pstatus_t));
myStatus = (pstatus_t *) buffer;
- buffer = malloc(sizeof (psinfo_t));
- memset(buffer, 0, sizeof(psinfo_t));
+ buffer = calloc(1, sizeof (psinfo_t));
read_file_contents(f_psinfo, buffer, sizeof (psinfo_t));
myInfo = (psinfo_t *) buffer;
- buffer = malloc(sizeof (prusage_t));
- memset(buffer, 0, sizeof(prusage_t));
+ buffer = calloc(1, sizeof (prusage_t));
read_file_contents(f_usage, buffer, sizeof (prusage_t));
myUsage = (prusage_t *) buffer;
ps->io_syscr = myUsage->pr_sysc;
ps->io_syscw = myUsage->pr_sysc;
+ /*
+ * TODO: context switch counters for Solaris
+ */
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
+
/*
* TODO: Find way of setting BLOCKED and PAGING status
* are retrieved from kstat (module cpu, name sys, class misc, stat nthreads).
* The result is the sum for all the threads created on each cpu
*/
-static int read_fork_rate()
+static int read_fork_rate (void)
{
extern kstat_ctl_t *kc;
- kstat_t *ksp_chain = NULL;
derive_t result = 0;
if (kc == NULL)
return (-1);
- for (ksp_chain = kc->kc_chain;
+ for (kstat_t *ksp_chain = kc->kc_chain;
ksp_chain != NULL;
ksp_chain = ksp_chain->ks_next)
{
#if HAVE_THREAD_INFO
kern_return_t status;
- int pset;
processor_set_t port_pset_priv;
- int task;
task_array_t task_list;
mach_msg_type_number_t task_list_len;
int task_pid;
char task_name[MAXCOMLEN + 1];
- int thread;
thread_act_array_t thread_list;
mach_msg_type_number_t thread_list_len;
thread_basic_info_data_t thread_data;
* Tasks are assigned to sets of processors, so that's where you go to
* get a list.
*/
- for (pset = 0; pset < pset_list_len; pset++)
+ for (mach_msg_type_number_t pset = 0; pset < pset_list_len; pset++)
{
if ((status = host_processor_set_priv (port_host_self,
pset_list[pset],
continue;
}
- for (task = 0; task < task_list_len; task++)
+ for (mach_msg_type_number_t task = 0; task < task_list_len; task++)
{
ps = NULL;
if (mach_get_task_name (task_list[task],
pse.cpu_user_counter = task_absolutetime_info.total_user;
pse.cpu_system_counter = task_absolutetime_info.total_system;
+
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
}
status = task_threads (task_list[task], &thread_list,
continue; /* with next task_list */
}
- for (thread = 0; thread < thread_list_len; thread++)
+ for (mach_msg_type_number_t thread = 0; thread < thread_list_len; thread++)
{
thread_data_len = THREAD_BASIC_INFO_COUNT;
status = thread_info (thread_list[thread],
procstat_entry_t pse;
char state;
- procstat_t *ps_ptr;
-
running = sleeping = zombies = stopped = paging = blocked = 0;
ps_list_reset ();
pse.io_syscr = ps.io_syscr;
pse.io_syscw = ps.io_syscw;
+ pse.cswitch_vol = ps.cswitch_vol;
+ pse.cswitch_invol = ps.cswitch_invol;
+
switch (state)
{
case 'R': running++; break;
ps_submit_state ("paging", paging);
ps_submit_state ("blocked", blocked);
- for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
read_fork_rate();
struct kinfo_proc *procs; /* array of processes */
struct kinfo_proc *proc_ptr = NULL;
int count; /* returns number of processes */
- int i;
- procstat_t *ps_ptr;
procstat_entry_t pse;
ps_list_reset ();
}
/* Iterate through the processes in kinfo_proc */
- for (i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
{
/* Create only one process list entry per _process_, i.e.
* filter out threads (duplicate PID entries). */
pse.io_syscr = -1;
pse.io_syscw = -1;
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
ps_list_add (procs[i].ki_comm, have_cmdline ? cmdline : NULL, &pse);
switch (procs[i].ki_stat)
ps_submit_state ("idle", idle);
ps_submit_state ("wait", wait);
- for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
struct kinfo_proc *procs; /* array of processes */
struct kinfo_proc *proc_ptr = NULL;
int count; /* returns number of processes */
- int i;
- procstat_t *ps_ptr;
procstat_entry_t pse;
ps_list_reset ();
}
/* Iterate through the processes in kinfo_proc */
- for (i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
{
/* Create only one process list entry per _process_, i.e.
* filter out threads (duplicate PID entries). */
pse.io_syscr = -1;
pse.io_syscw = -1;
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
ps_list_add (procs[i].p_comm, have_cmdline ? cmdline : NULL, &pse);
switch (procs[i].p_stat)
ps_submit_state ("idle", idle);
ps_submit_state ("dead", dead);
- for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD */
pid_t pindex = 0;
int nprocs;
- procstat_t *ps;
procstat_entry_t pse;
ps_list_reset ();
/* fdsinfo = */ NULL, sizeof(struct fdsinfo64),
&pindex, MAXPROCENTRY)) > 0)
{
- int i;
-
- for (i = 0; i < nprocs; i++)
+ for (int i = 0; i < nprocs; i++)
{
tid64_t thindex;
int nthreads;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
ps_list_add (cmdline, cargs, &pse);
} /* for (i = 0 .. nprocs) */
ps_submit_state ("paging", paging);
ps_submit_state ("blocked", blocked);
- for (ps = list_head_g; ps != NULL; ps = ps->next)
+ for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next)
ps_submit_proc_list (ps);
/* #endif HAVE_PROCINFO_H */
DIR *proc;
int status;
- procstat_t *ps_ptr;
char state;
char cmdline[PRARGSZ];
pse.io_syscr = ps.io_syscr;
pse.io_syscw = ps.io_syscw;
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
switch (state)
{
case 'R': running++; break;
ps_submit_state ("system", system);
ps_submit_state ("orphan", orphan);
- for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+ for (procstat_t *ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
read_fork_rate();
diff --git a/src/protocols.c b/src/protocols.c
index 1a39aad3ef93c4eeecfb1b00ba22487869232751..208da8b20f41b9c89e6342c4d7bac71bc81dcfb5 100644 (file)
--- a/src/protocols.c
+++ b/src/protocols.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_ignorelist.h"
static ignorelist_t *values_list = NULL;
-/*
+/*
* Functions
*/
static void submit (const char *protocol_name,
diff --git a/src/pyconfig.c b/src/pyconfig.c
index b5c01aaf1d5481256bf872e6d078c6e4b74dc15c..83748b4fa45f9cee15e4dffd7f7b2ded66d0f729 100644 (file)
--- a/src/pyconfig.c
+++ b/src/pyconfig.c
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Sven Trenkel <collectd at semidefinite.de>
+ * Sven Trenkel <collectd at semidefinite.de>
**/
#include <Python.h>
#include <structmember.h>
#include "collectd.h"
+
#include "common.h"
#include "cpython.h"
@@ -57,11 +58,11 @@ static char children_doc[] = "This is a tuple of child nodes. For most nodes thi
static PyObject *Config_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
Config *self;
-
+
self = (Config *) type->tp_alloc(type, 0);
if (self == NULL)
return NULL;
-
+
self->parent = NULL;
self->key = NULL;
self->values = NULL;
PyObject *key = NULL, *parent = NULL, *values = NULL, *children = NULL, *tmp;
Config *self = (Config *) s;
static char *kwlist[] = {"key", "parent", "values", "children", NULL};
-
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist,
&key, &parent, &values, &children))
return -1;
-
+
if (!IS_BYTES_OR_UNICODE(key)) {
PyErr_SetString(PyExc_TypeError, "argument 1 must be str");
Py_XDECREF(parent);
Config *self = (Config *) s;
PyObject *ret = NULL;
static PyObject *node_prefix = NULL, *root_prefix = NULL, *ending = NULL;
-
+
/* This is ok because we have the GIL, so this is thread-save by default. */
if (node_prefix == NULL)
node_prefix = cpy_string_to_unicode_or_bytes("<collectd.Config node ");
ending = cpy_string_to_unicode_or_bytes(">");
if (node_prefix == NULL || root_prefix == NULL || ending == NULL)
return NULL;
-
+
ret = PyObject_Str(self->key);
CPY_SUBSTITUTE(PyObject_Repr, ret, ret);
if (self->parent == NULL || self->parent == Py_None)
else
CPY_STRCAT(&ret, node_prefix);
CPY_STRCAT(&ret, ending);
-
+
return ret;
}
diff --git a/src/python.c b/src/python.c
index c7524143424aecbb87fa3c037eabb9f8fee5016a..ec2317b3721d00149e68fdc1567f59340da2cf99 100644 (file)
--- a/src/python.c
+++ b/src/python.c
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Sven Trenkel <collectd at semidefinite.de>
+ * Sven Trenkel <collectd at semidefinite.de>
**/
#include <Python.h>
#include <structmember.h>
#include <signal.h>
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
#include "collectd.h"
+
#include "common.h"
#include "cpython.h"
@@ -199,7 +197,7 @@ static char reg_flush_doc[] = "register_flush(callback[, data][, name]) -> ident
"The callback function will be called with two or three parameters:\n"
"timeout: Indicates that only data older than 'timeout' seconds is to\n"
" be flushed.\n"
- "id: Specifies which values are to be flushed.\n"
+ "id: Specifies which values are to be flushed. Might be None.\n"
"data: The optional data parameter passed to the register function.\n"
" If the parameter was omitted it will be omitted here, too.";
@@ -221,7 +219,9 @@ static char reg_shutdown_doc[] = "register_shutdown(callback[, data][, name]) ->
" data if it was supplied.";
-static int do_interactive = 0;
+static pthread_t main_thread;
+static PyOS_sighandler_t python_sigint_handler;
+static _Bool do_interactive = 0;
/* This is our global thread state. Python saves some stuff in thread-local
* storage. So if we allow the interpreter to run in the background
static cpy_callback_t *cpy_init_callbacks;
static cpy_callback_t *cpy_shutdown_callbacks;
+/* Make sure to hold the GIL while modifying these. */
+static int cpy_shutdown_triggered = 0;
+static int cpy_num_callbacks = 0;
+
static void cpy_destroy_user_data(void *data) {
cpy_callback_t *c = data;
free(c->name);
+ CPY_LOCK_THREADS
Py_DECREF(c->callback);
Py_XDECREF(c->data);
free(c);
+ --cpy_num_callbacks;
+ if (!cpy_num_callbacks && cpy_shutdown_triggered) {
+ Py_Finalize();
+ return;
+ }
+ CPY_RELEASE_THREADS
}
/* You must hold the GIL to call this function!
static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) {
const char *module = NULL;
PyObject *mod = NULL;
-
+
if (name != NULL) {
snprintf(buf, size, "python.%s", name);
return;
}
-
+
mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
if (mod != NULL)
module = cpy_unicode_or_bytes_to_string(&mod);
-
+
if (module != NULL) {
snprintf(buf, size, "python.%s", module);
Py_XDECREF(mod);
@@ -267,16 +278,16 @@ static void cpy_build_name(char *buf, size_t size, PyObject *callback, const cha
return;
}
Py_XDECREF(mod);
-
+
snprintf(buf, size, "python.%p", callback);
PyErr_Clear();
}
void cpy_log_exception(const char *context) {
- int l = 0, i;
+ int l = 0;
const char *typename = NULL, *message = NULL;
PyObject *type, *value, *traceback, *tn, *m, *list;
-
+
PyErr_Fetch(&type, &value, &traceback);
PyErr_NormalizeException(&type, &value, &traceback);
if (type == NULL) return;
if (list)
l = PyObject_Length(list);
- for (i = 0; i < l; ++i) {
+ for (int i = 0; i < l; ++i) {
PyObject *line;
char const *msg;
char *cpy;
}
static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
- int i;
cpy_callback_t *c = data->data;
PyObject *ret, *list, *temp, *dict = NULL;
Values *v;
@@ -366,24 +376,15 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
cpy_log_exception("write callback");
CPY_RETURN_FROM_THREADS 0;
}
- for (i = 0; i < value_list->values_len; ++i) {
+ for (size_t i = 0; i < value_list->values_len; ++i) {
if (ds->ds[i].type == DS_TYPE_COUNTER) {
- if ((long) value_list->values[i].counter == value_list->values[i].counter)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
- else
- PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
+ PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
} else if (ds->ds[i].type == DS_TYPE_GAUGE) {
PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
} else if (ds->ds[i].type == DS_TYPE_DERIVE) {
- if ((long) value_list->values[i].derive == value_list->values[i].derive)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
- else
- PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
+ PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
} else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
- if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
- PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
- else
- PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
+ PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
} else {
Py_BEGIN_ALLOW_THREADS
ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
@@ -399,19 +400,18 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
}
dict = PyDict_New(); /* New reference. */
if (value_list->meta) {
- int num;
char **table;
meta_data_t *meta = value_list->meta;
- num = meta_data_toc(meta, &table);
- for (i = 0; i < num; ++i) {
+ int num = meta_data_toc(meta, &table);
+ for (int i = 0; i < num; ++i) {
int type;
char *string;
int64_t si;
uint64_t ui;
double d;
_Bool b;
-
+
type = meta_data_type(meta, table[i]);
if (type == MD_TYPE_STRING) {
if (meta_data_get_string(meta, table[i], &string))
@@ -529,7 +529,12 @@ static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
PyObject *ret, *text;
CPY_LOCK_THREADS
- text = cpy_string_to_unicode_or_bytes(id);
+ if (id) {
+ text = cpy_string_to_unicode_or_bytes(id);
+ } else {
+ text = Py_None;
+ Py_INCREF(text);
+ }
if (c->data == NULL)
ret = PyObject_CallFunction(c->callback, "iN", timeout, text); /* New reference. */
else
@@ -549,7 +554,7 @@ static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args
char *name = NULL;
PyObject *callback = NULL, *data = NULL, *mod = NULL;
static char *kwlist[] = {"callback", "data", "name", NULL};
-
+
if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
if (PyCallable_Check(callback) == 0) {
PyMem_Free(name);
@@ -561,15 +566,15 @@ static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args
Py_INCREF(callback);
Py_XINCREF(data);
- c = malloc(sizeof(*c));
+ c = calloc(1, sizeof(*c));
if (c == NULL)
return NULL;
- memset (c, 0, sizeof (*c));
c->name = strdup(buf);
c->callback = callback;
c->data = data;
c->next = *list_head;
+ ++cpy_num_callbacks;
*list_head = c;
Py_XDECREF(mod);
PyMem_Free(name);
}
static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
- int i;
char *name;
const data_set_t *ds;
PyObject *list, *tuple;
return NULL;
}
list = PyList_New(ds->ds_num); /* New reference. */
- for (i = 0; i < ds->ds_num; ++i) {
+ for (size_t i = 0; i < ds->ds_num; ++i) {
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
int timeout = -1;
char *plugin = NULL, *identifier = NULL;
static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
-
+
if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
Py_BEGIN_ALLOW_THREADS
plugin_flush(plugin, timeout, identifier);
@@ -636,11 +640,10 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObjec
char buf[512];
reg_function_t *register_function = (reg_function_t *) reg;
cpy_callback_t *c = NULL;
- user_data_t user_data;
char *name = NULL;
PyObject *callback = NULL, *data = NULL;
static char *kwlist[] = {"callback", "data", "name", NULL};
-
+
if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
if (PyCallable_Check(callback) == 0) {
PyMem_Free(name);
@@ -649,38 +652,37 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObjec
}
cpy_build_name(buf, sizeof(buf), callback, name);
PyMem_Free(name);
-
+
Py_INCREF(callback);
Py_XINCREF(data);
- c = malloc(sizeof(*c));
+ c = calloc(1, sizeof(*c));
if (c == NULL)
return NULL;
- memset (c, 0, sizeof (*c));
c->name = strdup(buf);
c->callback = callback;
c->data = data;
c->next = NULL;
- memset (&user_data, 0, sizeof (user_data));
- user_data.free_func = cpy_destroy_user_data;
- user_data.data = c;
+ user_data_t user_data = {
+ .data = c,
+ .free_func = cpy_destroy_user_data
+ };
register_function(buf, handler, &user_data);
+ ++cpy_num_callbacks;
return cpy_string_to_unicode_or_bytes(buf);
}
static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
char buf[512];
cpy_callback_t *c = NULL;
- user_data_t user_data;
double interval = 0;
char *name = NULL;
PyObject *callback = NULL, *data = NULL;
- struct timespec ts;
static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
-
+
if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
if (PyCallable_Check(callback) == 0) {
PyMem_Free(name);
@@ -689,29 +691,27 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd
}
cpy_build_name(buf, sizeof(buf), callback, name);
PyMem_Free(name);
-
+
Py_INCREF(callback);
Py_XINCREF(data);
- c = malloc(sizeof(*c));
+ c = calloc(1, sizeof(*c));
if (c == NULL)
return NULL;
- memset (c, 0, sizeof (*c));
c->name = strdup(buf);
c->callback = callback;
c->data = data;
c->next = NULL;
- memset (&user_data, 0, sizeof (user_data));
- user_data.free_func = cpy_destroy_user_data;
- user_data.data = c;
+ user_data_t user_data = {
+ .data = c,
+ .free_func = cpy_destroy_user_data
+ };
- ts.tv_sec = interval;
- ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
plugin_register_complex_read(/* group = */ "python", buf,
- cpy_read_callback, &ts, &user_data);
-
+ cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
+ ++cpy_num_callbacks;
return cpy_string_to_unicode_or_bytes(buf);
}
@@ -817,8 +817,8 @@ static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *ar
PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
return NULL;
}
- /* Yes, this is actually save. To call this function the caller has to
- * hold the GIL. Well, save as long as there is only one GIL anyway ... */
+ /* Yes, this is actually safe. To call this function the caller has to
+ * hold the GIL. Well, safe as long as there is only one GIL anyway ... */
if (prev == NULL)
*list_head = tmp->next;
else
@@ -827,6 +827,15 @@ static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *ar
Py_RETURN_NONE;
}
+static void cpy_unregister_list(cpy_callback_t **list_head) {
+ cpy_callback_t *cur, *next;
+ for (cur = *list_head; cur; cur = next) {
+ next = cur->next;
+ cpy_destroy_user_data(cur);
+ }
+ *list_head = NULL;
+}
+
typedef int cpy_unregister_function_t(const char *name);
static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
};
static int cpy_shutdown(void) {
- cpy_callback_t *c;
PyObject *ret;
-
- /* This can happen if the module was loaded but not configured. */
- if (state != NULL)
- PyEval_RestoreThread(state);
- for (c = cpy_shutdown_callbacks; c; c = c->next) {
+ if (!state) {
+ printf("================================================================\n");
+ printf("collectd shutdown while running an interactive session. This will\n");
+ printf("probably leave your terminal in a mess.\n");
+ printf("Run the command \"reset\" to get it back into a usable state.\n");
+ printf("You can press Ctrl+D in the interactive session to\n");
+ printf("close collectd and avoid this problem in the future.\n");
+ printf("================================================================\n");
+ }
+
+ CPY_LOCK_THREADS
+
+ for (cpy_callback_t *c = cpy_shutdown_callbacks; c; c = c->next) {
ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
if (ret == NULL)
cpy_log_exception("shutdown callback");
Py_DECREF(ret);
}
PyErr_Print();
- Py_Finalize();
+
+ Py_BEGIN_ALLOW_THREADS
+ cpy_unregister_list(&cpy_config_callbacks);
+ cpy_unregister_list(&cpy_init_callbacks);
+ cpy_unregister_list(&cpy_shutdown_callbacks);
+ cpy_shutdown_triggered = 1;
+ Py_END_ALLOW_THREADS
+
+ if (!cpy_num_callbacks) {
+ Py_Finalize();
+ return 0;
+ }
+
+ CPY_RELEASE_THREADS
return 0;
}
-static void cpy_int_handler(int sig) {
- return;
-}
+static void *cpy_interactive(void *pipefd) {
+ PyOS_sighandler_t cur_sig;
-static void *cpy_interactive(void *data) {
- sigset_t sigset;
- struct sigaction sig_int_action, old;
-
/* Signal handler in a plugin? Bad stuff, but the best way to
* handle it I guess. In an interactive session people will
* press Ctrl+C at some time, which will generate a SIGINT.
* This will cause collectd to shutdown, thus killing the
* interactive interpreter, and leaving the terminal in a
* mess. Chances are, this isn't what the user wanted to do.
- *
+ *
* So this is the plan:
- * 1. Block SIGINT in the main thread.
- * 2. Install our own signal handler that does nothing.
- * 3. Unblock SIGINT in the interactive thread.
+ * 1. Restore Python's own signal handler
+ * 2. Tell Python we just forked so it will accept this thread
+ * as the main one. No version of Python will ever handle
+ * interrupts anywhere but in the main thread.
+ * 3. After the interactive loop is done, restore collectd's
+ * SIGINT handler.
+ * 4. Raise SIGINT for a clean shutdown. The signal is sent to
+ * the main thread to ensure it wakes up the main interval
+ * sleep so that collectd shuts down immediately not in 10
+ * seconds.
*
* This will make sure that SIGINT won't kill collectd but
- * still interrupt syscalls like sleep and pause.
- * It does not raise a KeyboardInterrupt exception because so
- * far nobody managed to figure out how to do that. */
- memset (&sig_int_action, '\0', sizeof (sig_int_action));
- sig_int_action.sa_handler = cpy_int_handler;
- sigaction (SIGINT, &sig_int_action, &old);
-
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGINT);
- pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
- PyEval_AcquireThread(state);
+ * still interrupt syscalls like sleep and pause. */
+
if (PyImport_ImportModule("readline") == NULL) {
/* This interactive session will suck. */
cpy_log_exception("interactive session init");
}
+ cur_sig = PyOS_setsig(SIGINT, python_sigint_handler);
+ PyOS_AfterFork();
+ PyEval_InitThreads();
+ close(*(int *) pipefd);
PyRun_InteractiveLoop(stdin, "<stdin>");
+ PyOS_setsig(SIGINT, cur_sig);
PyErr_Print();
- PyEval_ReleaseThread(state);
+ state = PyEval_SaveThread();
NOTICE("python: Interactive interpreter exited, stopping collectd ...");
- /* Restore the original collectd SIGINT handler and raise SIGINT.
- * The main thread still has SIGINT blocked and there's nothing we
- * can do about that so this thread will handle it. But that's not
- * important, except that it won't interrupt the main loop and so
- * it might take a few seconds before collectd really shuts down. */
- sigaction (SIGINT, &old, NULL);
- raise(SIGINT);
- pause();
+ pthread_kill(main_thread, SIGINT);
return NULL;
}
static int cpy_init(void) {
- cpy_callback_t *c;
PyObject *ret;
+ int pipefd[2];
+ char buf;
static pthread_t thread;
- sigset_t sigset;
-
+
if (!Py_IsInitialized()) {
WARNING("python: Plugin loaded but not configured.");
plugin_unregister_shutdown("python");
+ Py_Finalize();
return 0;
}
- PyEval_InitThreads();
- /* Now it's finally OK to use python threads. */
- for (c = cpy_init_callbacks; c; c = c->next) {
+ main_thread = pthread_self();
+ if (do_interactive) {
+ if (pipe(pipefd)) {
+ ERROR("python: Unable to create pipe.");
+ return 1;
+ }
+ if (plugin_thread_create(&thread, NULL, cpy_interactive, pipefd + 1)) {
+ ERROR("python: Error creating thread for interactive interpreter.");
+ }
+ if(read(pipefd[0], &buf, 1))
+ ;
+ (void)close(pipefd[0]);
+ } else {
+ PyEval_InitThreads();
+ state = PyEval_SaveThread();
+ }
+ CPY_LOCK_THREADS
+ for (cpy_callback_t *c = cpy_init_callbacks; c; c = c->next) {
ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
if (ret == NULL)
cpy_log_exception("init callback");
else
Py_DECREF(ret);
}
- sigemptyset(&sigset);
- sigaddset(&sigset, SIGINT);
- pthread_sigmask(SIG_BLOCK, &sigset, NULL);
- state = PyEval_SaveThread();
- if (do_interactive) {
- if (plugin_thread_create(&thread, NULL, cpy_interactive, NULL)) {
- ERROR("python: Error creating thread for interactive interpreter.");
- }
- }
+ CPY_RELEASE_THREADS
return 0;
}
static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
- int i;
PyObject *item, *values, *children, *tmp;
-
+
if (parent == NULL)
parent = Py_None;
-
+
values = PyTuple_New(ci->values_num); /* New reference. */
- for (i = 0; i < ci->values_num; ++i) {
+ for (int i = 0; i < ci->values_num; ++i) {
if (ci->values[i].type == OCONFIG_TYPE_STRING) {
PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
} else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
@@ -1034,13 +1061,13 @@ static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
}
}
-
+
tmp = cpy_string_to_unicode_or_bytes(ci->key);
item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
if (item == NULL)
return NULL;
children = PyTuple_New(ci->children_num); /* New reference. */
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
}
tmp = ((Config *) item)->children;
#endif
static int cpy_init_python(void) {
+ PyOS_sighandler_t cur_sig;
PyObject *sys;
PyObject *module;
#else
char *argv = "";
#endif
-
+
+ /* Chances are the current signal handler is already SIG_DFL, but let's make sure. */
+ cur_sig = PyOS_setsig(SIGINT, SIG_DFL);
Py_Initialize();
-
+ python_sigint_handler = PyOS_setsig(SIGINT, cur_sig);
+
PyType_Ready(&ConfigType);
PyType_Ready(&PluginDataType);
ValuesType.tp_base = &PluginDataType;
}
static int cpy_config(oconfig_item_t *ci) {
- int i;
PyObject *tb;
+ int status = 0;
/* Ok in theory we shouldn't do initialization at this point
* but we have to. In order to give python scripts a chance
if (!Py_IsInitialized() && cpy_init_python()) return 1;
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *item = ci->children + i;
-
+
if (strcasecmp(item->key, "Interactive") == 0) {
- if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
+ if (cf_util_get_boolean(item, &do_interactive) != 0) {
+ status = 1;
continue;
- do_interactive = item->values[0].value.boolean;
+ }
} else if (strcasecmp(item->key, "Encoding") == 0) {
- if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
+ char *encoding = NULL;
+ if (cf_util_get_string(item, &encoding) != 0) {
+ status = 1;
continue;
+ }
#ifdef IS_PY3K
- NOTICE("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings. Ignoring this.");
+ ERROR("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings");
+ status = 1;
+ sfree(encoding);
+ continue;
#else
/* Why is this even necessary? And undocumented? */
- if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
+ if (PyUnicode_SetDefaultEncoding(encoding)) {
cpy_log_exception("setting default encoding");
+ status = 1;
+ }
#endif
+ sfree(encoding);
} else if (strcasecmp(item->key, "LogTraces") == 0) {
- if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
+ _Bool log_traces;
+ if (cf_util_get_boolean(item, &log_traces) != 0) {
+ status = 1;
continue;
- if (!item->values[0].value.boolean) {
+ }
+ if (!log_traces) {
Py_XDECREF(cpy_format_exception);
cpy_format_exception = NULL;
continue;
tb = PyImport_ImportModule("traceback"); /* New reference. */
if (tb == NULL) {
cpy_log_exception("python initialization");
+ status = 1;
continue;
}
cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
Py_DECREF(tb);
- if (cpy_format_exception == NULL)
+ if (cpy_format_exception == NULL) {
cpy_log_exception("python initialization");
+ status = 1;
+ }
} else if (strcasecmp(item->key, "ModulePath") == 0) {
char *dir = NULL;
PyObject *dir_object;
-
- if (cf_util_get_string(item, &dir) != 0)
+
+ if (cf_util_get_string(item, &dir) != 0) {
+ status = 1;
continue;
+ }
dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
if (dir_object == NULL) {
ERROR("python plugin: Unable to convert \"%s\" to "
"a python object.", dir);
free(dir);
cpy_log_exception("python initialization");
+ status = 1;
continue;
}
if (PyList_Insert(sys_path, 0, dir_object) != 0) {
ERROR("python plugin: Unable to prepend \"%s\" to "
"python module path.", dir);
cpy_log_exception("python initialization");
+ status = 1;
}
Py_DECREF(dir_object);
free(dir);
} else if (strcasecmp(item->key, "Import") == 0) {
char *module_name = NULL;
PyObject *module;
-
- if (cf_util_get_string(item, &module_name) != 0)
+
+ if (cf_util_get_string(item, &module_name) != 0) {
+ status = 1;
continue;
+ }
module = PyImport_ImportModule(module_name); /* New reference. */
if (module == NULL) {
ERROR("python plugin: Error importing module \"%s\".", module_name);
cpy_log_exception("importing module");
+ status = 1;
}
free(module_name);
Py_XDECREF(module);
char *name = NULL;
cpy_callback_t *c;
PyObject *ret;
-
- if (cf_util_get_string(item, &name) != 0)
+
+ if (cf_util_get_string(item, &name) != 0) {
+ status = 1;
continue;
+ }
for (c = cpy_config_callbacks; c; c = c->next) {
if (strcasecmp(c->name + 7, name) == 0)
break;
else
ret = PyObject_CallFunction(c->callback, "NO",
cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
- if (ret == NULL)
+ if (ret == NULL) {
cpy_log_exception("loading module");
- else
+ status = 1;
+ } else
Py_DECREF(ret);
} else {
- WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
+ ERROR("python plugin: Unknown config key \"%s\".", item->key);
+ status = 1;
}
}
- return 0;
+ return (status);
}
void module_register(void) {
diff --git a/src/pyvalues.c b/src/pyvalues.c
index 0ea81f8c986c6fcba479d85f3f0ec73ebed9f1aa..a7cb792357fcef570fe4f6d04902d26b4f17204e 100644 (file)
--- a/src/pyvalues.c
+++ b/src/pyvalues.c
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Sven Trenkel <collectd at semidefinite.de>
+ * Sven Trenkel <collectd at semidefinite.de>
**/
#include <Python.h>
#include <structmember.h>
#include "collectd.h"
+
#include "common.h"
#include "cpython.h"
static PyObject *l_type = NULL, *l_type_instance = NULL, *l_plugin = NULL, *l_plugin_instance = NULL;
static PyObject *l_host = NULL, *l_time = NULL;
PluginData *self = (PluginData *) s;
-
+
if (l_type == NULL)
l_type = cpy_string_to_unicode_or_bytes("(type=");
if (l_type_instance == NULL)
l_host = cpy_string_to_unicode_or_bytes(",host=");
if (l_time == NULL)
l_time = cpy_string_to_unicode_or_bytes(",time=");
-
+
if (!l_type || !l_type_instance || !l_plugin || !l_plugin_instance || !l_host || !l_time)
return NULL;
-
+
ret = cpy_string_to_unicode_or_bytes(s->ob_type->tp_name);
CPY_STRCAT(&ret, l_type);
return ret;
}
-static char time_doc[] = "This is the Unix timestap of the time this value was read.\n"
+static char time_doc[] = "This is the Unix timestamp of the time this value was read.\n"
"For dispatching values this can be set to 0 which means \"now\".\n"
"This means the time the value is actually dispatched, not the time\n"
"it was set to 0.";
static char host_doc[] = "The hostname of the host this value was read from.\n"
"For dispatching this can be set to an empty string which means\n"
- "the local hostname as defined in the collectd.conf.";
+ "the local hostname as defined in collectd.conf.";
static char type_doc[] = "The type of this value. This type has to be defined\n"
- "in your types.db. Attempting to set it to any other value will\n"
- "raise a TypeError exception.\n"
- "Assigning a type is mandetory, calling dispatch without doing\n"
+ "in the types.db file. Attempting to set it to any other value\n"
+ "will raise a TypeError exception.\n"
+ "Assigning a type is mandatory, calling dispatch without doing\n"
"so will raise a RuntimeError exception.";
static char type_instance_doc[] = "";
@@ -129,16 +130,16 @@ static char plugin_doc[] = "The name of the plugin that read the data. Setting t
static char plugin_instance_doc[] = "";
static char PluginData_doc[] = "This is an internal class that is the base for Values\n"
- "and Notification. It is pretty useless by itself and was therefore not\n"
+ "and Notification. It is pretty useless by itself and is therefore not\n"
"exported to the collectd module.";
static PyObject *PluginData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
PluginData *self;
-
+
self = (PluginData *) type->tp_alloc(type, 0);
if (self == NULL)
return NULL;
-
+
self->time = 0;
self->host[0] = 0;
self->plugin[0] = 0;
char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
static char *kwlist[] = {"type", "plugin_instance", "type_instance",
"plugin", "host", "time", NULL};
-
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetd", kwlist, NULL, &type,
NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin, NULL, &host, &time))
return -1;
-
+
if (type && plugin_get_ds(type) == NULL) {
PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
FreeAll();
static PyObject *PluginData_repr(PyObject *s) {
PyObject *ret;
static PyObject *l_closing = NULL;
-
+
if (l_closing == NULL)
l_closing = cpy_string_to_unicode_or_bytes(")");
-
+
if (l_closing == NULL)
return NULL;
-
+
ret = cpy_common_repr(s);
CPY_STRCAT(&ret, l_closing);
return ret;
static PyObject *PluginData_getstring(PyObject *self, void *data) {
const char *value = ((char *) self) + (intptr_t) data;
-
+
return cpy_string_to_unicode_or_bytes(value);
}
static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
char *old;
const char *new;
-
+
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
return -1;
static int PluginData_settype(PyObject *self, PyObject *value, void *data) {
char *old;
const char *new;
-
+
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
return -1;
@@ -312,8 +313,8 @@ static char interval_doc[] = "The interval is the timespan in seconds between tw
static char values_doc[] = "These are the actual values that get dispatched to collectd.\n"
"It has to be a sequence (a tuple or list) of numbers.\n"
"The size of the sequence and the type of its content depend on the type\n"
- "member your types.db file. For more information on this read the types.db\n"
- "man page.\n"
+ "member in the types.db file. For more information on this read the\n"
+ "types.db man page.\n"
"\n"
"If the sequence does not have the correct size upon dispatch a RuntimeError\n"
"exception will be raised. If the content of the sequence is not a number,\n"
@@ -322,7 +323,7 @@ static char values_doc[] = "These are the actual values that get dispatched to c
static char meta_doc[] = "These are the meta data for this Value object.\n"
"It has to be a dictionary of numbers, strings or bools. All keys must be\n"
"strings. int and long objects will be dispatched as signed integers unless\n"
- "they are between 2**63 and 2**64-1, which will result in a unsigned integer.\n"
+ "they are between 2**63 and 2**64-1, which will result in an unsigned integer.\n"
"You can force one of these storage classes by using the classes\n"
"collectd.Signed and collectd.Unsigned. A meta object received by a write\n"
"callback will always contain Signed or Unsigned objects.";
@@ -340,7 +341,7 @@ static char dispatch_doc[] = "dispatch([type][, values][, plugin_instance][, typ
static char write_doc[] = "write([destination][, type][, values][, plugin_instance][, type_instance]"
"[, plugin][, host][, time][, interval]) -> None. Dispatch a value list.\n"
"\n"
- "Write this instance to a single plugin or all plugins if 'destination' is obmitted.\n"
+ "Write this instance to a single plugin or all plugins if 'destination' is omitted.\n"
"This will bypass the main collectd process and all filtering and caching.\n"
"Other than that it works similar to 'dispatch'. In most cases 'dispatch' should be\n"
"used instead of 'write'.\n";
@@ -349,11 +350,11 @@ static char Values_doc[] = "A Values object used for dispatching values to colle
static PyObject *Values_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
Values *self;
-
+
self = (Values *) PluginData_new(type, args, kwds);
if (self == NULL)
return NULL;
-
+
self->values = PyList_New(0);
self->meta = PyDict_New();
self->interval = 0;
char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
"plugin", "host", "time", "interval", "meta", NULL};
-
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
NULL, &plugin, NULL, &host, &time, &interval, &meta))
return -1;
-
+
if (type && plugin_get_ds(type) == NULL) {
PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
FreeAll();
} else {
Py_INCREF(values);
}
-
+
if (meta == NULL) {
meta = PyDict_New();
PyErr_Clear();
} else {
Py_INCREF(meta);
}
-
+
tmp = self->values;
self->values = values;
Py_XDECREF(tmp);
-
+
tmp = self->meta;
self->meta = meta;
Py_XDECREF(tmp);
}
static meta_data_t *cpy_build_meta(PyObject *meta) {
- int i, s;
+ int s;
meta_data_t *m = NULL;
PyObject *l;
-
+
if ((meta == NULL) || (meta == Py_None))
return NULL;
}
m = meta_data_create();
- for (i = 0; i < s; ++i) {
+ for (int i = 0; i < s; ++i) {
const char *string, *keystring;
PyObject *key, *value, *item, *tmp;
-
+
item = PyList_GET_ITEM(l, i);
key = PyTuple_GET_ITEM(item, 0);
Py_INCREF(key);
}
static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
- int i, ret;
+ int ret;
const data_set_t *ds;
- int size;
+ size_t size;
value_t *value;
value_list_t value_list = VALUE_LIST_INIT;
PyObject *values = self->values, *meta = self->meta;
double time = self->data.time, interval = self->interval;
char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL;
-
+
static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
"plugin", "host", "time", "interval", "meta", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
@@ -542,15 +543,15 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
PyErr_Format(PyExc_TypeError, "meta must be a dict");
return NULL;
}
- size = (int) PySequence_Length(values);
+ size = (size_t) PySequence_Length(values);
if (size != ds->ds_num) {
- PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+ PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
return NULL;
}
- value = malloc(size * sizeof(*value));
- for (i = 0; i < size; ++i) {
+ value = calloc(size, sizeof(*value));
+ for (size_t i = 0; i < size; ++i) {
PyObject *item, *num;
- item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
+ item = PySequence_Fast_GET_ITEM(values, (int) i); /* Borrowed reference. */
switch (ds->ds[i].type) {
case DS_TYPE_COUNTER:
num = PyNumber_Long(item); /* New reference. */
@@ -616,15 +617,15 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
}
static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
- int i, ret;
+ int ret;
const data_set_t *ds;
- int size;
+ size_t size;
value_t *value;
value_list_t value_list = VALUE_LIST_INIT;
PyObject *values = self->values, *meta = self->meta;
double time = self->data.time, interval = self->interval;
char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL, *dest = NULL;
-
+
static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance",
"plugin", "host", "time", "interval", "meta", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|etOetetetetdiO", kwlist, NULL, &dest,
PyErr_Format(PyExc_TypeError, "values must be list or tuple");
return NULL;
}
- size = (int) PySequence_Length(values);
+ size = (size_t) PySequence_Length(values);
if (size != ds->ds_num) {
- PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+ PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu", value_list.type, ds->ds_num, size);
return NULL;
}
- value = malloc(size * sizeof(*value));
- for (i = 0; i < size; ++i) {
+ value = calloc(size, sizeof(*value));
+ for (size_t i = 0; i < size; ++i) {
PyObject *item, *num;
item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
switch (ds->ds[i].type) {
value_list.values_len = size;
value_list.time = DOUBLE_TO_CDTIME_T(time);
value_list.interval = DOUBLE_TO_CDTIME_T(interval);
- value_list.meta = cpy_build_meta(meta);;
+ value_list.meta = cpy_build_meta(meta);
if (value_list.host[0] == 0)
sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
if (value_list.plugin[0] == 0)
PyObject *ret, *tmp;
static PyObject *l_interval = NULL, *l_values = NULL, *l_meta = NULL, *l_closing = NULL;
Values *self = (Values *) s;
-
+
if (l_interval == NULL)
l_interval = cpy_string_to_unicode_or_bytes(",interval=");
if (l_values == NULL)
l_meta = cpy_string_to_unicode_or_bytes(",meta=");
if (l_closing == NULL)
l_closing = cpy_string_to_unicode_or_bytes(")");
-
+
if (l_interval == NULL || l_values == NULL || l_meta == NULL || l_closing == NULL)
return NULL;
-
+
ret = cpy_common_repr(s);
if (self->interval != 0) {
CPY_STRCAT(&ret, l_interval);
char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
"plugin", "host", "time", "severity", NULL};
-
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
NULL, &type, NULL, &message, NULL, &plugin_instance, NULL, &type_instance,
NULL, &plugin, NULL, &host, &time, &severity))
return -1;
-
+
if (type && plugin_get_ds(type) == NULL) {
PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
FreeAll();
@@ -889,7 +890,7 @@ static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObj
int severity = self->severity;
char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL;
char *message = NULL;
-
+
static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
"plugin", "host", "time", "severity", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
@@ -937,11 +938,11 @@ static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObj
static PyObject *Notification_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
Notification *self;
-
+
self = (Notification *) PluginData_new(type, args, kwds);
if (self == NULL)
return NULL;
-
+
self->message[0] = 0;
self->severity = 0;
return (PyObject *) self;
@@ -950,7 +951,7 @@ static PyObject *Notification_new(PyTypeObject *type, PyObject *args, PyObject *
static int Notification_setstring(PyObject *self, PyObject *value, void *data) {
char *old;
const char *new;
-
+
if (value == NULL) {
PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
return -1;
PyObject *ret, *tmp;
static PyObject *l_severity = NULL, *l_message = NULL, *l_closing = NULL;
Notification *self = (Notification *) s;
-
+
if (l_severity == NULL)
l_severity = cpy_string_to_unicode_or_bytes(",severity=");
if (l_message == NULL)
l_message = cpy_string_to_unicode_or_bytes(",message=");
if (l_closing == NULL)
l_closing = cpy_string_to_unicode_or_bytes(")");
-
+
if (l_severity == NULL || l_message == NULL || l_closing == NULL)
return NULL;
-
+
ret = cpy_common_repr(s);
if (self->severity != 0) {
CPY_STRCAT(&ret, l_severity);
diff --git a/src/redis.c b/src/redis.c
index 2586ca0c83325656c4ebfbee142cb5ddb9742768..5214eccc1e6efc39db7ae37579c6b7d6a5db897f 100644 (file)
--- a/src/redis.c
+++ b/src/redis.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
-#include <pthread.h>
#include <sys/time.h>
#include <hiredis/hiredis.h>
{
redis_query_t *rq;
int status;
- int i;
rq = calloc(1, sizeof(*rq));
if (rq == NULL) {
- ERROR("redis plugin: calloca failed adding redis_query.");
+ ERROR("redis plugin: calloc failed adding redis_query.");
return NULL;
}
status = cf_util_get_string_buffer(ci, rq->query, sizeof(rq->query));
(void)sstrncpy(rq->instance, rq->query, sizeof(rq->instance));
replace_special(rq->instance, sizeof(rq->instance));
- for (i = 0; i < ci->children_num; i++) {
+ for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *option = ci->children + i;
if (strcasecmp("Type", option->key) == 0) {
static int redis_config_node (oconfig_item_t *ci) /* {{{ */
{
- redis_node_t rn;
redis_query_t *rq;
- int i;
int status;
int timeout;
- memset (&rn, 0, sizeof (rn));
+ redis_node_t rn = {
+ .port = REDIS_DEF_PORT,
+ .timeout.tv_usec = REDIS_DEF_TIMEOUT
+ };
+
sstrncpy (rn.host, REDIS_DEF_HOST, sizeof (rn.host));
- rn.port = REDIS_DEF_PORT;
- rn.timeout.tv_usec = REDIS_DEF_TIMEOUT;
- rn.queries = NULL;
status = cf_util_get_string_buffer (ci, rn.name, sizeof (rn.name));
if (status != 0)
return (status);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
static int redis_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
@@ -304,7 +299,7 @@ static int redis_handle_info (char *node, char const *info_line, char const *typ
int i;
str += strlen (field_name) + 1; /* also skip the ':' */
- for(i=0;(*str && (isdigit(*str) || *str == '.'));i++,str++)
+ for(i=0;(*str && (isdigit((unsigned char)*str) || *str == '.'));i++,str++)
buf[i] = *str;
buf[i] ='\0';
@@ -380,10 +375,7 @@ static int redis_handle_query (redisContext *rh, redis_node_t *rn, redis_query_t
static int redis_read (void) /* {{{ */
{
- redis_node_t *rn;
- redis_query_t *rq;
-
- for (rn = nodes_head; rn != NULL; rn = rn->next)
+ for (redis_node_t *rn = nodes_head; rn != NULL; rn = rn->next)
{
redisContext *rh;
redisReply *rr;
redis_handle_info (rn->name, rr->str, "volatile_changes", NULL, "changes_since_last_save", DS_TYPE_GAUGE);
redis_handle_info (rn->name, rr->str, "total_connections", NULL, "total_connections_received", DS_TYPE_DERIVE);
redis_handle_info (rn->name, rr->str, "total_operations", NULL, "total_commands_processed", DS_TYPE_DERIVE);
+ redis_handle_info (rn->name, rr->str, "operations_per_second", NULL, "instantaneous_ops_per_sec", DS_TYPE_GAUGE);
redis_handle_info (rn->name, rr->str, "expired_keys", NULL, "expired_keys", DS_TYPE_DERIVE);
+ redis_handle_info (rn->name, rr->str, "evicted_keys", NULL, "evicted_keys", DS_TYPE_DERIVE);
redis_handle_info (rn->name, rr->str, "pubsub", "channels", "pubsub_channels", DS_TYPE_GAUGE);
redis_handle_info (rn->name, rr->str, "pubsub", "patterns", "pubsub_patterns", DS_TYPE_GAUGE);
redis_handle_info (rn->name, rr->str, "current_connections", "slaves", "connected_slaves", DS_TYPE_GAUGE);
+ redis_handle_info (rn->name, rr->str, "cache_result", "hits", "keyspace_hits", DS_TYPE_DERIVE);
+ redis_handle_info (rn->name, rr->str, "cache_result", "misses", "keyspace_misses", DS_TYPE_DERIVE);
+ redis_handle_info (rn->name, rr->str, "total_bytes", "input", "total_net_input_bytes", DS_TYPE_DERIVE);
+ redis_handle_info (rn->name, rr->str, "total_bytes", "output", "total_net_output_bytes", DS_TYPE_DERIVE);
- for (rq = rn->queries; rq != NULL; rq = rq->next)
+ for (redis_query_t *rq = rn->queries; rq != NULL; rq = rq->next)
redis_handle_query(rh, rn, rq);
redis_fail:
diff --git a/src/riemann.proto b/src/riemann.proto
--- a/src/riemann.proto
+++ /dev/null
@@ -1,45 +0,0 @@
-option java_package = "com.aphyr.riemann";
-option java_outer_classname = "Proto";
-
-message State {
- optional int64 time = 1;
- optional string state = 2;
- optional string service = 3;
- optional string host = 4;
- optional string description = 5;
- optional bool once = 6;
- repeated string tags = 7;
- optional float ttl = 8;
-}
-
-message Event {
- optional int64 time = 1;
- optional string state = 2;
- optional string service = 3;
- optional string host = 4;
- optional string description = 5;
- repeated string tags = 7;
- optional float ttl = 8;
- repeated Attribute attributes = 9;
-
- optional sint64 metric_sint64 = 13;
- optional double metric_d = 14;
- optional float metric_f = 15;
-}
-
-message Query {
- optional string string = 1;
-}
-
-message Msg {
- optional bool ok = 2;
- optional string error = 3;
- repeated State states = 4;
- optional Query query = 5;
- repeated Event events = 6;
-}
-
-message Attribute {
- required string key = 1;
- optional string value = 2;
-}
diff --git a/src/routeros.c b/src/routeros.c
index 4863d7c082b1e8297b48152c379dc6a4701b0a1d..a270f484981dbde8a9e1ac2681a8205c445049ba 100644 (file)
--- a/src/routeros.c
+++ b/src/routeros.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
char read_name[128];
user_data_t user_data;
int status;
- int i;
- router_data = malloc (sizeof (*router_data));
+ router_data = calloc (1, sizeof (*router_data));
if (router_data == NULL)
return (-1);
- memset (router_data, 0, sizeof (*router_data));
router_data->connection = NULL;
router_data->node = NULL;
router_data->service = NULL;
router_data->password = NULL;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
user_data.free_func = (void *) cr_free_data;
if (status == 0)
status = plugin_register_complex_read (/* group = */ NULL, read_name,
- cr_read, /* interval = */ NULL, &user_data);
+ cr_read, /* interval = */ 0, &user_data);
if (status != 0)
cr_free_data (router_data);
static int cr_config (oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/rrdcached.c b/src/rrdcached.c
index 42fd3a34414969b139d8b0086c3016ebd7603f7b..0b9040536ecc165f0b9a85ea7bacd1d5866358d6 100644 (file)
--- a/src/rrdcached.c
+++ b/src/rrdcached.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include "utils_rrdcreate.h"
{
int offset;
int status;
- int i;
time_t t;
assert (0 == strcmp (ds->type, vl->type));
return (-1);
offset = status;
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if ((ds->ds[i].type != DS_TYPE_COUNTER)
&& (ds->ds[i].type != DS_TYPE_GAUGE)
status = ssnprintf (buffer + offset, buffer_len - offset,
":%llu", vl->values[i].counter);
}
- else if (ds->ds[i].type == DS_TYPE_GAUGE)
+ else if (ds->ds[i].type == DS_TYPE_GAUGE)
{
status = ssnprintf (buffer + offset, buffer_len - offset,
":%f", vl->values[i].gauge);
else /* if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */ {
status = ssnprintf (buffer + offset, buffer_len - offset,
":%"PRIu64, vl->values[i].absolute);
-
+
}
if ((status < 1) || (status >= (buffer_len - offset)))
static int rc_config (oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t const *child = ci->children + i;
const char *key = child->key;
{
int status;
rrdc_stats_t *head;
- rrdc_stats_t *ptr;
_Bool retried = 0;
value_t values[1];
if (status == 0)
break;
- if (! retried)
+ if (!retried)
{
retried = 1;
if (try_reconnect () == 0)
return (-1);
}
- for (ptr = head; ptr != NULL; ptr = ptr->next)
+ for (rrdc_stats_t *ptr = head; ptr != NULL; ptr = ptr->next)
{
if (ptr->type == RRDC_STATS_TYPE_GAUGE)
values[0].gauge = (gauge_t) ptr->value.gauge;
if (status == 0)
break;
- if (! retried)
+ if (!retried)
{
retried = 1;
if (try_reconnect () == 0)
if (status == 0)
break;
- if (! retried)
+ if (!retried)
{
retried = 1;
if (try_reconnect () == 0)
diff --git a/src/rrdtool.c b/src/rrdtool.c
index 7cfdae60302f5e26968288c50ec7572d455d3687..094dd42a7a6b8217a5fec858ec0683a535342be1 100644 (file)
--- a/src/rrdtool.c
+++ b/src/rrdtool.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include "utils_avltree.h"
#include <rrd.h>
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
/*
* Private types
*/
assert (template == NULL);
new_argc = 2 + argc;
- new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+ new_argv = malloc ((new_argc + 1) * sizeof (*new_argv));
if (new_argv == NULL)
{
ERROR ("rrdtool plugin: malloc failed.");
int offset;
int status;
time_t tt;
- int i;
memset (buffer, '\0', buffer_len);
return (-1);
offset = status;
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if ((ds->ds[i].type != DS_TYPE_COUNTER)
&& (ds->ds[i].type != DS_TYPE_GAUGE)
char **values;
int values_num;
int status;
- int i;
values = NULL;
values_num = 0;
pthread_mutex_unlock (&queue_lock);
/* We now need the cache lock so the entry isn't updated while
- * we make a copy of it's values */
+ * we make a copy of its values */
pthread_mutex_lock (&cache_lock);
status = c_avl_get (cache, queue_entry->filename,
}
/* Update `tv_next_update' */
- if (write_rate > 0.0)
+ if (write_rate > 0.0)
{
gettimeofday (&tv_now, /* timezone = */ NULL);
tv_next_update.tv_sec = tv_now.tv_sec;
values_num, (values_num == 1) ? "" : "s",
queue_entry->filename);
- for (i = 0; i < values_num; i++)
+ for (int i = 0; i < values_num; i++)
{
sfree (values[i]);
}
{
rrd_queue_t *queue_entry;
- queue_entry = (rrd_queue_t *) malloc (sizeof (rrd_queue_t));
+ queue_entry = malloc (sizeof (*queue_entry));
if (queue_entry == NULL)
return (-1);
{
if (strcmp (this->filename, filename) == 0)
break;
-
+
prev = this;
this = this->next;
}
char *key;
c_avl_iterator_t *iter;
- int i;
DEBUG ("rrdtool plugin: Flushing cache, timeout = %.3f",
CDTIME_T_TO_DOUBLE (timeout));
}
else /* ancient and no values -> waste of memory */
{
- char **tmp = (char **) realloc ((void *) keys,
+ char **tmp = realloc (keys,
(keys_num + 1) * sizeof (char *));
if (tmp == NULL)
{
}
} /* while (c_avl_iterator_next) */
c_avl_iterator_destroy (iter);
-
- for (i = 0; i < keys_num; i++)
+
+ for (int i = 0; i < keys_num; i++)
{
if (c_avl_remove (cache, keys[i], (void *) &key, (void *) &rc) != 0)
{
long min;
long max;
- if (random_timeout <= 0)
+ if (random_timeout == 0)
return (0);
/* Assure that "cache_timeout + random_variation" is never negative. */
return (-1);
}
- values_new = (char **) realloc ((void *) rc->values,
+ values_new = realloc ((void *) rc->values,
(rc->values_num + 1) * sizeof (char *));
if (values_new == NULL)
{
while (c_avl_pick (cache, &key, &value) == 0)
{
rrd_cache_t *rc;
- int i;
sfree (key);
key = NULL;
if (rc->values_num > 0)
non_empty++;
- for (i = 0; i < rc->values_num; i++)
+ for (int i = 0; i < rc->values_num; i++)
sfree (rc->values[i]);
sfree (rc->values);
sfree (rc);
while ((ptr = strtok_r (dummy, ", \t", &saveptr)) != NULL)
{
dummy = NULL;
-
+
tmp_alloc = realloc (rrdcreate_config.timespans,
sizeof (int) * (rrdcreate_config.timespans_num + 1));
if (tmp_alloc == NULL)
diff --git a/src/sensors.c b/src/sensors.c
index dc6a2101778ca4677e06d2f75dc954a294103672..4f3d0d6032b33b6d3e13d11a3223bbf326efd33b 100644 (file)
--- a/src/sensors.c
+++ b/src/sensors.c
*
* Authors:
* Florian octo Forster <octo at collectd.org>
- *
+ *
* Lubos Stanek <lubek at users.sourceforge.net> Wed Oct 27, 2006
* - config ExtendedSensorNaming option
* - precise sensor feature selection (chip-bus-address/type-feature)
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_ignorelist.h"
#if defined(HAVE_SENSORS_SENSORS_H)
typedef struct sensors_labeltypes_s sensors_labeltypes_t;
/* finite list of known labels extracted from lm_sensors */
-static sensors_labeltypes_t known_features[] =
+static sensors_labeltypes_t known_features[] =
{
{ "fan1", SENSOR_TYPE_FANSPEED },
{ "fan2", SENSOR_TYPE_FANSPEED },
{
"Sensor",
"IgnoreSelected",
- "SensorConfigFile"
+ "SensorConfigFile",
+ "UseLabels"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
} featurelist_t;
static char *conffile = NULL;
+static _Bool use_labels = 0;
/* #endif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500) */
#else /* if SENSORS_API_VERSION >= 0x500 */
"as bug."
#endif
-featurelist_t *first_feature = NULL;
+static featurelist_t *first_feature = NULL;
static ignorelist_t *sensor_list;
#if SENSORS_API_VERSION < 0x400
static int sensors_feature_name_to_type (const char *name)
{
- int i;
-
/* Yes, this is slow, but it's only ever done during initialization, so
* it's a one time cost.. */
- for (i = 0; i < known_features_num; i++)
+ for (int i = 0; i < known_features_num; i++)
if (strcasecmp (known_features[i].label, name) == 0)
return (known_features[i].type);
if (IS_TRUE (value))
ignorelist_set_invert (sensor_list, 0);
}
+#if (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500)
+ else if (strcasecmp (key, "UseLabels") == 0)
+ {
+ use_labels = IS_TRUE (value) ? 1 : 0;
+ }
+#endif
else
{
return (-1);
static void sensors_free_features (void)
{
- featurelist_t *thisft;
featurelist_t *nextft;
if (first_feature == NULL)
sensors_cleanup ();
- for (thisft = first_feature; thisft != NULL; thisft = nextft)
+ for (featurelist_t *thisft = first_feature; thisft != NULL; thisft = nextft)
{
nextft = thisft->next;
sfree (thisft);
FILE *fh = NULL;
featurelist_t *last_feature = NULL;
-
+
const sensors_chip_name *chip;
int chip_num;
continue;
}
- fl = (featurelist_t *) malloc (sizeof (featurelist_t));
+ fl = calloc (1, sizeof (*fl));
if (fl == NULL)
{
- ERROR ("sensors plugin: malloc failed.");
+ ERROR ("sensors plugin: calloc failed.");
continue;
}
- memset (fl, '\0', sizeof (featurelist_t));
fl->chip = chip;
fl->data = feature;
&& (subfeature->type != SENSORS_SUBFEATURE_POWER_INPUT))
continue;
- fl = (featurelist_t *) malloc (sizeof (featurelist_t));
+ fl = calloc (1, sizeof (*fl));
if (fl == NULL)
{
- ERROR ("sensors plugin: malloc failed.");
+ ERROR ("sensors plugin: calloc failed.");
continue;
}
- memset (fl, '\0', sizeof (featurelist_t));
fl->chip = chip;
fl->feature = feature;
static int sensors_read (void)
{
- featurelist_t *fl;
-
if (sensors_load_conf () != 0)
return (-1);
#if SENSORS_API_VERSION < 0x400
- for (fl = first_feature; fl != NULL; fl = fl->next)
+ for (featurelist_t *fl = first_feature; fl != NULL; fl = fl->next)
{
double value;
int status;
/* #endif SENSORS_API_VERSION < 0x400 */
#elif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500)
- for (fl = first_feature; fl != NULL; fl = fl->next)
+ for (featurelist_t *fl = first_feature; fl != NULL; fl = fl->next)
{
double value;
int status;
char plugin_instance[DATA_MAX_NAME_LEN];
char type_instance[DATA_MAX_NAME_LEN];
+ char *sensor_label;
const char *type;
status = sensors_get_value (fl->chip,
if (status < 0)
continue;
- sstrncpy (type_instance, fl->feature->name,
- sizeof (type_instance));
+ if (use_labels)
+ {
+ sensor_label = sensors_get_label (fl->chip, fl->feature);
+ sstrncpy (type_instance, sensor_label, sizeof (type_instance));
+ free (sensor_label);
+ }
+ else
+ {
+ sstrncpy (type_instance, fl->feature->name,
+ sizeof (type_instance));
+ }
if (fl->feature->type == SENSORS_FEATURE_IN)
type = "voltage";
diff --git a/src/serial.c b/src/serial.c
index 430082220595c58f2b927089871a76e4e482a157..cf7ad2a1ed9961d4c5ae254bf02b3371a87561e2 100644 (file)
--- a/src/serial.c
+++ b/src/serial.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
FILE *fh;
char buffer[1024];
- derive_t rx = 0;
- derive_t tx = 0;
-
- char *fields[16];
- int i, numfields;
- int len;
-
/* there are a variety of names for the serial device */
if ((fh = fopen ("/proc/tty/driver/serial", "r")) == NULL &&
(fh = fopen ("/proc/tty/driver/ttyS", "r")) == NULL)
while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
- int have_rx = 0, have_tx = 0;
+ derive_t rx = 0;
+ derive_t tx = 0;
+ _Bool have_rx = 0, have_tx = 0;
+ size_t len;
- numfields = strsplit (buffer, fields, 16);
+ char *fields[16];
+ int numfields;
+ numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
if (numfields < 6)
continue;
* 0: uart:16550A port:000003F8 irq:4 tx:0 rx:0
* 1: uart:16550A port:000002F8 irq:3 tx:0 rx:0
*/
- len = strlen (fields[0]) - 1;
- if (len < 1)
+ len = strlen (fields[0]);
+ if (len < 2)
continue;
- if (fields[0][len] != ':')
+ if (fields[0][len - 1] != ':')
continue;
- fields[0][len] = '\0';
+ fields[0][len - 1] = 0;
- for (i = 1; i < numfields; i++)
+ for (int i = 1; i < numfields; i++)
{
len = strlen (fields[i]);
if (len < 4)
if (strncmp (fields[i], "tx:", 3) == 0)
{
- tx = atoll (fields[i] + 3);
- have_tx++;
+ if (strtoderive (fields[i] + 3, &tx) == 0)
+ have_tx = 1;
}
else if (strncmp (fields[i], "rx:", 3) == 0)
{
- rx = atoll (fields[i] + 3);
- have_rx++;
+ if (strtoderive (fields[i] + 3, &rx) == 0)
+ have_rx = 1;
}
}
- if ((have_rx == 0) || (have_tx == 0))
- continue;
-
- serial_submit (fields[0], rx, tx);
+ if (have_rx && have_tx)
+ serial_submit (fields[0], rx, tx);
}
fclose (fh);
diff --git a/src/sigrok.c b/src/sigrok.c
index 487f31a1b8030edbb299affb87368849d743064c..400645538d7d842f5d47f422f1347a2be5d7112d 100644 (file)
--- a/src/sigrok.c
+++ b/src/sigrok.c
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#include <pthread.h>
#include <glib.h>
#include <libsigrok/libsigrok.h>
static int sigrok_config_device(oconfig_item_t *ci)
{
struct config_device *cfdev;
- int i;
- if (!(cfdev = malloc(sizeof(struct config_device)))) {
- ERROR("sigrok plugin: malloc() failed.");
+ if (!(cfdev = calloc(1, sizeof(*cfdev)))) {
+ ERROR("sigrok plugin: calloc failed.");
return -1;
}
- memset(cfdev, 0, sizeof(*cfdev));
if (cf_util_get_string(ci, &cfdev->name)) {
free(cfdev);
WARNING("sigrok plugin: Invalid device name.");
}
cfdev->min_dispatch_interval = DEFAULT_MIN_DISPATCH_INTERVAL;
- for (i = 0; i < ci->children_num; i++) {
+ for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *item = ci->children + i;
if (!strcasecmp(item->key, "driver"))
cf_util_get_string(item, &cfdev->driver);
static int sigrok_config(oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++) {
+ for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *item = ci->children + i;
if (strcasecmp("LogLevel", item->key) == 0) {
int status;
return 0;
}
-static char *sigrok_value_type(const struct sr_datafeed_analog *analog)
+static const char *sigrok_value_type(const struct sr_datafeed_analog *analog)
{
- char *s;
+ const char *s;
if (analog->mq == SR_MQ_VOLTAGE)
s = "voltage";
{
const struct sr_datafeed_analog *analog;
struct config_device *cfdev;
- GSList *l;
value_t value;
value_list_t vl = VALUE_LIST_INIT;
/* Find this device's configuration. */
cfdev = NULL;
- for (l = config_devices; l; l = l->next) {
+ for (GSList *l = config_devices; l; l = l->next) {
cfdev = l->data;
if (cfdev->sdi == sdi) {
/* Found it. */
drvopts = NULL;
if (cfdev->conn) {
- if (!(src = malloc(sizeof(struct sr_config))))
+ if (!(src = malloc(sizeof(*src))))
return -1;
src->key = SR_CONF_CONN;
src->data = g_variant_new_string(cfdev->conn);
drvopts = g_slist_append(drvopts, src);
}
if (cfdev->serialcomm) {
- if (!(src = malloc(sizeof(struct sr_config))))
+ if (!(src = malloc(sizeof(*src))))
return -1;
src->key = SR_CONF_SERIALCOMM;
src->data = g_variant_new_string(cfdev->serialcomm);
diff --git a/src/smart.c b/src/smart.c
index 2207bd6722449f4de11c3b89a976817ba8702558..752cb74cbe603baf47be59d482c0475983f063a6 100644 (file)
--- a/src/smart.c
+++ b/src/smart.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_ignorelist.h"
static const char *config_keys[] =
{
"Disk",
- "IgnoreSelected"
+ "IgnoreSelected",
+ "IgnoreSleepMode",
+ "UseSerial"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static ignorelist_t *ignorelist = NULL;
+static int ignore_sleep_mode = 0;
+static int use_serial = 0;
static int smart_config (const char *key, const char *value)
{
invert = 0;
ignorelist_set_invert (ignorelist, invert);
}
+ else if (strcasecmp ("IgnoreSleepMode", key) == 0)
+ {
+ if (IS_TRUE (value))
+ ignore_sleep_mode = 1;
+ }
+ else if (strcasecmp ("UseSerial", key) == 0)
+ {
+ if (IS_TRUE (value))
+ use_serial = 1;
+ }
else
{
return (-1);
return (0);
} /* int smart_config */
-static void smart_submit (const char *dev, char *type, char *type_inst, double value)
+static void smart_submit (const char *dev, const char *type,
+ const char *type_inst, double value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
@@ -129,7 +145,7 @@ static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedD
}
}
-static void smart_handle_disk (const char *dev)
+static void smart_handle_disk (const char *dev, const char *serial)
{
SkDisk *d = NULL;
SkBool awake = FALSE;
const SkSmartParsedData *spd;
uint64_t poweron, powercycles, badsectors, temperature;
- shortname = strrchr(dev, '/');
- if (!shortname) return;
- shortname++;
+ if (use_serial && serial)
+ {
+ shortname = serial;
+ }
+ else
+ {
+ shortname = strrchr(dev, '/');
+ if (!shortname) return;
+ shortname++;
+ }
if (ignorelist_match (ignorelist, shortname) != 0) {
DEBUG ("smart plugin: ignoring %s.", dev);
return;
DEBUG ("smart plugin: disk %s has no SMART support.", dev);
goto end;
}
- if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+ if (!ignore_sleep_mode)
{
- DEBUG ("smart plugin: disk %s is sleeping.", dev);
- goto end;
+ if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+ {
+ DEBUG ("smart plugin: disk %s is sleeping.", dev);
+ goto end;
+ }
}
if (sk_disk_smart_read_data (d) < 0)
{
devices = udev_enumerate_get_list_entry (enumerate);
udev_list_entry_foreach (dev_list_entry, devices)
{
- const char *path, *devpath;
+ const char *path, *devpath, *serial;
path = udev_list_entry_get_name (dev_list_entry);
dev = udev_device_new_from_syspath (handle_udev, path);
devpath = udev_device_get_devnode (dev);
+ serial = udev_device_get_property_value (dev, "ID_SERIAL");
/* Query status with libatasmart */
- smart_handle_disk (devpath);
+ smart_handle_disk (devpath, serial);
udev_device_unref (dev);
}
diff --git a/src/snmp.c b/src/snmp.c
index ae41d03ae8562781a5ba0f7ec1ff155666f63795..abeda436795427f9597e281c30ce1e8ae656b519 100644 (file)
--- a/src/snmp.c
+++ b/src/snmp.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_complain.h"
-#include <pthread.h>
-
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
instance_t instance;
char *instance_prefix;
oid_t *values;
- int values_len;
+ size_t values_len;
double scale;
double shift;
struct data_definition_s *next;
{
char oid_str[MAX_OID_LEN][16];
char *oid_str_ptr[MAX_OID_LEN];
- size_t i;
- for (i = 0; i < o->oid_len; i++)
+ for (size_t i = 0; i < o->oid_len; i++)
{
ssnprintf (oid_str[i], sizeof (oid_str[i]), "%lu", (unsigned long) o->oid[i]);
oid_str_ptr[i] = oid_str[i];
static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *ci)
{
- int i;
-
if (ci->values_num < 1)
{
WARNING ("snmp plugin: `Values' needs at least one argument.");
return (-1);
}
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
if (ci->values[i].type != OCONFIG_TYPE_STRING)
{
WARNING ("snmp plugin: `Values' needs only string argument.");
@@ -310,12 +306,12 @@ static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *
sfree (dd->values);
dd->values_len = 0;
- dd->values = (oid_t *) malloc (sizeof (oid_t) * ci->values_num);
+ dd->values = malloc (sizeof (*dd->values) * ci->values_num);
if (dd->values == NULL)
return (-1);
- dd->values_len = ci->values_num;
+ dd->values_len = (size_t) ci->values_num;
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
dd->values[i].oid_len = MAX_OID_LEN;
@@ -336,12 +332,10 @@ static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *
static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t *ci)
{
- int i;
-
if (ci->values_num < 1)
return (0);
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
if (ci->values[i].type != OCONFIG_TYPE_STRING)
{
@@ -353,7 +347,7 @@ static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t
dd->ignores_len = 0;
dd->ignores = NULL;
- for (i = 0; i < ci->values_num; ++i)
+ for (int i = 0; i < ci->values_num; ++i)
{
if (strarray_add(&(dd->ignores), &(dd->ignores_len), ci->values[i].value.string) != 0)
{
{
data_definition_t *dd;
int status = 0;
- int i;
- dd = (data_definition_t *) malloc (sizeof (data_definition_t));
+ dd = calloc (1, sizeof (*dd));
if (dd == NULL)
return (-1);
- memset (dd, '\0', sizeof (data_definition_t));
status = cf_util_get_string(ci, &dd->name);
if (status != 0)
dd->scale = 1.0;
dd->shift = 0.0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
return (-1);
}
- DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %i }",
+ DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %zu }",
dd->name, dd->type, (dd->is_table != 0) ? "true" : "false", dd->values_len);
if (data_head == NULL)
data_definition_t *data;
data_definition_t **data_list;
int data_list_len;
- int i;
if (ci->values_num < 1)
{
return (-1);
}
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
if (ci->values[i].type != OCONFIG_TYPE_STRING)
{
WARNING ("snmp plugin: All arguments to `Collect' must be strings.");
}
data_list_len = host->data_list_len + ci->values_num;
- data_list = (data_definition_t **) realloc (host->data_list,
+ data_list = realloc (host->data_list,
sizeof (data_definition_t *) * data_list_len);
if (data_list == NULL)
return (-1);
host->data_list = data_list;
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
for (data = data_head; data != NULL; data = data->next)
if (strcasecmp (ci->values[i].value.string, data->name) == 0)
{
host_definition_t *hd;
int status = 0;
- int i;
/* Registration stuff. */
char cb_name[DATA_MAX_NAME_LEN];
- user_data_t cb_data;
- struct timespec cb_interval;
- hd = (host_definition_t *) malloc (sizeof (host_definition_t));
+ hd = calloc (1, sizeof (*hd));
if (hd == NULL)
return (-1);
- memset (hd, '\0', sizeof (host_definition_t));
hd->version = 2;
C_COMPLAIN_INIT (&hd->complaint);
hd->sess_handle = NULL;
hd->interval = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
status = 0;
ssnprintf (cb_name, sizeof (cb_name), "snmp-%s", hd->name);
- memset (&cb_data, 0, sizeof (cb_data));
- cb_data.data = hd;
- cb_data.free_func = csnmp_host_definition_destroy;
-
- CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval);
+ user_data_t ud = {
+ .data = hd,
+ .free_func = csnmp_host_definition_destroy
+ };
status = plugin_register_complex_read (/* group = */ NULL, cb_name,
- csnmp_read_host, /* interval = */ &cb_interval,
- /* user_data = */ &cb_data);
+ csnmp_read_host, hd->interval, /* user_data = */ &ud);
if (status != 0)
{
ERROR ("snmp plugin: Registering complex read function failed.");
static int csnmp_config (oconfig_item_t *ci)
{
- int i;
-
call_snmp_init_once ();
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("Data", child->key) == 0)
}
else
{
- char oid_buffer[1024];
+ char oid_buffer[1024] = { 0 };
- memset (oid_buffer, 0, sizeof (oid_buffer));
snprint_objid (oid_buffer, sizeof (oid_buffer) - 1,
vl->name, vl->name_length);
@@ -1055,50 +1037,67 @@ static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
return (ret);
} /* value_t csnmp_value_list_to_value */
+/* csnmp_strvbcopy_hexstring converts the bit string contained in "vb" to a hex
+ * representation and writes it to dst. Returns zero on success and ENOMEM if
+ * dst is not large enough to hold the string. dst is guaranteed to be
+ * nul-terminated. */
static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
const struct variable_list *vb, size_t dst_size)
{
char *buffer_ptr;
size_t buffer_free;
- size_t i;
+
+ dst[0] = 0;
buffer_ptr = dst;
buffer_free = dst_size;
- for (i = 0; i < vb->val_len; i++)
+ for (size_t i = 0; i < vb->val_len; i++)
{
int status;
status = snprintf (buffer_ptr, buffer_free,
(i == 0) ? "%02x" : ":%02x", (unsigned int) vb->val.bitstring[i]);
+ assert (status >= 0);
- if (status >= buffer_free)
+ if (((size_t) status) >= buffer_free) /* truncated */
{
- buffer_ptr += (buffer_free - 1);
- *buffer_ptr = 0;
- return (dst_size + (buffer_free - status));
+ dst[dst_size - 1] = 0;
+ return ENOMEM;
}
else /* if (status < buffer_free) */
{
- buffer_ptr += status;
- buffer_free -= status;
+ buffer_ptr += (size_t) status;
+ buffer_free -= (size_t) status;
}
}
- return ((int) (dst_size - buffer_free));
+ return 0;
} /* }}} int csnmp_strvbcopy_hexstring */
+/* csnmp_strvbcopy copies the octet string or bit string contained in vb to
+ * dst. If non-printable characters are detected, it will switch to a hex
+ * representation of the string. Returns zero on success, EINVAL if vb does not
+ * contain a string and ENOMEM if dst is not large enough to contain the
+ * string. */
static int csnmp_strvbcopy (char *dst, /* {{{ */
const struct variable_list *vb, size_t dst_size)
{
char *src;
size_t num_chars;
- size_t i;
if (vb->type == ASN_OCTET_STR)
src = (char *) vb->val.string;
else if (vb->type == ASN_BIT_STR)
src = (char *) vb->val.bitstring;
+ else if (vb->type == ASN_IPADDRESS)
+ {
+ return ssnprintf (dst, dst_size, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"",
+ (uint8_t) vb->val.string[0],
+ (uint8_t) vb->val.string[1],
+ (uint8_t) vb->val.string[2],
+ (uint8_t) vb->val.string[3]);
+ }
else
{
dst[0] = 0;
if (num_chars > vb->val_len)
num_chars = vb->val_len;
- for (i = 0; i < num_chars; i++)
+ for (size_t i = 0; i < num_chars; i++)
{
/* Check for control characters. */
if ((unsigned char)src[i] < 32)
dst[i] = src[i];
}
dst[num_chars] = 0;
+ dst[dst_size - 1] = 0;
+
+ if (dst_size <= vb->val_len)
+ return ENOMEM;
- return ((int) vb->val_len);
+ return 0;
} /* }}} int csnmp_strvbcopy */
static int csnmp_instance_list_add (csnmp_list_instances_t **head,
struct variable_list *vb;
oid_t vb_name;
int status;
- uint32_t i;
uint32_t is_matched;
/* Set vb on the last variable */
csnmp_oid_init (&vb_name, vb->name, vb->name_length);
- il = malloc (sizeof (*il));
+ il = calloc (1, sizeof (*il));
if (il == NULL)
{
- ERROR ("snmp plugin: malloc failed.");
+ ERROR ("snmp plugin: calloc failed.");
return (-1);
}
- memset (il, 0, sizeof (*il));
il->next = NULL;
status = csnmp_oid_suffix (&il->suffix, &vb_name, &dd->instance.oid);
}
/* Get instance name */
- if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR))
+ if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR) || (vb->type == ASN_IPADDRESS))
{
char *ptr;
csnmp_strvbcopy (il->instance, vb, sizeof (il->instance));
is_matched = 0;
- for (i = 0; i < dd->ignores_len; i++)
+ for (uint32_t i = 0; i < dd->ignores_len; i++)
{
status = fnmatch(dd->ignores[i], il->instance, 0);
if (status == 0)
@@ -1226,7 +1227,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
csnmp_list_instances_t *instance_list_ptr;
csnmp_table_values_t **value_table_ptr;
- int i;
+ size_t i;
_Bool have_more;
oid_t current_suffix;
@@ -1241,7 +1242,7 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
instance_list_ptr = instance_list;
- value_table_ptr = calloc ((size_t) data->values_len, sizeof (*value_table_ptr));
+ value_table_ptr = calloc (data->values_len, sizeof (*value_table_ptr));
if (value_table_ptr == NULL)
return (-1);
for (i = 0; i < data->values_len; i++)
@@ -1262,7 +1263,6 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
vl.interval = host->interval;
have_more = 1;
- memset (¤t_suffix, 0, sizeof (current_suffix));
while (have_more)
{
_Bool suffix_skipped = 0;
@@ -1361,8 +1361,12 @@ static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *dat
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 (&vl);
+ /* If we get here `vl.type_instance' and all `vl.values' have been set
+ * vl.type_instance can be empty, i.e. a blank port description on a
+ * switch if you're using IF-MIB::ifDescr as Instance.
+ */
+ if (vl.type_instance[0] != '\0')
+ plugin_dispatch_values (&vl);
if (instance_list != NULL)
instance_list_ptr = instance_list_ptr->next;
@@ -1384,7 +1388,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
const data_set_t *ds;
- uint32_t oid_list_len = (uint32_t) (data->values_len + 1);
+ size_t oid_list_len = data->values_len + 1;
/* Holds the last OID returned by the device. We use this in the GETNEXT
* request to proceed. */
oid_t oid_list[oid_list_len];
@@ -1393,8 +1397,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
_Bool oid_list_todo[oid_list_len];
int status;
- int i;
- uint32_t j;
+ size_t i;
/* `value_list_head' and `value_list_tail' implement a linked list for each
* value. `instance_list_head' and `instance_list_tail' implement a linked list of
@@ -1422,7 +1425,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
if (ds->ds_num != data->values_len)
{
- ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
+ ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
data->type, ds->ds_num, data->values_len);
return (-1);
}
@@ -1435,8 +1438,8 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
else /* no InstanceFrom option specified. */
oid_list_len--;
- for (j = 0; j < oid_list_len; j++)
- oid_list_todo[j] = 1;
+ for (i = 0; i < oid_list_len; i++)
+ oid_list_todo[i] = 1;
/* We're going to construct n linked lists, one for each "value".
* value_list_head will contain pointers to the heads of these linked lists,
@@ -1468,13 +1471,13 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
}
oid_list_todo_num = 0;
- for (j = 0; j < oid_list_len; j++)
+ for (i = 0; i < oid_list_len; i++)
{
/* Do not rerequest already finished OIDs */
- if (!oid_list_todo[j])
+ if (!oid_list_todo[i])
continue;
oid_list_todo_num++;
- snmp_add_null_var (req, oid_list[j].oid, oid_list[j].oid_len);
+ snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);
}
if (oid_list_todo_num == 0)
@@ -1570,7 +1573,7 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
if (ret != 0)
{
- DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+ DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
"Value probably left its subtree.",
host->name, data->name, i);
oid_list_todo[i] = 0;
@@ -1582,21 +1585,20 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
if ((value_list_tail[i] != NULL)
&& (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
{
- DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+ DEBUG ("snmp plugin: host = %s; data = %s; i = %zu; "
"Suffix is not increasing.",
host->name, data->name, i);
oid_list_todo[i] = 0;
continue;
}
- vt = malloc (sizeof (*vt));
+ vt = calloc (1, sizeof (*vt));
if (vt == NULL)
{
- ERROR ("snmp plugin: malloc failed.");
+ ERROR ("snmp plugin: calloc failed.");
status = -1;
break;
}
- memset (vt, 0, sizeof (*vt));
vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
data->scale, data->shift, host->name, data->name);
@@ -1659,14 +1661,14 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
{
struct snmp_pdu *req;
- struct snmp_pdu *res;
+ struct snmp_pdu *res = NULL;
struct variable_list *vb;
const data_set_t *ds;
value_list_t vl = VALUE_LIST_INIT;
int status;
- int i;
+ size_t i;
DEBUG ("snmp plugin: csnmp_read_value (host = %s, data = %s)",
host->name, data->name);
@@ -1686,13 +1688,13 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
if (ds->ds_num != data->values_len)
{
- ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
+ ERROR ("snmp plugin: DataSet `%s' requires %zu values, but config talks about %zu",
data->type, ds->ds_num, data->values_len);
return (-1);
}
vl.values_len = ds->ds_num;
- vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len);
+ vl.values = malloc (sizeof (*vl.values) * vl.values_len);
if (vl.values == NULL)
return (-1);
for (i = 0; i < vl.values_len; i++)
@@ -1721,7 +1723,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
for (i = 0; i < data->values_len; i++)
snmp_add_null_var (req, data->values[i].oid, data->values[i].oid_len);
- res = NULL;
status = snmp_sess_synch_response (host->sess_handle, req, &res);
if ((status != STAT_SUCCESS) || (res == NULL))
@@ -1734,7 +1735,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
if (res != NULL)
snmp_free_pdu (res);
- res = NULL;
sfree (errstr);
sfree (vl.values);
@@ -1760,9 +1760,7 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
data->scale, data->shift, host->name, data->name);
} /* for (res->variables) */
- if (res != NULL)
- snmp_free_pdu (res);
- res = NULL;
+ snmp_free_pdu (res);
DEBUG ("snmp plugin: -> plugin_dispatch_values (&vl);");
plugin_dispatch_values (&vl);
@@ -1774,8 +1772,6 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
static int csnmp_read_host (user_data_t *ud)
{
host_definition_t *host;
- cdtime_t time_start;
- cdtime_t time_end;
int status;
int success;
int i;
if (host->interval == 0)
host->interval = plugin_get_interval ();
- time_start = cdtime ();
-
if (host->sess_handle == NULL)
csnmp_host_open_session (host);
success++;
}
- time_end = cdtime ();
- if ((time_end - time_start) > host->interval)
- {
- WARNING ("snmp plugin: Host `%s' should be queried every %.3f "
- "seconds, but reading all values takes %.3f seconds.",
- host->name,
- CDTIME_T_TO_DOUBLE (host->interval),
- CDTIME_T_TO_DOUBLE (time_end - time_start));
- }
-
if (success == 0)
return (-1);
diff --git a/src/statsd.c b/src/statsd.c
index 54b6e943618d8f65b19c1a538a0cdf6758442814..9c138f978bb6dec71e600bf49a72682f62664ab4 100644 (file)
--- a/src/statsd.c
+++ b/src/statsd.c
*/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
-#include "configfile.h"
#include "utils_avltree.h"
-#include "utils_complain.h"
#include "utils_latency.h"
-#include <pthread.h>
-
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
#include <poll.h>
{
metric_type_t type;
double value;
+ derive_t counter;
latency_counter_t *latency;
c_avl_tree_t *set;
unsigned long updates_num;
static double *conf_timer_percentile = NULL;
static size_t conf_timer_percentile_num = 0;
+static _Bool conf_counter_sum = 0;
static _Bool conf_timer_lower = 0;
static _Bool conf_timer_upper = 0;
static _Bool conf_timer_sum = 0;
@@ -126,14 +124,13 @@ static statsd_metric_t *statsd_metric_lookup_unsafe (char const *name, /* {{{ */
return (NULL);
}
- metric = malloc (sizeof (*metric));
+ metric = calloc (1, sizeof (*metric));
if (metric == NULL)
{
- ERROR ("statsd plugin: malloc failed.");
+ ERROR ("statsd plugin: calloc failed.");
sfree (key_copy);
return (NULL);
}
- memset (metric, 0, sizeof (*metric));
metric->type = type;
metric->latency = NULL;
if (status != 0)
return (status);
+ /* Changes to the counter are added to (statsd_metric_t*)->value. ->counter is
+ * only updated in statsd_metric_submit_unsafe(). */
return (statsd_metric_add (name, (double) (value.gauge / scale.gauge),
STATSD_COUNTER));
} /* }}} int statsd_handle_counter */
/* Make sure metric->set exists. */
if (metric->set == NULL)
- metric->set = c_avl_create ((void *) strcmp);
+ metric->set = c_avl_create ((int (*) (const void *, const void *)) strcmp);
if (metric->set == NULL)
{
struct pollfd *fds = NULL;
size_t fds_num = 0;
- struct addrinfo ai_hints;
- struct addrinfo *ai_list = NULL;
- struct addrinfo *ai_ptr;
+ struct addrinfo *ai_list;
int status;
char const *node = (conf_node != NULL) ? conf_node : STATSD_DEFAULT_NODE;
char const *service = (conf_service != NULL)
? conf_service : STATSD_DEFAULT_SERVICE;
- memset (&ai_hints, 0, sizeof (ai_hints));
- ai_hints.ai_flags = AI_PASSIVE;
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_DGRAM;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_PASSIVE | AI_ADDRCONFIG,
+ .ai_socktype = SOCK_DGRAM
+ };
status = getaddrinfo (node, service, &ai_hints, &ai_list);
if (status != 0)
return (status);
}
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
int fd;
struct pollfd *tmp;
struct pollfd *fds = NULL;
size_t fds_num = 0;
int status;
- size_t i;
status = statsd_network_init (&fds, &fds_num);
if (status != 0)
break;
}
- for (i = 0; i < fds_num; i++)
+ for (size_t i = 0; i < fds_num; i++)
{
if ((fds[i].revents & (POLLIN | POLLPRI)) == 0)
continue;
} /* while (!network_thread_shutdown) */
/* Clean up */
- for (i = 0; i < fds_num; i++)
+ for (size_t i = 0; i < fds_num; i++)
close (fds[i].fd);
sfree (fds);
static int statsd_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
cf_util_get_boolean (child, &conf_delete_gauges);
else if (strcasecmp ("DeleteSets", child->key) == 0)
cf_util_get_boolean (child, &conf_delete_sets);
+ else if (strcasecmp ("CounterSum", child->key) == 0)
+ cf_util_get_boolean (child, &conf_counter_sum);
else if (strcasecmp ("TimerLower", child->key) == 0)
cf_util_get_boolean (child, &conf_timer_lower);
else if (strcasecmp ("TimerUpper", child->key) == 0)
{
pthread_mutex_lock (&metrics_lock);
if (metrics_tree == NULL)
- metrics_tree = c_avl_create ((void *) strcmp);
+ metrics_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
if (!network_thread_running)
{
} /* }}} int statsd_metric_clear_set_unsafe */
/* Must hold metrics_lock when calling this function. */
-static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
- statsd_metric_t const *metric)
+static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metric) /* {{{ */
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
values[0].gauge = (gauge_t) metric->value;
else if (metric->type == STATSD_TIMER)
{
- size_t i;
_Bool have_events = (metric->updates_num > 0);
/* Make sure all timer metrics share the *same* timestamp. */
plugin_dispatch_values (&vl);
}
- for (i = 0; i < conf_timer_percentile_num; i++)
+ for (size_t i = 0; i < conf_timer_percentile_num; i++)
{
ssnprintf (vl.type_instance, sizeof (vl.type_instance),
"%s-percentile-%.0f", name, conf_timer_percentile[i]);
values[0].gauge = (gauge_t) c_avl_size (metric->set);
}
else { /* STATSD_COUNTER */
- /*
- * Expand a single value to two metrics:
- *
- * - The absolute counter, as a gauge
- * - A derived rate for this counter
- */
- values[0].derive = (derive_t) metric->value;
- plugin_dispatch_values(&vl);
+ gauge_t delta = nearbyint (metric->value);
+
+ /* Etsy's statsd writes counters as two metrics: a rate and the change since
+ * the last write. Since collectd does not reset its DERIVE metrics to zero,
+ * this makes little sense, but we're dispatching a "count" metric here
+ * anyway - if requested by the user - for compatibility reasons. */
+ if (conf_counter_sum)
+ {
+ sstrncpy (vl.type, "count", sizeof (vl.type));
+ values[0].gauge = delta;
+ plugin_dispatch_values (&vl);
+
+ /* restore vl.type */
+ sstrncpy (vl.type, "derive", sizeof (vl.type));
+ }
+
+ /* Rather than resetting value to zero, subtract delta so we correctly keep
+ * track of residuals. */
+ metric->value -= delta;
+ metric->counter += (derive_t) delta;
- sstrncpy(vl.type, "gauge", sizeof (vl.type));
- values[0].gauge = (gauge_t) metric->value;
+ values[0].derive = metric->counter;
}
return (plugin_dispatch_values (&vl));
char **to_be_deleted = NULL;
size_t to_be_deleted_num = 0;
- size_t i;
pthread_mutex_lock (&metrics_lock);
}
c_avl_iterator_destroy (iter);
- for (i = 0; i < to_be_deleted_num; i++)
+ for (size_t i = 0; i < to_be_deleted_num; i++)
{
int status;
diff --git a/src/swap.c b/src/swap.c
index e4c5d24f23bccc918b440c06db86260c0715d44d..9c63e9bbb56ca82a7e4ce25de7219d79aa8040d2 100644 (file)
--- a/src/swap.c
+++ b/src/swap.c
#endif
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
static _Bool report_by_device = 0;
/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS */
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS
+/* No global variables */
+/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
+
#elif defined(VM_SWAPUSAGE)
/* No global variables */
/* #endif defined(VM_SWAPUSAGE) */
static int swap_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("ReportBytes", child->key) == 0)
char *s_paths;
int swap_num;
int status;
- int i;
gauge_t avail = 0;
gauge_t total = 0;
sfree (s);
return (-1);
}
- for (i = 0; i < swap_num; i++)
+ for (int i = 0; i < swap_num; i++)
s->swt_ent[i].ste_path = s_paths + (i * PATH_MAX);
s->swt_n = swap_num;
/* less elements returned than requested */
swap_num = status;
- for (i = 0; i < swap_num; i++)
+ for (int i = 0; i < swap_num; i++)
{
char path[PATH_MAX];
gauge_t this_total;
struct swapent *swap_entries;
int swap_num;
int status;
- int i;
gauge_t used = 0;
gauge_t total = 0;
/* TODO: Report per-device stats. The path name is available from
* swap_entries[i].se_path */
- for (i = 0; i < swap_num; i++)
+ for (int i = 0; i < swap_num; i++)
{
if ((swap_entries[i].se_flags & SWF_ENABLE) == 0)
continue;
{
ERROR ("swap plugin: Total swap space (%g) is less than used swap space (%g).",
total, used);
+ sfree (swap_entries);
return (-1);
}
#elif HAVE_PERFSTAT
static int swap_read (void) /* {{{ */
{
- perfstat_memory_total_t pmemory;
+ perfstat_memory_total_t pmemory = { 0 };
int status;
gauge_t total;
gauge_t free;
gauge_t reserved;
- memset (&pmemory, 0, sizeof (pmemory));
status = perfstat_memory_total (NULL, &pmemory, sizeof(perfstat_memory_total_t), 1);
if (status < 0)
{
diff --git a/src/syslog.c b/src/syslog.c
index 3f73178fa5e09283dec5efee71f57a3d941b0735..73e5e1f39fa440376fe2aa353b019b0690925a6f 100644 (file)
--- a/src/syslog.c
+++ b/src/syslog.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
char buf[1024] = "";
size_t offset = 0;
int log_severity;
- char *severity_string;
+ const char *severity_string;
int status;
if (n->severity > notif_severity)
diff --git a/src/table.c b/src/table.c
index fcbac4f5e475f9499eacf6d68caa891585f10d6d..81e946145fd858c0031f3452629b1357ca58d484 100644 (file)
--- a/src/table.c
+++ b/src/table.c
*/
#include "collectd.h"
+
#include "common.h"
-#include "configfile.h"
#include "plugin.h"
#define log_err(...) ERROR ("table plugin: " __VA_ARGS__)
*/
typedef struct {
- char *type;
- char *instance_prefix;
- int *instances;
- size_t instances_num;
- int *values;
- size_t values_num;
+ char *type;
+ char *instance_prefix;
+ size_t *instances;
+ size_t instances_num;
+ size_t *values;
+ size_t values_num;
const data_set_t *ds;
} tbl_result_t;
static void tbl_clear (tbl_t *tbl)
{
- size_t i;
-
sfree (tbl->file);
sfree (tbl->sep);
sfree (tbl->instance);
- for (i = 0; i < tbl->results_num; ++i)
+ for (size_t i = 0; i < tbl->results_num; ++i)
tbl_result_clear (tbl->results + i);
sfree (tbl->results);
tbl->results_num = 0;
return 0;
} /* tbl_config_set_separator */
-static int tbl_config_append_array_i (char *name, int **var, size_t *len,
+static int tbl_config_append_array_i (char *name, size_t **var, size_t *len,
oconfig_item_t *ci)
{
- int *tmp;
-
- size_t i;
+ size_t *tmp;
+ size_t num;
if (1 > ci->values_num) {
log_err ("\"%s\" expects at least one argument.", name);
return 1;
}
- for (i = 0; i < ci->values_num; ++i) {
+ num = (size_t) ci->values_num;
+ for (size_t i = 0; i < num; ++i) {
if (OCONFIG_TYPE_NUMBER != ci->values[i].type) {
log_err ("\"%s\" expects numerical arguments only.", name);
return 1;
}
}
- *len += ci->values_num;
- tmp = (int *)realloc (*var, *len * sizeof (**var));
+ tmp = realloc (*var, ((*len) + num) * sizeof (**var));
if (NULL == tmp) {
char errbuf[1024];
log_err ("realloc failed: %s.",
sstrerror (errno, errbuf, sizeof (errbuf)));
return -1;
}
-
*var = tmp;
- for (i = *len - ci->values_num; i < *len; ++i)
- (*var)[i] = (int)ci->values[i].value.number;
+ for (size_t i = 0; i < num; ++i) {
+ (*var)[*len] = (size_t) ci->values[i].value.number;
+ (*len)++;
+ }
+
return 0;
} /* tbl_config_append_array_s */
tbl_result_t *res;
int status = 0;
- size_t i;
if (0 != ci->values_num) {
log_err ("<Result> does not expect any arguments.");
return 1;
}
- res = (tbl_result_t *)realloc (tbl->results,
+ res = realloc (tbl->results,
(tbl->results_num + 1) * sizeof (*tbl->results));
if (res == NULL) {
char errbuf[1024];
res = tbl->results + tbl->results_num - 1;
tbl_result_setup (res);
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
if (0 == strcasecmp (c->key, "Type"))
tbl_t *tbl;
int status = 0;
- size_t i;
if ((1 != ci->values_num)
|| (OCONFIG_TYPE_STRING != ci->values[0].type)) {
return 1;
}
- tbl = (tbl_t *)realloc (tables, (tables_num + 1) * sizeof (*tables));
+ tbl = realloc (tables, (tables_num + 1) * sizeof (*tables));
if (NULL == tbl) {
char errbuf[1024];
log_err ("realloc failed: %s.",
tbl = tables + tables_num - 1;
tbl_setup (tbl, ci->values[0].value.string);
- for (i = 0; i < ci->children_num; ++i) {
+ for (size_t i = 0; i < ((size_t) ci->children_num); ++i) {
oconfig_item_t *c = ci->children + i;
if (0 == strcasecmp (c->key, "Separator"))
return status;
}
- for (i = 0; i < tbl->results_num; ++i) {
+ for (size_t i = 0; i < tbl->results_num; ++i) {
tbl_result_t *res = tbl->results + i;
- size_t j;
- for (j = 0; j < res->instances_num; ++j)
+ for (size_t j = 0; j < res->instances_num; ++j)
if (res->instances[j] > tbl->max_colnum)
tbl->max_colnum = res->instances[j];
- for (j = 0; j < res->values_num; ++j)
+ for (size_t j = 0; j < res->values_num; ++j)
if (res->values[j] > tbl->max_colnum)
tbl->max_colnum = res->values[j];
}
static int tbl_config (oconfig_item_t *ci)
{
- size_t i;
-
- for (i = 0; i < ci->children_num; ++i) {
+ for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
if (0 == strcasecmp (c->key, "Table"))
static int tbl_prepare (tbl_t *tbl)
{
- size_t i;
-
- for (i = 0; i < tbl->results_num; ++i) {
+ for (size_t i = 0; i < tbl->results_num; ++i) {
tbl_result_t *res = tbl->results + i;
res->ds = plugin_get_ds (res->type);
return -1;
}
- if (res->values_num != (size_t)res->ds->ds_num) {
+ if (res->values_num != res->ds->ds_num) {
log_err ("Invalid type \"%s\". Expected %zu data source%s, "
- "got %i.", res->type, res->values_num,
+ "got %zu.", res->type, res->values_num,
(1 == res->values_num) ? "" : "s",
res->ds->ds_num);
return -1;
static int tbl_finish (tbl_t *tbl)
{
- size_t i;
-
- for (i = 0; i < tbl->results_num; ++i)
+ for (size_t i = 0; i < tbl->results_num; ++i)
tbl->results[i].ds = NULL;
return 0;
} /* tbl_finish */
value_list_t vl = VALUE_LIST_INIT;
value_t values[res->values_num];
- size_t i;
-
assert (NULL != res->ds);
assert (res->values_num == res->ds->ds_num);
- for (i = 0; i < res->values_num; ++i) {
+ for (size_t i = 0; i < res->values_num; ++i) {
char *value;
assert (res->values[i] < fields_num);
char *instances[res->instances_num];
char instances_str[DATA_MAX_NAME_LEN];
- for (i = 0; i < res->instances_num; ++i) {
+ for (size_t i = 0; i < res->instances_num; ++i) {
assert (res->instances[i] < fields_num);
instances[i] = fields[res->instances[i]];
}
char *fields[tbl->max_colnum + 1];
char *ptr, *saveptr;
- size_t i;
+ size_t i = 0;
- i = 0;
ptr = line;
saveptr = NULL;
while (NULL != (fields[i] = strtok_r (ptr, tbl->sep, &saveptr))) {
}
if (i <= tbl->max_colnum) {
- log_err ("Not enough columns in line "
+ log_warn ("Not enough columns in line "
"(expected at least %zu, got %zu).",
tbl->max_colnum + 1, i);
return -1;
while (NULL != fgets (buf, sizeof (buf), fh)) {
if ('\0' != buf[sizeof (buf) - 1]) {
buf[sizeof (buf) - 1] = '\0';
- log_err ("Table %s: Truncated line: %s", tbl->file, buf);
+ log_warn ("Table %s: Truncated line: %s", tbl->file, buf);
}
if (0 != tbl_parse_line (tbl, buf, sizeof (buf))) {
- log_err ("Table %s: Failed to parse line: %s", tbl->file, buf);
+ log_warn ("Table %s: Failed to parse line: %s", tbl->file, buf);
continue;
}
}
static int tbl_read (void)
{
int status = -1;
- size_t i;
if (0 == tables_num)
return 0;
- for (i = 0; i < tables_num; ++i) {
+ for (size_t i = 0; i < tables_num; ++i) {
tbl_t *tbl = tables + i;
if (0 != tbl_prepare (tbl)) {
static int tbl_shutdown (void)
{
- size_t i;
-
- for (i = 0; i < tables_num; ++i)
+ for (size_t i = 0; i < tables_num; ++i)
tbl_clear (&tables[i]);
sfree (tables);
return 0;
diff --git a/src/tail.c b/src/tail.c
index 708cd2a32737e0a10678bc7d650c48c4c6029ba8..e8cde1edcd21a3cf27a1e9a8dea4ba9f7588e728 100644 (file)
--- a/src/tail.c
+++ b/src/tail.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_tail_match.h"
};
typedef struct ctail_config_match_s ctail_config_match_t;
-cu_tail_match_t **tail_match_list = NULL;
-size_t tail_match_list_num = 0;
-cdtime_t tail_match_list_intervals[255];
+static cu_tail_match_t **tail_match_list = NULL;
+static size_t tail_match_list_num = 0;
+static cdtime_t tail_match_list_intervals[255];
static int ctail_config_add_match_dstype (ctail_config_match_t *cm,
oconfig_item_t *ci)
static int ctail_config_add_match (cu_tail_match_t *tm,
const char *plugin_instance, oconfig_item_t *ci, cdtime_t interval)
{
- ctail_config_match_t cm;
+ ctail_config_match_t cm = { 0 };
int status;
- int i;
-
- memset (&cm, '\0', sizeof (cm));
if (ci->values_num != 0)
{
}
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
cdtime_t interval = 0;
char *plugin_instance = NULL;
int num_matches = 0;
- int i;
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
{
return (-1);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
int status = 0;
{
cu_tail_match_t **temp;
- temp = (cu_tail_match_t **) realloc (tail_match_list,
+ temp = realloc (tail_match_list,
sizeof (cu_tail_match_t *) * (tail_match_list_num + 1));
if (temp == NULL)
{
static int ctail_config (oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
static int ctail_init (void)
{
- struct timespec cb_interval;
char str[255];
- user_data_t ud;
- size_t i;
if (tail_match_list_num == 0)
{
return (-1);
}
- memset(&ud, '\0', sizeof(ud));
-
- for (i = 0; i < tail_match_list_num; i++)
+ for (size_t i = 0; i < tail_match_list_num; i++)
{
- ud.data = (void *)tail_match_list[i];
ssnprintf(str, sizeof(str), "tail-%zu", i);
- CDTIME_T_TO_TIMESPEC (tail_match_list_intervals[i], &cb_interval);
- plugin_register_complex_read (NULL, str, ctail_read, &cb_interval, &ud);
+
+ user_data_t ud = {
+ .data = tail_match_list[i]
+ };
+
+ plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], &ud);
}
return (0);
static int ctail_shutdown (void)
{
- size_t i;
-
- for (i = 0; i < tail_match_list_num; i++)
+ for (size_t i = 0; i < tail_match_list_num; i++)
{
tail_match_destroy (tail_match_list[i]);
tail_match_list[i] = NULL;
diff --git a/src/tail_csv.c b/src/tail_csv.c
index 919f94821498a2dc3823882211c720fb943b2130..206f1037fba03aef9c9af748b6122c10ce8cdb2e 100644 (file)
--- a/src/tail_csv.c
+++ b/src/tail_csv.c
**/
#include "collectd.h"
+
#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
#include "common.h" /* auxiliary functions */
#include "utils_tail.h"
#include <string.h>
struct metric_definition_s {
- char *name;
- char *type;
- char *instance;
- int data_source_type;
- int value_from;
+ char *name;
+ char *type;
+ char *instance;
+ int data_source_type;
+ ssize_t value_from;
struct metric_definition_s *next;
};
typedef struct metric_definition_s metric_definition_t;
struct instance_definition_s {
- char *instance;
- char *path;
- cu_tail_t *tail;
+ char *instance;
+ char *path;
+ cu_tail_t *tail;
metric_definition_t **metric_list;
- size_t metric_list_len;
- cdtime_t interval;
- int time_from;
+ size_t metric_list_len;
+ cdtime_t interval;
+ ssize_t time_from;
struct instance_definition_s *next;
};
typedef struct instance_definition_s instance_definition_t;
static cdtime_t parse_time (char const *tbuf)
{
double t;
- char *endptr = 0;
+ char *endptr = NULL;
errno = 0;
t = strtod (tbuf, &endptr);
char **fields, size_t fields_num)
{
value_t v;
- cdtime_t t;
+ cdtime_t t = 0;
int status;
if (md->data_source_type == -1)
return (EINVAL);
- if (md->value_from >= fields_num)
- return (EINVAL);
-
- if (id->time_from >= 0 && (id->time_from >= fields_num))
+ assert (md->value_from >= 0);
+ if (((size_t) md->value_from) >= fields_num)
return (EINVAL);
- t = 0;
- if (id->time_from >= 0)
- t = parse_time (fields[id->time_from]);
-
status = parse_value (fields[md->value_from], &v, md->data_source_type);
if (status != 0)
return (status);
+ if (id->time_from >= 0) {
+ if (((size_t) id->time_from) >= fields_num)
+ return (EINVAL);
+ t = parse_time (fields[id->time_from]);
+ }
+
return (tcsv_submit (id, md, v, t));
}
-static _Bool tcsv_check_index (int index, size_t fields_num, char const *name)
+static _Bool tcsv_check_index (ssize_t index, size_t fields_num, char const *name)
{
if (index < 0)
return 1;
else if (((size_t) index) < fields_num)
return 1;
- ERROR ("tail_csv plugin: Metric \"%s\": Request for index %i when "
+ ERROR ("tail_csv plugin: Metric \"%s\": Request for index %zd when "
"only %zu fields are available.",
name, index, fields_num);
return (0);
tcsv_metric_definition_destroy (next);
}
-static int tcsv_config_get_index(oconfig_item_t *ci, int *ret_index) {
- int index;
-
+static int tcsv_config_get_index(oconfig_item_t *ci, ssize_t *ret_index) {
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)){
WARNING("tail_csv plugin: The \"%s\" config option needs exactly one "
"integer argument.", ci->key);
return (-1);
}
- index = (int) ci->values[0].value.number;
- if (index < 0) {
+ if (ci->values[0].value.number < 0) {
WARNING("tail_csv plugin: The \"%s\" config option must be positive "
"(or zero).", ci->key);
return (-1);
}
- *ret_index = index;
+ *ret_index = (ssize_t) ci->values[0].value.number;
return (0);
}
/* Parse metric */
static int tcsv_config_add_metric(oconfig_item_t *ci){
metric_definition_t *md;
- int status = 0;
- int i;
+ int status;
- md = (metric_definition_t *)malloc(sizeof(*md));
+ md = calloc(1, sizeof(*md));
if (md == NULL)
return (-1);
- memset(md, 0, sizeof(*md));
md->name = NULL;
md->type = NULL;
md->instance = NULL;
return (-1);
}
- for (i = 0; i < ci->children_num; ++i){
+ for (int i = 0; i < ci->children_num; ++i){
oconfig_item_t *option = ci->children + i;
if (strcasecmp("Type", option->key) == 0)
@@ -380,7 +376,6 @@ static int tcsv_config_add_instance_collect(instance_definition_t *id, oconfig_i
metric_definition_t *metric;
metric_definition_t **metric_list;
size_t metric_list_size;
- int i;
if (ci->values_num < 1) {
WARNING("tail_csv plugin: The `Collect' config option needs at least one argument.");
@@ -393,7 +388,7 @@ static int tcsv_config_add_instance_collect(instance_definition_t *id, oconfig_i
return (-1);
id->metric_list = metric_list;
- for (i = 0; i < ci->values_num; i++) {
+ for (int i = 0; i < ci->values_num; i++) {
char *metric_name;
if (ci->values[i].type != OCONFIG_TYPE_STRING) {
{
instance_definition_t* id;
int status = 0;
- int i;
/* Registration variables */
char cb_name[DATA_MAX_NAME_LEN];
- user_data_t cb_data;
- struct timespec cb_interval;
- id = malloc(sizeof(*id));
+ id = calloc(1, sizeof(*id));
if (id == NULL)
return (-1);
- memset(id, 0, sizeof(*id));
id->instance = NULL;
id->path = NULL;
id->metric_list = NULL;
/* Use default interval. */
id->interval = plugin_get_interval();
- for (i = 0; i < ci->children_num; ++i){
+ for (int i = 0; i < ci->children_num; ++i){
oconfig_item_t *option = ci->children + i;
status = 0;
}
ssnprintf (cb_name, sizeof (cb_name), "tail_csv/%s", id->path);
- memset(&cb_data, 0, sizeof(cb_data));
- cb_data.data = id;
- cb_data.free_func = tcsv_instance_definition_destroy;
- CDTIME_T_TO_TIMESPEC(id->interval, &cb_interval);
- status = plugin_register_complex_read(NULL, cb_name, tcsv_read, &cb_interval, &cb_data);
+
+ user_data_t ud = {
+ .data = id,
+ .free_func = tcsv_instance_definition_destroy
+ };
+
+ status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &ud);
if (status != 0){
ERROR("tail_csv plugin: Registering complex read function failed.");
/* Parse blocks */
static int tcsv_config(oconfig_item_t *ci){
- int i;
- for (i = 0; i < ci->children_num; ++i){
+ for (int i = 0; i < ci->children_num; ++i){
oconfig_item_t *child = ci->children + i;
if (strcasecmp("Metric", child->key) == 0)
tcsv_config_add_metric(child);
}
else if (ds->ds_num != 1)
{
- ERROR ("tail_csv plugin: The type \"%s\" has %i data sources. "
+ ERROR ("tail_csv plugin: The type \"%s\" has %zu data sources. "
"Only types with a single data source are supported.",
ds->type, ds->ds_num);
continue;
diff --git a/src/tape.c b/src/tape.c
index a8e7dc45faab08bdf18ffd42fbebd242f3f3477f..52da2bc69db465a6e99bf97e529f43c56a0cd5c8 100644 (file)
--- a/src/tape.c
+++ b/src/tape.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
# error "kstat_io_t does not have the required members"
#endif
static kstat_io_t kio;
- int i;
if (kc == NULL)
return (-1);
if (numtape <= 0)
return (-1);
- for (i = 0; i < numtape; i++)
+ for (int i = 0; i < numtape; i++)
{
if (kstat_read (kc, ksp[i], &kio) == -1)
continue;
index ceb454ecba7bb6e8579e27044468c876310437e0..21c071ed422f36d625f44366ace457add857f46e 100644 (file)
**/
#include "collectd.h"
+
#include "common.h"
#include "filter_chain.h"
#include "utils_cache.h"
{
tn_data_t *data;
int status;
- int i;
- data = (tn_data_t *) malloc (sizeof (*data));
+ data = calloc (1, sizeof (*data));
if (data == NULL)
{
- ERROR ("tn_create: malloc failed.");
+ ERROR ("tn_create: calloc failed.");
return (-ENOMEM);
}
- memset (data, 0, sizeof (*data));
data->message = NULL;
data->severity = 0;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
notification_meta_t __attribute__((unused)) **meta, void **user_data)
{
tn_data_t *data;
- notification_t n;
+ notification_t n = { 0 };
char temp[NOTIF_MAX_MSG_LEN];
gauge_t *rates;
int rates_failed;
- int i;
-
if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
return (-EINVAL);
}
/* Initialize the structure. */
- memset (&n, 0, sizeof (n));
n.severity = data->severity;
n.time = cdtime ();
sstrncpy (n.message, data->message, sizeof (n.message));
rates_failed = 0;
rates = NULL;
- for (i = 0; i < ds->ds_num; i++)
+
+ for (size_t i = 0; i < ds->ds_num; i++)
{
char template[DATA_MAX_NAME_LEN];
char value_str[DATA_MAX_NAME_LEN];
void module_register (void)
{
- target_proc_t tproc;
+ target_proc_t tproc = { 0 };
- memset (&tproc, 0, sizeof (tproc));
tproc.create = tn_create;
tproc.destroy = tn_destroy;
tproc.invoke = tn_invoke;
diff --git a/src/target_replace.c b/src/target_replace.c
index a85eced33532a75b7e81732ec7755ded9d2c1f66..40a6fec992687466720d11abea95778fb5984aa2 100644 (file)
--- a/src/target_replace.c
+++ b/src/target_replace.c
**/
#include "collectd.h"
+
#include "common.h"
#include "filter_chain.h"
#include "utils_subst.h"
return (NULL);
sz = strlen (orig) + 1;
- dest = (char *) malloc (sz);
+ dest = malloc (sz);
if (dest == NULL)
return (NULL);
return (-1);
}
- act = (tr_action_t *) malloc (sizeof (*act));
+ act = calloc (1, sizeof (*act));
if (act == NULL)
{
- ERROR ("tr_config_add_action: malloc failed.");
+ ERROR ("tr_config_add_action: calloc failed.");
return (-ENOMEM);
}
- memset (act, 0, sizeof (*act));
act->replacement = NULL;
act->may_be_empty = may_be_empty;
static int tr_action_invoke (tr_action_t *act_head, /* {{{ */
char *buffer_in, size_t buffer_in_size, int may_be_empty)
{
- tr_action_t *act;
int status;
char buffer[DATA_MAX_NAME_LEN];
- regmatch_t matches[8];
+ regmatch_t matches[8] = { [0] = { 0 } };
if (act_head == NULL)
return (-EINVAL);
sstrncpy (buffer, buffer_in, sizeof (buffer));
- memset (matches, 0, sizeof (matches));
DEBUG ("target_replace plugin: tr_action_invoke: <- buffer = %s;", buffer);
- for (act = act_head; act != NULL; act = act->next)
+ for (tr_action_t *act = act_head; act != NULL; act = act->next)
{
char temp[DATA_MAX_NAME_LEN];
char *subst_status;
}
subst_status = subst (temp, sizeof (temp), buffer,
- matches[0].rm_so, matches[0].rm_eo, act->replacement);
+ (size_t) matches[0].rm_so, (size_t) matches[0].rm_eo, act->replacement);
if (subst_status == NULL)
{
ERROR ("Target `replace': subst (buffer = %s, start = %zu, end = %zu, "
{
tr_data_t *data;
int status;
- int i;
- data = (tr_data_t *) malloc (sizeof (*data));
+ data = calloc (1, sizeof (*data));
if (data == NULL)
{
- ERROR ("tr_create: malloc failed.");
+ ERROR ("tr_create: calloc failed.");
return (-ENOMEM);
}
- memset (data, 0, sizeof (*data));
data->host = NULL;
data->plugin = NULL;
data->type_instance = NULL;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
void module_register (void)
{
- target_proc_t tproc;
+ target_proc_t tproc = { 0 };
- memset (&tproc, 0, sizeof (tproc));
tproc.create = tr_create;
tproc.destroy = tr_destroy;
tproc.invoke = tr_invoke;
diff --git a/src/target_scale.c b/src/target_scale.c
index b29a02bfa64801d9e967294ba4d1af7e6ce0cb48..22af4e319d60af7db98e0a86790b3438dfe640b3 100644 (file)
--- a/src/target_scale.c
+++ b/src/target_scale.c
**/
#include "collectd.h"
+
#include "common.h"
#include "filter_chain.h"
if (failure == 0)
{
- uint64_t difference;
+ uint64_t diff;
double rate;
- /* Calcualte the rate */
- if (prev_counter > curr_counter) /* => counter overflow */
- {
- if (prev_counter <= 4294967295UL) /* 32 bit overflow */
- difference = (4294967295UL - prev_counter) + curr_counter;
- else /* 64 bit overflow */
- difference = (18446744073709551615ULL - prev_counter) + curr_counter;
- }
- else /* no overflow */
- {
- difference = curr_counter - prev_counter;
- }
- rate = ((double) difference) / CDTIME_T_TO_DOUBLE (vl->interval);
+ diff = (uint64_t) counter_diff (prev_counter, curr_counter);
+ rate = ((double) diff) / CDTIME_T_TO_DOUBLE (vl->interval);
/* Modify the rate. */
if (!isnan (data->factor))
/* Calculate the internal counter. */
int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval));
- difference = (uint64_t) int_fraction;
- int_fraction -= ((double) difference);
- int_counter += difference;
+ diff = (uint64_t) int_fraction;
+ int_fraction -= ((double) diff);
+ int_counter += diff;
assert (int_fraction >= 0.0);
assert (int_fraction < 1.0);
{
size_t new_data_sources_num;
char **temp;
- int i;
/* Check number of arbuments. */
if (ci->values_num < 1)
}
/* Check type of arguments */
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
if (ci->values[i].type == OCONFIG_TYPE_STRING)
continue;
/* Allocate space for the char pointers */
new_data_sources_num = data->data_sources_num + ((size_t) ci->values_num);
- temp = (char **) realloc (data->data_sources,
+ temp = realloc (data->data_sources,
new_data_sources_num * sizeof (char *));
if (temp == NULL)
{
data->data_sources = temp;
/* Copy the strings, allocating memory as needed. */
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
size_t j;
if ((data != NULL) && (data->data_sources != NULL))
{
- size_t i;
- for (i = 0; i < data->data_sources_num; i++)
+ for (size_t i = 0; i < data->data_sources_num; i++)
sfree (data->data_sources[i]);
sfree (data->data_sources);
}
{
ts_data_t *data;
int status;
- int i;
- data = (ts_data_t *) malloc (sizeof (*data));
+ data = calloc (1, sizeof (*data));
if (data == NULL)
{
- ERROR ("ts_create: malloc failed.");
+ ERROR ("ts_create: calloc failed.");
return (-ENOMEM);
}
- memset (data, 0, sizeof (*data));
data->factor = NAN;
data->offset = NAN;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
notification_meta_t __attribute__((unused)) **meta, void **user_data)
{
ts_data_t *data;
- int i;
if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
return (-EINVAL);
return (-EINVAL);
}
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
/* If we've got a list of data sources, is it in the list? */
if (data->data_sources) {
void module_register (void)
{
- target_proc_t tproc;
+ target_proc_t tproc = { 0 };
- memset (&tproc, 0, sizeof (tproc));
tproc.create = ts_create;
tproc.destroy = ts_destroy;
tproc.invoke = ts_invoke;
diff --git a/src/target_set.c b/src/target_set.c
index daeaf8be62f7c2d9779b66f2643dd0e447ac6bd5..4f00cbbdaf1aedbc2bf6eedbdf60a003e826e9b5 100644 (file)
--- a/src/target_set.c
+++ b/src/target_set.c
**/
#include "collectd.h"
+
#include "common.h"
#include "filter_chain.h"
char *plugin_instance;
/* char *type; */
char *type_instance;
+ meta_data_t *meta;
};
typedef struct ts_data_s ts_data_t;
+static int ts_util_get_key_and_string_wo_strdup (const oconfig_item_t *ci, char **ret_key, char **ret_string) /* {{{ */
+{
+ if ((ci->values_num != 2)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING)
+ || (ci->values[1].type != OCONFIG_TYPE_STRING))
+ {
+ ERROR ("ts_util_get_key_and_string_wo_strdup: The %s option requires "
+ "exactly two string argument.", ci->key);
+ return (-1);
+ }
+
+ *ret_key = ci->values[0].value.string;
+ *ret_string = ci->values[1].value.string;
+
+ return (0);
+} /* }}} int ts_util_get_key_and_string_wo_strdup */
+
static int ts_config_add_string (char **dest, /* {{{ */
const oconfig_item_t *ci, int may_be_empty)
{
return (0);
} /* }}} int ts_config_add_string */
+static int ts_config_add_meta (meta_data_t **dest, /* {{{ */
+ const oconfig_item_t *ci, int may_be_empty)
+{
+ char *key = NULL;
+ char *string = NULL;
+ int status;
+
+ status = ts_util_get_key_and_string_wo_strdup (ci, &key, &string);
+ if (status != 0)
+ return (status);
+
+ if (strlen (key) == 0)
+ {
+ ERROR ("Target `set': The `%s' option does not accept empty string as first argument.",
+ ci->key);
+ return (-1);
+ }
+
+ if (!may_be_empty && (strlen (string) == 0))
+ {
+ ERROR ("Target `set': The `%s' option does not accept empty string as second argument.",
+ ci->key);
+ return (-1);
+ }
+
+ if ((*dest) == NULL)
+ {
+ // Create a new meta_data_t
+ if ((*dest = meta_data_create()) == NULL)
+ {
+ ERROR ("Target `set': failed to create a meta data for `%s'.", ci->key);
+ return (-1);
+ }
+ }
+
+ return (meta_data_add_string (*dest, key, string));
+} /* }}} int ts_config_add_meta */
+
static int ts_destroy (void **user_data) /* {{{ */
{
ts_data_t *data;
free (data->plugin_instance);
/* free (data->type); */
free (data->type_instance);
+ meta_data_destroy(data->meta);
free (data);
return (0);
{
ts_data_t *data;
int status;
- int i;
- data = (ts_data_t *) malloc (sizeof (*data));
+ data = calloc (1, sizeof (*data));
if (data == NULL)
{
- ERROR ("ts_create: malloc failed.");
+ ERROR ("ts_create: calloc failed.");
return (-ENOMEM);
}
- memset (data, 0, sizeof (*data));
data->host = NULL;
data->plugin = NULL;
data->plugin_instance = NULL;
/* data->type = NULL; */
data->type_instance = NULL;
+ data->meta = NULL;
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
else if (strcasecmp ("TypeInstance", child->key) == 0)
status = ts_config_add_string (&data->type_instance, child,
/* may be empty = */ 1);
+ else if (strcasecmp ("MetaData", child->key) == 0)
+ status = ts_config_add_meta (&data->meta, child,
+ /* may be empty = */ 1);
else
{
ERROR ("Target `set': The `%s' configuration option is not understood "
&& (data->plugin == NULL)
&& (data->plugin_instance == NULL)
/* && (data->type == NULL) */
- && (data->type_instance == NULL))
+ && (data->type_instance == NULL)
+ && (data->meta == NULL))
{
ERROR ("Target `set': You need to set at least one of `Host', "
- "`Plugin', `PluginInstance' or `TypeInstance'.");
+ "`Plugin', `PluginInstance', `TypeInstance', `MetaData'.");
status = -1;
}
return (-EINVAL);
}
+ if (data->meta != NULL)
+ {
+ meta_data_clone_merge(&(vl->meta), data->meta);
+ }
+
#define SET_FIELD(f) if (data->f != NULL) { sstrncpy (vl->f, data->f, sizeof (vl->f)); }
SET_FIELD (host);
SET_FIELD (plugin);
void module_register (void)
{
- target_proc_t tproc;
+ target_proc_t tproc = { 0 };
- memset (&tproc, 0, sizeof (tproc));
tproc.create = ts_create;
tproc.destroy = ts_destroy;
tproc.invoke = ts_invoke;
diff --git a/src/target_v5upgrade.c b/src/target_v5upgrade.c
index d85a181fb933d9fbdda91c8c366539834fbf8586..f7baa3aee468ce5e1a5cac6f29ea7f2a8ee8ecc9 100644 (file)
--- a/src/target_v5upgrade.c
+++ b/src/target_v5upgrade.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include "filter_chain.h"
void module_register (void)
{
- target_proc_t tproc;
+ target_proc_t tproc = { 0 };
- memset (&tproc, 0, sizeof (tproc));
tproc.create = v5_create;
tproc.destroy = v5_destroy;
tproc.invoke = v5_invoke;
diff --git a/src/tcpconns.c b/src/tcpconns.c
index 5d4bb6966f98b024e57ffc7fd0956082777212ab..e74e4bc8856d6360472a44d52a7dae93a3586ca2 100644 (file)
--- a/src/tcpconns.c
+++ b/src/tcpconns.c
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#if KERNEL_LINUX
# include <asm/types.h>
-/* sys/socket.h is necessary to compile when using netlink on older systems. */
-# include <sys/socket.h>
# include <linux/netlink.h>
#if HAVE_LINUX_INET_DIAG_H
# include <linux/inet_diag.h>
#endif
-# include <sys/socket.h>
# include <arpa/inet.h>
/* #endif KERNEL_LINUX */
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#if HAVE_NET_IF_H
# include <net/if.h>
#endif
/* This is for OpenBSD and 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>
static uint32_t sequence_number = 0;
#endif
-enum
+static enum
{
SRC_DUNNO,
SRC_NETLINK,
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- int i;
conn_prepare_vl (&vl, values);
ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
"%"PRIu16"-local", pe->port);
- for (i = 1; i <= TCP_STATE_MAX; i++)
+ for (int i = 1; i <= TCP_STATE_MAX; i++)
{
vl.values[0].gauge = pe->count_local[i];
ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
"%"PRIu16"-remote", pe->port);
- for (i = 1; i <= TCP_STATE_MAX; i++)
+ for (int i = 1; i <= TCP_STATE_MAX; i++)
{
vl.values[0].gauge = pe->count_remote[i];
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- int i;
conn_prepare_vl (&vl, values);
sstrncpy (vl.plugin_instance, "all", sizeof (vl.plugin_instance));
- for (i = 1; i <= TCP_STATE_MAX; i++)
+ for (int i = 1; i <= TCP_STATE_MAX; i++)
{
vl.values[0].gauge = count_total[i];
static void conn_submit_all (void)
{
- port_entry_t *pe;
-
if (port_collect_total)
conn_submit_port_total ();
- for (pe = port_list_head; pe != NULL; pe = pe->next)
+ for (port_entry_t *pe = port_list_head; pe != NULL; pe = pe->next)
conn_submit_port_entry (pe);
} /* void conn_submit_all */
if ((ret == NULL) && (create != 0))
{
- ret = (port_entry_t *) malloc (sizeof (port_entry_t));
+ ret = calloc (1, sizeof (*ret));
if (ret == NULL)
return (NULL);
- memset (ret, '\0', sizeof (port_entry_t));
ret->port = port;
ret->next = port_list_head;
{
#if HAVE_STRUCT_LINUX_INET_DIAG_REQ
int fd;
- struct sockaddr_nl nladdr;
- struct nlreq req;
- struct msghdr msg;
- struct iovec iov;
struct inet_diag_msg *r;
char buf[8192];
return (-1);
}
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
-
- memset(&req, 0, sizeof(req));
- req.nlh.nlmsg_len = sizeof(req);
- req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
- /* NLM_F_ROOT: return the complete table instead of a single entry.
- * NLM_F_MATCH: return all entries matching criteria (not implemented)
- * NLM_F_REQUEST: must be set on all request messages */
- req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
- req.nlh.nlmsg_pid = 0;
- /* The sequence_number is used to track our messages. Since netlink is not
- * reliable, we don't want to end up with a corrupt or incomplete old
- * message in case the system is/was out of memory. */
- req.nlh.nlmsg_seq = ++sequence_number;
- req.r.idiag_family = AF_INET;
- req.r.idiag_states = 0xfff;
- req.r.idiag_ext = 0;
-
- memset(&iov, 0, sizeof(iov));
- iov.iov_base = &req;
- iov.iov_len = sizeof(req);
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_name = (void*)&nladdr;
- msg.msg_namelen = sizeof(nladdr);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
+ struct sockaddr_nl nladdr = {
+ .nl_family = AF_NETLINK
+ };
+
+ struct nlreq req = {
+ .nlh.nlmsg_len = sizeof(req),
+ .nlh.nlmsg_type = TCPDIAG_GETSOCK,
+ /* NLM_F_ROOT: return the complete table instead of a single entry.
+ * NLM_F_MATCH: return all entries matching criteria (not implemented)
+ * NLM_F_REQUEST: must be set on all request messages */
+ .nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST,
+ .nlh.nlmsg_pid = 0,
+ /* The sequence_number is used to track our messages. Since netlink is not
+ * reliable, we don't want to end up with a corrupt or incomplete old
+ * message in case the system is/was out of memory. */
+ .nlh.nlmsg_seq = ++sequence_number,
+ .r.idiag_family = AF_INET,
+ .r.idiag_states = 0xfff,
+ .r.idiag_ext = 0
+ };
+
+ struct iovec iov = {
+ .iov_base = &req,
+ .iov_len = sizeof(req)
+ };
+
+ struct msghdr msg = {
+ .msg_name = (void*)&nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1
+ };
if (sendmsg (fd, &msg, 0) < 0)
{
return (-1);
}
- buffer = (char *) malloc (buffer_len);
+ buffer = malloc (buffer_len);
if (buffer == NULL)
{
ERROR ("tcpconns plugin: malloc failed.");
static int conn_read (void)
{
int size;
- int i;
int nconn;
void *data;
struct netinfo_header *header;
nconn = header->size;
conn = (struct netinfo_conn *)(data + sizeof(struct netinfo_header));
- for (i=0; i < nconn; conn++, i++)
+ for (int i = 0; i < nconn; conn++, i++)
{
conn_handle_ports (conn->srcport, conn->dstport, conn->tcp_state);
}
diff --git a/src/teamspeak2.c b/src/teamspeak2.c
index 0e683ce9fc42cb17a3f18802904f90df94bc4bfd..a1cde320dd2cb3e9a83f9910da40beb31eefbb43 100644 (file)
--- a/src/teamspeak2.c
+++ b/src/teamspeak2.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
-#include <sys/socket.h>
#include <netdb.h>
/*
}
/* Allocate memory */
- entry = (vserver_list_t *) malloc (sizeof (vserver_list_t));
+ entry = calloc (1, sizeof (*entry));
if (entry == NULL)
{
- ERROR ("teamspeak2 plugin: malloc failed.");
+ ERROR ("teamspeak2 plugin: calloc failed.");
return (-1);
}
- memset (entry, 0, sizeof (vserver_list_t));
/* Save data */
entry->port = vserver_port;
if (type_instance != NULL)
sstrncpy (vl.type_instance, type_instance,
sizeof (vl.type_instance));
-
+
plugin_dispatch_values (&vl);
} /* void tss2_submit_gauge */
* Returns connected file objects or establishes the connection
* if it's not already present
*/
- struct addrinfo ai_hints;
struct addrinfo *ai_head;
- struct addrinfo *ai_ptr;
int sd = -1;
int status;
}
/* Get all addrs for this hostname */
- memset (&ai_hints, 0, sizeof (ai_hints));
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_STREAM;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_socktype = SOCK_STREAM
+ };
status = getaddrinfo ((config_host != NULL) ? config_host : DEFAULT_HOST,
(config_port != NULL) ? config_port : DEFAULT_PORT,
}
/* Try all given hosts until we can connect to one */
- for (ai_ptr = ai_head; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_head; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
/* Create socket */
sd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
* Receive a single line from the given file object
*/
char *temp;
-
+
/*
* fgets is blocking but much easier then doing anything else
* TODO: Non-blocking Version would be safer
char buffer[4096];
char *value;
char *endptr = NULL;
-
+
status = tss2_receive_line (read_fh, buffer, sizeof (buffer));
if (status != 0)
{
return (-1);
}
buffer[sizeof (buffer) - 1] = 0;
-
+
if (strncmp ("average_packet_loss=", buffer,
strlen ("average_packet_loss=")) == 0)
{
}
value++;
}
-
+
value = &buffer[20];
-
+
packet_loss = strtod (value, &endptr);
if (value == endptr)
{
buffer);
}
}
-
+
*ret_value = packet_loss;
return (0);
} /* int tss2_vserver_gapl */
gauge_t packet_loss = NAN;
int valid = 0;
- char plugin_instance[DATA_MAX_NAME_LEN];
+ char plugin_instance[DATA_MAX_NAME_LEN] = { 0 };
FILE *read_fh;
FILE *write_fh;
if (vserver == NULL)
{
/* Request global information */
- memset (plugin_instance, 0, sizeof (plugin_instance));
-
status = tss2_send_request (write_fh, "gi\r\n");
}
else
char *key;
char *value;
char *endptr = NULL;
-
+
/* Read one line of the server's answer */
status = tss2_receive_line (read_fh, buffer, sizeof (buffer));
if (status != 0)
/*
* Interpret configuration values
*/
- if (strcasecmp ("Host", key) == 0)
+ if (strcasecmp ("Host", key) == 0)
{
char *temp;
{
/* Server variable found */
int status;
-
+
status = tss2_add_vserver (atoi (value));
if (status != 0)
return (1);
* Poll function which collects global and vserver information
* and submits it to collectd
*/
- vserver_list_t *vserver;
int success = 0;
int status;
}
/* Handle vservers */
- for (vserver = server_list; vserver != NULL; vserver = vserver->next)
+ for (vserver_list_t *vserver = server_list; vserver != NULL; vserver = vserver->next)
{
status = tss2_read_vserver (vserver);
if (status == 0)
continue;
}
}
-
+
if (success == 0)
return (-1);
- return (0);
+ return (0);
} /* int tss2_read */
static int tss2_shutdown(void)
/* Get rid of the configuration */
sfree (config_host);
sfree (config_port);
-
+
return (0);
} /* int tss2_shutdown */
diff --git a/src/ted.c b/src/ted.c
index 5dd75bc924b7bdea84f6664d89e8c85c77f33139..5ed6c278d0f985f52f1c8267027d501c370bf362 100644 (file)
--- a/src/ted.c
+++ b/src/ted.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#if HAVE_TERMIOS_H && HAVE_SYS_IOCTL_H && HAVE_MATH_H
# include <termios.h>
{
unsigned char receive_buffer[300];
unsigned char package_buffer[300];
- char pkt_request[1] = {0xAA};
+ unsigned char pkt_request[1] = {0xAA};
int package_buffer_pos;
fd_set input;
- struct timeval timeout;
+
+ /* Initialize timeout structure, set to 2 seconds */
+ struct timeval timeout = {
+ .tv_sec = 2
+ };
int end_flag;
int escape_flag;
FD_ZERO (&input);
FD_SET (fd, &input);
- /* Initialize timeout structure, set to 2 seconds */
- memset (&timeout, 0, sizeof (timeout));
- timeout.tv_sec = 2;
- timeout.tv_usec = 0;
-
/* clear out anything in the buffer */
tcflush (fd, TCIFLUSH);
while (end_flag == 0)
{
ssize_t receive_buffer_length;
- ssize_t i;
/* check for timeout or input error*/
status = select (fd + 1, &input, NULL, NULL, &timeout);
WARNING ("ted plugin: Received EOF from file descriptor.");
return (-1);
}
- else if (receive_buffer_length > sizeof (receive_buffer))
+ else if (((size_t) receive_buffer_length) > sizeof (receive_buffer))
{
ERROR ("ted plugin: read(2) returned invalid value %zi.",
receive_buffer_length);
* the beginning of the package has been found. */
escape_flag = 0;
- for (i = 0; i < receive_buffer_length; i++)
+ for (ssize_t i = 0; i < receive_buffer_length; i++)
{
/* Check if previous byte was the escape byte. */
if (escape_flag == 1)
return (0);
} /* int ted_open_device */
-static void ted_submit (char *type, double value)
+static void ted_submit (const char *type, double value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
double power;
double voltage;
int status;
- int i;
status = ted_open_device ();
if (status != 0)
power = NAN;
voltage = NAN;
- for (i = 0; i <= conf_retries; i++)
+ for (int i = 0; i <= conf_retries; i++)
{
status = ted_read_value (&power, &voltage);
if (status == 0)
diff --git a/src/testing.h b/src/testing.h
index 5df1b83a3e0f076b3a35bff53df09b021b9a0ea5..1bcc276c1a8666be6b30113addc572af02689ef5 100644 (file)
--- a/src/testing.h
+++ b/src/testing.h
/**
* collectd - src/tests/macros.h
- * Copyright (C) 2013 Florian octo Forster
+ * Copyright (C) 2013-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* Florian octo Forster <octo at collectd.org>
*/
+#ifndef TESTING_H
+#define TESTING_H 1
+
+#include <inttypes.h>
+
static int fail_count__ = 0;
static int check_count__ = 0;
-#define DEF_TEST(func) static int test_##func ()
+#ifndef DBL_PRECISION
+# define DBL_PRECISION 1e-12
+#endif
+
+#define DEF_TEST(func) static int test_##func (void)
#define RUN_TEST(func) do { \
int status; \
#define OK1(cond, text) do { \
_Bool result = (cond); \
printf ("%s %i - %s\n", result ? "ok" : "not ok", ++check_count__, text); \
+ if (!result) { return -1; } \
} while (0)
#define OK(cond) OK1(cond, #cond)
-#define STREQ(expect, actual) do { \
- if (strcmp (expect, actual) != 0) { \
- printf ("not ok %i - %s incorrect: expected \"%s\", got \"%s\"\n", \
- ++check_count__, #actual, expect, actual); \
+#define EXPECT_EQ_STR(expect, actual) do { \
+ /* Evaluate 'actual' only once. */ \
+ const char *got__ = actual; \
+ if (strcmp (expect, got__) != 0) { \
+ printf ("not ok %i - %s = \"%s\", want \"%s\"\n", \
+ ++check_count__, #actual, got__, expect); \
return (-1); \
} \
- printf ("ok %i - %s evaluates to \"%s\"\n", ++check_count__, #actual, expect); \
+ printf ("ok %i - %s = \"%s\"\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_INT(expect, actual) do { \
+ int want__ = (int) expect; \
+ int got__ = (int) actual; \
+ if (got__ != want__) { \
+ printf ("not ok %i - %s = %d, want %d\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = %d\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_UINT64(expect, actual) do { \
+ uint64_t want__ = (uint64_t) expect; \
+ uint64_t got__ = (uint64_t) actual; \
+ if (got__ != want__) { \
+ printf ("not ok %i - %s = %"PRIu64", want %"PRIu64"\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = %"PRIu64"\n", ++check_count__, #actual, got__); \
+} while (0)
+
+#define EXPECT_EQ_DOUBLE(expect, actual) do { \
+ double want__ = (double) expect; \
+ double got__ = (double) actual; \
+ if (isnan (want__) && !isnan (got__)) { \
+ printf ("not ok %i - %s = %.15g, want %.15g\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } else if (!isnan (want__) && (((want__-got__) < -DBL_PRECISION) || ((want__-got__) > DBL_PRECISION))) { \
+ printf ("not ok %i - %s = %.15g, want %.15g\n", \
+ ++check_count__, #actual, got__, want__); \
+ return (-1); \
+ } \
+ printf ("ok %i - %s = %.15g\n", ++check_count__, #actual, got__); \
} while (0)
#define CHECK_NOT_NULL(expr) do { \
status_ = (long) (expr); \
OK1(status_ == 0L, #expr); \
} while (0)
+
+#endif /* TESTING_H */
diff --git a/src/thermal.c b/src/thermal.c
index 27c92bc730c65b44c54c25bd9dc27a75c279980c..e001a62ac7f85a69259e6e5e047414ad4e8e9587 100644 (file)
--- a/src/thermal.c
+++ b/src/thermal.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_ignorelist.h"
#if !KERNEL_LINUX
"ForceUseProcfs"
};
-const char *const dirname_sysfs = "/sys/class/thermal";
-const char *const dirname_procfs = "/proc/acpi/thermal_zone";
+static const char *const dirname_sysfs = "/sys/class/thermal";
+static const char *const dirname_procfs = "/proc/acpi/thermal_zone";
static _Bool force_procfs = 0;
static ignorelist_t *device_list;
diff --git a/src/threshold.c b/src/threshold.c
index 45ee3b4d02c61b722419577ee607580dcdb4cb26..1d9bcf95ba8fcfe52a2ce0de5a1d1a5c5ce07034 100644 (file)
--- a/src/threshold.c
+++ b/src/threshold.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_avltree.h"
#include "utils_cache.h"
#include "utils_threshold.h"
-#include <assert.h>
-#include <pthread.h>
-
/*
* Threshold management
* ====================
return (-1);
}
- th_copy = (threshold_t *) malloc (sizeof (threshold_t));
+ th_copy = malloc (sizeof (*th_copy));
if (th_copy == NULL)
{
sfree (name_copy);
return (-1);
}
memcpy (th_copy, th, sizeof (threshold_t));
- th_ptr = NULL;
DEBUG ("ut_threshold_add: Adding entry `%s'", name);
static int ut_config_type (const threshold_t *th_orig, oconfig_item_t *ci)
{
- int i;
threshold_t th;
int status = 0;
th.hysteresis = 0;
th.flags = UT_FLAG_INTERESTING; /* interesting by default */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
static int ut_config_plugin (const threshold_t *th_orig, oconfig_item_t *ci)
{
- int i;
threshold_t th;
int status = 0;
memcpy (&th, th_orig, sizeof (th));
sstrncpy (th.plugin, ci->values[0].value.string, sizeof (th.plugin));
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
static int ut_config_host (const threshold_t *th_orig, oconfig_item_t *ci)
{
- int i;
threshold_t th;
int status = 0;
memcpy (&th, th_orig, sizeof (th));
sstrncpy (th.host, ci->values[0].value.string, sizeof (th.host));
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
{
gauge_t value;
gauge_t sum;
- int i;
sum = 0.0;
- for (i = 0; i < vl->values_len; i++)
+ for (size_t i = 0; i < vl->values_len; i++)
{
if (isnan (values[i]))
continue;
{ /* {{{ */
int ret = -1;
int ds_index = -1;
- int i;
gauge_t values_copy[ds->ds_num];
memcpy (values_copy, values, sizeof (values_copy));
}
/* Prepare `sum' and `num'. */
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
if (!isnan (values[i]))
{
num++;
if ((num == 0) /* All data sources are undefined. */
|| (sum == 0.0)) /* Sum is zero, cannot calculate percentage. */
{
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
values_copy[i] = NAN;
}
else /* We can actually calculate the percentage. */
{
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
values_copy[i] = 100.0 * values[i] / sum;
}
} /* if (UT_FLAG_PERCENTAGE) */
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
int status;
static int ut_config (oconfig_item_t *ci)
{ /* {{{ */
- int i;
int status = 0;
int old_size = c_avl_size (threshold_tree);
- threshold_t th;
-
if (threshold_tree == NULL)
{
- threshold_tree = c_avl_create ((void *) strcmp);
+ threshold_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
if (threshold_tree == NULL)
{
ERROR ("ut_config: c_avl_create failed.");
}
}
- memset (&th, '\0', sizeof (th));
- th.warning_min = NAN;
- th.warning_max = NAN;
- th.failure_min = NAN;
- th.failure_max = NAN;
-
- th.hits = 0;
- th.hysteresis = 0;
- th.flags = UT_FLAG_INTERESTING; /* interesting by default */
+ threshold_t th = {
+ .warning_min = NAN,
+ .warning_max = NAN,
+ .failure_min = NAN,
+ .failure_max = NAN,
+ .flags = UT_FLAG_INTERESTING /* interesting by default */
+ };
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *option = ci->children + i;
diff --git a/src/tokyotyrant.c b/src/tokyotyrant.c
index f04a5fceb3a51b9ae3b9738d505f5ee977b896f3..7c6d9129e709ee9b71a30a3a57848fc9fca56b06 100644 (file)
--- a/src/tokyotyrant.c
+++ b/src/tokyotyrant.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include "utils_cache.h"
static void tt_open_db (void)
{
- char* host = NULL;
- int port = DEFAULT_PORT;
+ const char *host;
+ int port = DEFAULT_PORT;
if (rdb != NULL)
return;
diff --git a/src/turbostat.c b/src/turbostat.c
index fc1b5dccc0dd3c4b2c2c848b1de1f9a57c95c156..2d8a08e646319b961f8ffb24f1a8654bb470c23f 100644 (file)
--- a/src/turbostat.c
+++ b/src/turbostat.c
#define _GNU_SOURCE
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_time.h"
@@ -651,11 +652,10 @@ for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_dat
struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
{
int retval;
- unsigned int pkg_no, core_no, thread_no;
- for (pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
- for (core_no = 0; core_no < topology.num_cores; ++core_no) {
- for (thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
+ for (unsigned int pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
+ for (unsigned int core_no = 0; core_no < topology.num_cores; ++core_no) {
+ for (unsigned int thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
struct thread_data *t;
struct core_data *c;
struct pkg_data *p;
@@ -691,11 +691,10 @@ for_all_cpus_delta(const struct thread_data *thread_new_base, const struct core_
const struct thread_data *thread_old_base, const struct core_data *core_old_base, const struct pkg_data *pkg_old_base)
{
int retval;
- unsigned int pkg_no, core_no, thread_no;
- for (pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
- for (core_no = 0; core_no < topology.num_cores; ++core_no) {
- for (thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
+ for (unsigned int pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
+ for (unsigned int core_no = 0; core_no < topology.num_cores; ++core_no) {
+ for (unsigned int thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
struct thread_data *t_delta;
const struct thread_data *t_old, *t_new;
struct core_data *c_delta;
static int __attribute__((warn_unused_result))
topology_probe(void)
{
- unsigned int i;
int ret;
unsigned int max_package_id, max_core_id, max_threads;
max_package_id = max_core_id = max_threads = 0;
* For online cpus
* find max_core_id, max_package_id
*/
- for (i = 0; i <= topology.max_cpu_id; ++i) {
+ for (unsigned int i = 0; i <= topology.max_cpu_id; ++i) {
unsigned int num_threads;
struct cpu_topology *cpu = &topology.cpus[i];
static int
allocate_counters(struct thread_data **threads, struct core_data **cores, struct pkg_data **packages)
{
- unsigned int i;
unsigned int total_threads, total_cores;
if ((topology.num_threads == 0)
@@ -1271,7 +1268,7 @@ allocate_counters(struct thread_data **threads, struct core_data **cores, struct
return -1;
}
- for (i = 0; i < total_threads; ++i)
+ for (unsigned int i = 0; i < total_threads; ++i)
(*threads)[i].cpu_id = topology.max_cpu_id + 1;
total_cores = topology.num_cores * topology.num_packages;
static void
initialize_counters(void)
{
- unsigned int cpu_id;
-
- for (cpu_id = 0; cpu_id <= topology.max_cpu_id; ++cpu_id) {
+ for (unsigned int cpu_id = 0; cpu_id <= topology.max_cpu_id; ++cpu_id) {
if (cpu_is_not_present(cpu_id))
continue;
init_counter(EVEN_COUNTERS, cpu_id);
CPU_FREE(cpu_present_set);
cpu_present_set = NULL;
- cpu_present_set = 0;
+ cpu_present_setsize = 0;
CPU_FREE(cpu_affinity_set);
cpu_affinity_set = NULL;
static int
check_permissions(void)
{
-#ifdef HAVE_SYS_CAPABILITY_H
- struct __user_cap_header_struct cap_header_data;
- cap_user_header_t cap_header = &cap_header_data;
- struct __user_cap_data_struct cap_data_data;
- cap_user_data_t cap_data = &cap_data_data;
- int ret = 0;
-#endif /* HAVE_SYS_CAPABILITY_H */
if (getuid() == 0) {
/* We have everything we need */
return 0;
-#ifndef HAVE_SYS_CAPABILITY_H
+#if !defined(HAVE_SYS_CAPABILITY_H) && !defined(CAP_SYS_RAWIO)
} else {
ERROR("turbostat plugin: Initialization failed: this plugin "
"requires collectd to run as root");
return -1;
}
-#else /* HAVE_SYS_CAPABILITY_H */
+#else /* HAVE_SYS_CAPABILITY_H && CAP_SYS_RAWIO */
}
- /* check for CAP_SYS_RAWIO */
- cap_header->pid = getpid();
- cap_header->version = _LINUX_CAPABILITY_VERSION;
- if (capget(cap_header, cap_data) < 0) {
- ERROR("turbostat plugin: capget failed");
- return -1;
- }
+ int ret = 0;
- if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) {
+ if (check_capability(CAP_SYS_RAWIO) != 0) {
WARNING("turbostat plugin: Collectd doesn't have the "
"CAP_SYS_RAWIO capability. If you don't want to run "
"collectd as root, try running \"setcap "
"collectd a special capability (CAP_SYS_RAWIO) and read "
"access to /dev/cpu/*/msr (see previous warnings)");
return ret;
-#endif /* HAVE_SYS_CAPABILITY_H */
+#endif /* HAVE_SYS_CAPABILITY_H && CAP_SYS_RAWIO */
}
static int
diff --git a/src/types.db b/src/types.db
index 18cb5d30330365018e7b1587ec987d1cd4eb0585..9ebc5fc6b0fc3922bf20f5364360f83764dac6a7 100644 (file)
--- a/src/types.db
+++ b/src/types.db
-absolute value:ABSOLUTE:0:U
-apache_bytes value:DERIVE:0:U
-apache_connections value:GAUGE:0:65535
-apache_idle_workers value:GAUGE:0:65535
-apache_requests value:DERIVE:0:U
-apache_scoreboard value:GAUGE:0:65535
-ath_nodes value:GAUGE:0:65535
-ath_stat value:DERIVE:0:U
-backends value:GAUGE:0:65535
-bitrate value:GAUGE:0:4294967295
-blocked_clients value:GAUGE:0:U
-bytes value:GAUGE:0:U
-cache_eviction value:DERIVE:0:U
-cache_operation value:DERIVE:0:U
-cache_ratio value:GAUGE:0:100
-cache_result value:DERIVE:0:U
-cache_size value:GAUGE:0:U
-capacity value:GAUGE:0:U
-ceph_bytes value:GAUGE:U:U
-ceph_latency value:GAUGE:U:U
-ceph_rate value:DERIVE:0:U
-changes_since_last_save value:GAUGE:0:U
-charge value:GAUGE:0:U
-compression_ratio value:GAUGE:0:2
-compression uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
-connections value:DERIVE:0:U
-conntrack value:GAUGE:0:4294967295
-contextswitch value:DERIVE:0:U
-count value:GAUGE:0:U
-counter value:COUNTER:U:U
-cpufreq value:GAUGE:0:U
-cpu value:DERIVE:0:U
-current_connections value:GAUGE:0:U
-current_sessions value:GAUGE:0:U
-current value:GAUGE:U:U
-delay value:GAUGE:-1000000:1000000
-derive value:DERIVE:0:U
-df_complex value:GAUGE:0:U
-df_inodes value:GAUGE:0:U
-df used:GAUGE:0:1125899906842623, free:GAUGE:0:1125899906842623
-disk_latency read:GAUGE:0:U, write:GAUGE:0:U
-disk_merged read:DERIVE:0:U, write:DERIVE:0:U
-disk_octets read:DERIVE:0:U, write:DERIVE:0:U
-disk_ops_complex value:DERIVE:0:U
-disk_ops read:DERIVE:0:U, write:DERIVE:0:U
-disk_time read:DERIVE:0:U, write:DERIVE:0:U
-disk_io_time io_time:DERIVE:0:U, weighted_io_time:DERIVE:0:U
-dns_answer value:DERIVE:0:U
-dns_notify value:DERIVE:0:U
-dns_octets queries:DERIVE:0:U, responses:DERIVE:0:U
-dns_opcode value:DERIVE:0:U
-dns_qtype_cached value:GAUGE:0:4294967295
-dns_qtype value:DERIVE:0:U
-dns_query value:DERIVE:0:U
-dns_question value:DERIVE:0:U
-dns_rcode value:DERIVE:0:U
-dns_reject value:DERIVE:0:U
-dns_request value:DERIVE:0:U
-dns_resolver value:DERIVE:0:U
-dns_response value:DERIVE:0:U
-dns_transfer value:DERIVE:0:U
-dns_update value:DERIVE:0:U
-dns_zops value:DERIVE:0:U
-drbd_resource value:DERIVE:0:U
-duration seconds:GAUGE:0:U
-email_check value:GAUGE:0:U
-email_count value:GAUGE:0:U
-email_size value:GAUGE:0:U
-entropy value:GAUGE:0:4294967295
-expired_keys value:DERIVE:0:U
-fanspeed value:GAUGE:0:U
-file_handles value:GAUGE:0:U
-file_size value:GAUGE:0:U
-files value:GAUGE:0:U
-flow value:GAUGE:0:U
-fork_rate value:DERIVE:0:U
-frequency_offset value:GAUGE:-1000000:1000000
-frequency value:GAUGE:0:U
-fscache_stat value:DERIVE:0:U
-gauge value:GAUGE:U:U
-hash_collisions value:DERIVE:0:U
-http_request_methods value:DERIVE:0:U
-http_requests value:DERIVE:0:U
-http_response_codes value:DERIVE:0:U
-humidity value:GAUGE:0:100
-if_collisions value:DERIVE:0:U
-if_dropped rx:DERIVE:0:U, tx:DERIVE:0:U
-if_errors rx:DERIVE:0:U, tx:DERIVE:0:U
-if_multicast value:DERIVE:0:U
-if_octets rx:DERIVE:0:U, tx:DERIVE:0:U
-if_packets rx:DERIVE:0:U, tx:DERIVE:0:U
-if_rx_errors value:DERIVE:0:U
-if_rx_octets value:DERIVE:0:U
-if_tx_errors value:DERIVE:0:U
-if_tx_octets value:DERIVE:0:U
-invocations value:DERIVE:0:U
-io_octets rx:DERIVE:0:U, tx:DERIVE:0:U
-io_packets rx:DERIVE:0:U, tx:DERIVE:0:U
-ipt_bytes value:DERIVE:0:U
-ipt_packets value:DERIVE:0:U
-irq value:DERIVE:0:U
-latency value:GAUGE:0:U
-links value:GAUGE:0:U
-load shortterm:GAUGE:0:5000, midterm:GAUGE:0:5000, longterm:GAUGE:0:5000
-md_disks value:GAUGE:0:U
-memcached_command value:DERIVE:0:U
-memcached_connections value:GAUGE:0:U
-memcached_items value:GAUGE:0:U
-memcached_octets rx:DERIVE:0:U, tx:DERIVE:0:U
-memcached_ops value:DERIVE:0:U
-memory value:GAUGE:0:281474976710656
-memory_lua value:GAUGE:0:281474976710656
-multimeter value:GAUGE:U:U
-mutex_operations value:DERIVE:0:U
-mysql_commands value:DERIVE:0:U
-mysql_handler value:DERIVE:0:U
-mysql_locks value:DERIVE:0:U
-mysql_log_position value:DERIVE:0:U
-mysql_octets rx:DERIVE:0:U, tx:DERIVE:0:U
-mysql_bpool_pages value:GAUGE:0:U
-mysql_bpool_bytes value:GAUGE:0:U
-mysql_bpool_counters value:DERIVE:0:U
-mysql_innodb_data value:DERIVE:0:U
-mysql_innodb_dblwr value:DERIVE:0:U
-mysql_innodb_log value:DERIVE:0:U
-mysql_innodb_pages value:DERIVE:0:U
-mysql_innodb_row_lock value:DERIVE:0:U
-mysql_innodb_rows value:DERIVE:0:U
-mysql_select value:DERIVE:0:U
-mysql_sort value:DERIVE:0:U
-nfs_procedure value:DERIVE:0:U
-nginx_connections value:GAUGE:0:U
-nginx_requests value:DERIVE:0:U
-node_octets rx:DERIVE:0:U, tx:DERIVE:0:U
-node_rssi value:GAUGE:0:255
-node_stat value:DERIVE:0:U
-node_tx_rate value:GAUGE:0:127
-objects value:GAUGE:0:U
-operations value:DERIVE:0:U
-packets value:DERIVE:0:U
-pending_operations value:GAUGE:0:U
-percent value:GAUGE:0:100.1
-percent_bytes value:GAUGE:0:100.1
-percent_inodes value:GAUGE:0:100.1
-pf_counters value:DERIVE:0:U
-pf_limits value:DERIVE:0:U
-pf_source value:DERIVE:0:U
-pf_states value:GAUGE:0:U
-pf_state value:DERIVE:0:U
-pg_blks value:DERIVE:0:U
-pg_db_size value:GAUGE:0:U
-pg_n_tup_c value:DERIVE:0:U
-pg_n_tup_g value:GAUGE:0:U
-pg_numbackends value:GAUGE:0:U
-pg_scan value:DERIVE:0:U
-pg_xact value:DERIVE:0:U
-ping_droprate value:GAUGE:0:100
-ping_stddev value:GAUGE:0:65535
-ping value:GAUGE:0:65535
-players value:GAUGE:0:1000000
-power value:GAUGE:U:U
-pressure value:GAUGE:0:U
-protocol_counter value:DERIVE:0:U
-ps_code value:GAUGE:0:9223372036854775807
-ps_count processes:GAUGE:0:1000000, threads:GAUGE:0:1000000
-ps_cputime user:DERIVE:0:U, syst:DERIVE:0:U
-ps_data value:GAUGE:0:9223372036854775807
-ps_disk_octets read:DERIVE:0:U, write:DERIVE:0:U
-ps_disk_ops read:DERIVE:0:U, write:DERIVE:0:U
-ps_pagefaults minflt:DERIVE:0:U, majflt:DERIVE:0:U
-ps_rss value:GAUGE:0:9223372036854775807
-ps_stacksize value:GAUGE:0:9223372036854775807
-ps_state value:GAUGE:0:65535
-ps_vm value:GAUGE:0:9223372036854775807
-pubsub value:GAUGE:0:U
-queue_length value:GAUGE:0:U
-records value:GAUGE:0:U
-requests value:GAUGE:0:U
-response_time value:GAUGE:0:U
-response_code value:GAUGE:0:U
-route_etx value:GAUGE:0:U
-route_metric value:GAUGE:0:U
-routes value:GAUGE:0:U
-segments value:GAUGE:0:65535
-serial_octets rx:DERIVE:0:U, tx:DERIVE:0:U
-signal_noise value:GAUGE:U:0
-signal_power value:GAUGE:U:0
-signal_quality value:GAUGE:0:U
-smart_poweron value:GAUGE:0:U
-smart_powercycles value:GAUGE:0:U
-smart_badsectors value:GAUGE:0:U
-smart_temperature value:GAUGE:-300:300
+absolute value:ABSOLUTE:0:U
+apache_bytes value:DERIVE:0:U
+apache_connections value:GAUGE:0:65535
+apache_idle_workers value:GAUGE:0:65535
+apache_requests value:DERIVE:0:U
+apache_scoreboard value:GAUGE:0:65535
+ath_nodes value:GAUGE:0:65535
+ath_stat value:DERIVE:0:U
+backends value:GAUGE:0:65535
+bitrate value:GAUGE:0:4294967295
+blocked_clients value:GAUGE:0:U
+bytes value:GAUGE:0:U
+cache_eviction value:DERIVE:0:U
+cache_operation value:DERIVE:0:U
+cache_ratio value:GAUGE:0:100
+cache_result value:DERIVE:0:U
+cache_size value:GAUGE:0:1125899906842623
+capacity value:GAUGE:0:U
+ceph_bytes value:GAUGE:U:U
+ceph_latency value:GAUGE:U:U
+ceph_rate value:DERIVE:0:U
+changes_since_last_save value:GAUGE:0:U
+charge value:GAUGE:0:U
+clock_last_meas value:GAUGE:0:U
+clock_last_update value:GAUGE:U:U
+clock_mode value:GAUGE:0:U
+clock_reachability value:GAUGE:0:U
+clock_skew_ppm value:GAUGE:-2:2
+clock_state value:GAUGE:0:U
+clock_stratum value:GAUGE:0:U
+compression uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
+compression_ratio value:GAUGE:0:2
+connections value:DERIVE:0:U
+conntrack value:GAUGE:0:4294967295
+contextswitch value:DERIVE:0:U
+count value:GAUGE:0:U
+counter value:COUNTER:U:U
+cpu value:DERIVE:0:U
+cpufreq value:GAUGE:0:U
+current value:GAUGE:U:U
+current_connections value:GAUGE:0:U
+current_sessions value:GAUGE:0:U
+delay value:GAUGE:-1000000:1000000
+derive value:DERIVE:0:U
+df used:GAUGE:0:1125899906842623, free:GAUGE:0:1125899906842623
+df_complex value:GAUGE:0:U
+df_inodes value:GAUGE:0:U
+dilution_of_precision value:GAUGE:0:U
+disk_io_time io_time:DERIVE:0:U, weighted_io_time:DERIVE:0:U
+disk_latency read:GAUGE:0:U, write:GAUGE:0:U
+disk_merged read:DERIVE:0:U, write:DERIVE:0:U
+disk_octets read:DERIVE:0:U, write:DERIVE:0:U
+disk_ops read:DERIVE:0:U, write:DERIVE:0:U
+disk_ops_complex value:DERIVE:0:U
+disk_time read:DERIVE:0:U, write:DERIVE:0:U
+dns_answer value:DERIVE:0:U
+dns_notify value:DERIVE:0:U
+dns_octets queries:DERIVE:0:U, responses:DERIVE:0:U
+dns_opcode value:DERIVE:0:U
+dns_qtype value:DERIVE:0:U
+dns_qtype_cached value:GAUGE:0:4294967295
+dns_query value:DERIVE:0:U
+dns_question value:DERIVE:0:U
+dns_rcode value:DERIVE:0:U
+dns_reject value:DERIVE:0:U
+dns_request value:DERIVE:0:U
+dns_resolver value:DERIVE:0:U
+dns_response value:DERIVE:0:U
+dns_transfer value:DERIVE:0:U
+dns_update value:DERIVE:0:U
+dns_zops value:DERIVE:0:U
+drbd_resource value:DERIVE:0:U
+duration seconds:GAUGE:0:U
+email_check value:GAUGE:0:U
+email_count value:GAUGE:0:U
+email_size value:GAUGE:0:U
+entropy value:GAUGE:0:4294967295
+evicted_keys value:DERIVE:0:U
+expired_keys value:DERIVE:0:U
+fanspeed value:GAUGE:0:U
+file_handles value:GAUGE:0:U
+file_size value:GAUGE:0:U
+files value:GAUGE:0:U
+flow value:GAUGE:0:U
+fork_rate value:DERIVE:0:U
+frequency value:GAUGE:0:U
+frequency_error value:GAUGE:-2:2
+frequency_offset value:GAUGE:-1000000:1000000
+fscache_stat value:DERIVE:0:U
+gauge value:GAUGE:U:U
+hash_collisions value:DERIVE:0:U
+http_request_methods value:DERIVE:0:U
+http_requests value:DERIVE:0:U
+http_response_codes value:DERIVE:0:U
+humidity value:GAUGE:0:100
+if_collisions value:DERIVE:0:U
+if_dropped rx:DERIVE:0:U, tx:DERIVE:0:U
+if_errors rx:DERIVE:0:U, tx:DERIVE:0:U
+if_multicast value:DERIVE:0:U
+if_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+if_packets rx:DERIVE:0:U, tx:DERIVE:0:U
+if_rx_errors value:DERIVE:0:U
+if_rx_octets value:DERIVE:0:U
+if_tx_errors value:DERIVE:0:U
+if_tx_octets value:DERIVE:0:U
+invocations value:DERIVE:0:U
+io_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+io_packets rx:DERIVE:0:U, tx:DERIVE:0:U
+ipt_bytes value:DERIVE:0:U
+ipt_packets value:DERIVE:0:U
+irq value:DERIVE:0:U
+latency value:GAUGE:0:U
+links value:GAUGE:0:U
+load shortterm:GAUGE:0:5000, midterm:GAUGE:0:5000, longterm:GAUGE:0:5000
+md_disks value:GAUGE:0:U
+memcached_command value:DERIVE:0:U
+memcached_connections value:GAUGE:0:U
+memcached_items value:GAUGE:0:U
+memcached_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+memcached_ops value:DERIVE:0:U
+memory value:GAUGE:0:281474976710656
+memory_lua value:GAUGE:0:281474976710656
+memory_throttle_count value:DERIVE:0:U
+multimeter value:GAUGE:U:U
+mutex_operations value:DERIVE:0:U
+mysql_bpool_bytes value:GAUGE:0:U
+mysql_bpool_counters value:DERIVE:0:U
+mysql_bpool_pages value:GAUGE:0:U
+mysql_commands value:DERIVE:0:U
+mysql_handler value:DERIVE:0:U
+mysql_innodb_data value:DERIVE:0:U
+mysql_innodb_dblwr value:DERIVE:0:U
+mysql_innodb_log value:DERIVE:0:U
+mysql_innodb_pages value:DERIVE:0:U
+mysql_innodb_row_lock value:DERIVE:0:U
+mysql_innodb_rows value:DERIVE:0:U
+mysql_locks value:DERIVE:0:U
+mysql_log_position value:DERIVE:0:U
+mysql_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+mysql_select value:DERIVE:0:U
+mysql_sort value:DERIVE:0:U
+mysql_sort_merge_passes value:DERIVE:0:U
+mysql_sort_rows value:DERIVE:0:U
+mysql_slow_queries value:DERIVE:0:U
+nfs_procedure value:DERIVE:0:U
+nginx_connections value:GAUGE:0:U
+nginx_requests value:DERIVE:0:U
+node_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+node_rssi value:GAUGE:0:255
+node_stat value:DERIVE:0:U
+node_tx_rate value:GAUGE:0:127
+objects value:GAUGE:0:U
+operations value:DERIVE:0:U
+operations_per_second value:GAUGE:0:U
+packets value:DERIVE:0:U
+pending_operations value:GAUGE:0:U
+percent value:GAUGE:0:100.1
+percent_bytes value:GAUGE:0:100.1
+percent_inodes value:GAUGE:0:100.1
+pf_counters value:DERIVE:0:U
+pf_limits value:DERIVE:0:U
+pf_source value:DERIVE:0:U
+pf_state value:DERIVE:0:U
+pf_states value:GAUGE:0:U
+pg_blks value:DERIVE:0:U
+pg_db_size value:GAUGE:0:U
+pg_n_tup_c value:DERIVE:0:U
+pg_n_tup_g value:GAUGE:0:U
+pg_numbackends value:GAUGE:0:U
+pg_scan value:DERIVE:0:U
+pg_xact value:DERIVE:0:U
+ping value:GAUGE:0:65535
+ping_droprate value:GAUGE:0:100
+ping_stddev value:GAUGE:0:65535
+players value:GAUGE:0:1000000
+power value:GAUGE:U:U
+pressure value:GAUGE:0:U
+protocol_counter value:DERIVE:0:U
+ps_code value:GAUGE:0:9223372036854775807
+ps_count processes:GAUGE:0:1000000, threads:GAUGE:0:1000000
+ps_cputime user:DERIVE:0:U, syst:DERIVE:0:U
+ps_data value:GAUGE:0:9223372036854775807
+ps_disk_octets read:DERIVE:0:U, write:DERIVE:0:U
+ps_disk_ops read:DERIVE:0:U, write:DERIVE:0:U
+ps_pagefaults minflt:DERIVE:0:U, majflt:DERIVE:0:U
+ps_rss value:GAUGE:0:9223372036854775807
+ps_stacksize value:GAUGE:0:9223372036854775807
+ps_state value:GAUGE:0:65535
+ps_vm value:GAUGE:0:9223372036854775807
+pubsub value:GAUGE:0:U
+queue_length value:GAUGE:0:U
+records value:GAUGE:0:U
+requests value:GAUGE:0:U
+response_code value:GAUGE:0:U
+response_time value:GAUGE:0:U
+root_delay value:GAUGE:U:U
+root_dispersion value:GAUGE:U:U
+route_etx value:GAUGE:0:U
+route_metric value:GAUGE:0:U
+routes value:GAUGE:0:U
+satellites value:GAUGE:0:U
+segments value:GAUGE:0:65535
+serial_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+signal_noise value:GAUGE:U:0
+signal_power value:GAUGE:U:0
+signal_quality value:GAUGE:0:U
smart_attribute current:GAUGE:0:255, worst:GAUGE:0:255, threshold:GAUGE:0:255, pretty:GAUGE:0:U
-snr value:GAUGE:0:U
-spam_check value:GAUGE:0:U
-spam_score value:GAUGE:U:U
-spl value:GAUGE:U:U
-swap_io value:DERIVE:0:U
-swap value:GAUGE:0:1099511627776
-tcp_connections value:GAUGE:0:4294967295
-temperature value:GAUGE:U:U
-threads value:GAUGE:0:U
-time_dispersion value:GAUGE:-1000000:1000000
-timeleft value:GAUGE:0:U
-time_offset value:GAUGE:-1000000:1000000
-total_bytes value:DERIVE:0:U
-total_connections value:DERIVE:0:U
-total_objects value:DERIVE:0:U
-total_operations value:DERIVE:0:U
-total_requests value:DERIVE:0:U
-total_sessions value:DERIVE:0:U
-total_threads value:DERIVE:0:U
-total_time_in_ms value:DERIVE:0:U
-total_values value:DERIVE:0:U
-uptime value:GAUGE:0:4294967295
-users value:GAUGE:0:65535
-vcl value:GAUGE:0:65535
-vcpu value:GAUGE:0:U
-virt_cpu_total value:DERIVE:0:U
-virt_vcpu value:DERIVE:0:U
-vmpage_action value:DERIVE:0:U
-vmpage_faults minflt:DERIVE:0:U, majflt:DERIVE:0:U
-vmpage_io in:DERIVE:0:U, out:DERIVE:0:U
-vmpage_number value:GAUGE:0:4294967295
-volatile_changes value:GAUGE:0:U
-voltage_threshold value:GAUGE:U:U, threshold:GAUGE:U:U
-voltage value:GAUGE:U:U
-vs_memory value:GAUGE:0:9223372036854775807
-vs_processes value:GAUGE:0:65535
-vs_threads value:GAUGE:0:65535
+smart_badsectors value:GAUGE:0:U
+smart_powercycles value:GAUGE:0:U
+smart_poweron value:GAUGE:0:U
+smart_temperature value:GAUGE:-300:300
+snr value:GAUGE:0:U
+spam_check value:GAUGE:0:U
+spam_score value:GAUGE:U:U
+spl value:GAUGE:U:U
+swap value:GAUGE:0:1099511627776
+swap_io value:DERIVE:0:U
+tcp_connections value:GAUGE:0:4294967295
+temperature value:GAUGE:U:U
+threads value:GAUGE:0:U
+time_dispersion value:GAUGE:-1000000:1000000
+time_offset value:GAUGE:-1000000:1000000
+time_offset_ntp value:GAUGE:-1000000:1000000
+time_offset_rms value:GAUGE:-1000000:1000000
+time_ref value:GAUGE:0:U
+timeleft value:GAUGE:0:U
+total_bytes value:DERIVE:0:U
+total_connections value:DERIVE:0:U
+total_objects value:DERIVE:0:U
+total_operations value:DERIVE:0:U
+total_requests value:DERIVE:0:U
+total_sessions value:DERIVE:0:U
+total_threads value:DERIVE:0:U
+total_time_in_ms value:DERIVE:0:U
+total_values value:DERIVE:0:U
+uptime value:GAUGE:0:4294967295
+users value:GAUGE:0:65535
+vcl value:GAUGE:0:65535
+vcpu value:GAUGE:0:U
+virt_cpu_total value:DERIVE:0:U
+virt_vcpu value:DERIVE:0:U
+vmpage_action value:DERIVE:0:U
+vmpage_faults minflt:DERIVE:0:U, majflt:DERIVE:0:U
+vmpage_io in:DERIVE:0:U, out:DERIVE:0:U
+vmpage_number value:GAUGE:0:4294967295
+volatile_changes value:GAUGE:0:U
+voltage value:GAUGE:U:U
+voltage_threshold value:GAUGE:U:U, threshold:GAUGE:U:U
+vs_memory value:GAUGE:0:9223372036854775807
+vs_processes value:GAUGE:0:65535
+vs_threads value:GAUGE:0:65535
#
# Legacy types
# (required for the v5 upgrade target)
#
-arc_counts demand_data:COUNTER:0:U, demand_metadata:COUNTER:0:U, prefetch_data:COUNTER:0:U, prefetch_metadata:COUNTER:0:U
-arc_l2_bytes read:COUNTER:0:U, write:COUNTER:0:U
-arc_l2_size value:GAUGE:0:U
-arc_ratio value:GAUGE:0:U
-arc_size current:GAUGE:0:U, target:GAUGE:0:U, minlimit:GAUGE:0:U, maxlimit:GAUGE:0:U
-mysql_qcache hits:COUNTER:0:U, inserts:COUNTER:0:U, not_cached:COUNTER:0:U, lowmem_prunes:COUNTER:0:U, queries_in_cache:GAUGE:0:U
-mysql_threads running:GAUGE:0:U, connected:GAUGE:0:U, cached:GAUGE:0:U, created:COUNTER:0:U
+arc_counts demand_data:COUNTER:0:U, demand_metadata:COUNTER:0:U, prefetch_data:COUNTER:0:U, prefetch_metadata:COUNTER:0:U
+arc_l2_bytes read:COUNTER:0:U, write:COUNTER:0:U
+arc_l2_size value:GAUGE:0:U
+arc_ratio value:GAUGE:0:U
+arc_size current:GAUGE:0:U, target:GAUGE:0:U, minlimit:GAUGE:0:U, maxlimit:GAUGE:0:U
+mysql_qcache hits:COUNTER:0:U, inserts:COUNTER:0:U, not_cached:COUNTER:0:U, lowmem_prunes:COUNTER:0:U, queries_in_cache:GAUGE:0:U
+mysql_threads running:GAUGE:0:U, connected:GAUGE:0:U, cached:GAUGE:0:U, created:COUNTER:0:U
diff --git a/src/unixsock.c b/src/unixsock.c
index e62ed6c0596b5ddb29848e66805d6e5ffd036f1c..808ba98bae65c48f20ec970c1c930214bdb51410 100644 (file)
--- a/src/unixsock.c
+++ b/src/unixsock.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_cmd_flush.h"
#include "utils_cmd_getval.h"
#include "utils_cmd_putval.h"
#include "utils_cmd_putnotif.h"
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
-#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
*/
static int us_open_socket (void)
{
- struct sockaddr_un sa;
+ struct sockaddr_un sa = { 0 };
int status;
sock_fd = socket (PF_UNIX, SOCK_STREAM, 0);
return (-1);
}
- memset (&sa, '\0', sizeof (sa));
sa.sun_family = AF_UNIX;
sstrncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
sizeof (sa.sun_path));
do
{
- char *grpname;
+ const char *grpname;
struct group *g;
struct group sg;
char grbuf[2048];
pthread_exit ((void *) 1);
}
- remote_fd = (int *) malloc (sizeof (int));
+ remote_fd = malloc (sizeof (*remote_fd));
if (remote_fd == NULL)
{
char errbuf[1024];
diff --git a/src/uptime.c b/src/uptime.c
index 345128da62f6750d30655d74a3f35a841ec6a110..cbe2f8c5dcaf2ebcaf4ff4fc059bbffa684d805e 100644 (file)
--- a/src/uptime.c
+++ b/src/uptime.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
/* #endif HAVE_LIBKSTAT */
# elif HAVE_SYS_SYSCTL_H
- struct timeval boottv;
+ struct timeval boottv = { 0 };
size_t boottv_len;
int status;
- int mib[2];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_BOOTTIME;
+ int mib[] = { CTL_KERN, KERN_BOOTTIME };
boottv_len = sizeof (boottv);
- memset (&boottv, 0, boottv_len);
status = sysctl (mib, STATIC_ARRAY_SIZE (mib), &boottv, &boottv_len,
/* new_value = */ NULL, /* new_length = */ 0);
diff --git a/src/users.c b/src/users.c
index 139c97659a974701c2f69051c4d8fb93e78fc833..30e0dbe67020817ed0d4b2630eb0341f99cdd5be 100644 (file)
--- a/src/users.c
+++ b/src/users.c
* Copyright (C) 2005-2007 Sebastian Harl
* Copyright (C) 2005 Niki W. Waibel
* Copyright (C) 2005-2007 Florian octo Forster
- * Copyright (C) 2008 Oleg King
+ * 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
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
users_submit (users);
/* #endif HAVE_GETUTXENT */
-
+
#elif HAVE_GETUTENT
unsigned int users = 0;
struct utmp *entry = NULL;
us = sg_get_user_stats ();
# endif
if (us == NULL)
- return (-1);
+ return (-1);
users_submit ((gauge_t)
# if HAVE_LIBSTATGRAB_0_90
diff --git a/src/utils_cmd_flush.c b/src/utils_cmd_flush.c
index a01d2343c9cb46f904dd295988f10fa9731418ca..1876150f38a0f6155fca7de383b86a49247f3c1d 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"
char **identifiers = NULL;
size_t identifiers_num = 0;
- size_t i;
-
#define PRINT_TO_SOCK(fh, ...) \
do { \
if (fprintf (fh, __VA_ARGS__) < 0) { \
}
} /* while (*buffer != 0) */
- for (i = 0; (i == 0) || (i < plugins_num); i++)
+ for (size_t i = 0; (i == 0) || (i < plugins_num); i++)
{
char *plugin = NULL;
- int j;
if (plugins_num != 0)
plugin = plugins[i];
- for (j = 0; (j == 0) || (j < identifiers_num); j++)
+ for (size_t j = 0; (j == 0) || (j < identifiers_num); j++)
{
char *identifier = NULL;
int status;
index 80babe3ebdc4dc36d63656c5c346ea67e297cc97..b2a0a23bfd892e7b77b6e24c4c1ad3934d69a6bc 100644 (file)
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
char *type;
char *type_instance;
- value_list_t vl;
threshold_t threshold;
int status;
return (-1);
}
- memset (&vl, 0, sizeof (vl));
+ value_list_t vl = {
+ .values = NULL
+ };
sstrncpy (vl.host, host, sizeof (vl.host));
sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
if (plugin_instance != NULL)
sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
sfree (identifier_copy);
- memset (&threshold, 0, sizeof (threshold));
status = ut_search_threshold (&vl, &threshold);
if (status == ENOENT)
{
diff --git a/src/utils_cmd_getval.c b/src/utils_cmd_getval.c
index 2d162224a4034bcf212845efe066c8a44f01af1c..cd88760a3746f01e4dee0a25f121987553e48ae8 100644 (file)
--- a/src/utils_cmd_getval.c
+++ b/src/utils_cmd_getval.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
const data_set_t *ds;
int status;
- size_t i;
if ((fh == NULL) || (buffer == NULL))
return (-1);
return (-1);
}
- if ((size_t) ds->ds_num != values_num)
+ if (ds->ds_num != values_num)
{
- ERROR ("ds[%s]->ds_num = %i, "
- "but uc_get_rate_by_name returned %u values.",
- ds->type, ds->ds_num, (unsigned int) values_num);
+ ERROR ("ds[%s]->ds_num = %zu, "
+ "but uc_get_rate_by_name returned %zu values.",
+ ds->type, ds->ds_num, values_num);
print_to_socket (fh, "-1 Error reading value from cache.\n");
sfree (values);
sfree (identifier_copy);
return (-1);
}
- print_to_socket (fh, "%u Value%s found\n", (unsigned int) values_num,
+ print_to_socket (fh, "%zu Value%s found\n", values_num,
(values_num == 1) ? "" : "s");
- for (i = 0; i < values_num; i++)
+ for (size_t i = 0; i < values_num; i++)
{
print_to_socket (fh, "%s=", ds->ds[i].name);
if (isnan (values[i]))
index b698388d3304e9686ae70f5c0202a1422a0fd36e..afbd01d0ceed106dd2b4852d06ca5b7a76e3dcea 100644 (file)
--- a/src/utils_cmd_listval.c
+++ b/src/utils_cmd_listval.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_parse_option.h"
#define free_everything_and_return(status) do { \
- size_t j; \
- for (j = 0; j < number; j++) { \
+ for (size_t j = 0; j < number; j++) { \
sfree(names[j]); \
names[j] = NULL; \
} \
char **names = NULL;
cdtime_t *times = NULL;
size_t number = 0;
- size_t i;
int status;
DEBUG ("utils_cmd_listval: handle_listval (fh = %p, buffer = %s);",
print_to_socket (fh, "%i Value%s found\n",
(int) number, (number == 1) ? "" : "s");
- for (i = 0; i < number; i++)
+ for (size_t i = 0; i < number; i++)
print_to_socket (fh, "%.3f %s\n", CDTIME_T_TO_DOUBLE (times[i]),
names[i]);
index 145cd107c771b7330bcd20fa18e737a810e76000..669ef837b94fa6ff5ae0678f249ddebbe25088b5 100644 (file)
--- a/src/utils_cmd_putnotif.c
+++ b/src/utils_cmd_putnotif.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
@@ -119,7 +120,7 @@ static int set_option (notification_t *n, const char *option, const char *value)
int handle_putnotif (FILE *fh, char *buffer)
{
char *command;
- notification_t n;
+ notification_t n = { 0 };
int status;
if ((fh == NULL) || (buffer == NULL))
return (-1);
}
- memset (&n, '\0', sizeof (n));
-
status = 0;
while (*buffer != 0)
{
diff --git a/src/utils_cmd_putval.c b/src/utils_cmd_putval.c
index 43244f6185cad30df9561aafcee746f1171a28bc..bf3e2b6f2b9880cf50f6d602bf721ed42c51afb7 100644 (file)
--- a/src/utils_cmd_putval.c
+++ b/src/utils_cmd_putval.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
sfree (identifier_copy);
vl.values_len = ds->ds_num;
- vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t));
+ vl.values = malloc (vl.values_len * sizeof (*vl.values));
if (vl.values == NULL)
{
print_to_socket (fh, "-1 malloc failed.\n");
} /* while (*buffer != 0) */
/* Done parsing the options. */
- print_to_socket (fh, "0 Success: %i %s been dispatched.\n",
+ if (fh!=stdout)
+ print_to_socket (fh, "0 Success: %i %s been dispatched.\n",
values_submitted,
(values_submitted == 1) ? "value has" : "values have");
diff --git a/src/utils_crc32.c b/src/utils_crc32.c
index f9eaf880c03737863741ce3e12bcd3c8f94ab658..79d77a23901a23695c8ae8703e3630bb9f2be502 100644 (file)
--- a/src/utils_crc32.c
+++ b/src/utils_crc32.c
uint32_t
crc32_buffer(const unsigned char *s, size_t len)
{
- size_t i;
uint32_t ret;
ret = 0;
- for (i = 0; i < len; i++)
+ for (size_t i = 0; i < len; i++)
ret = crc32_tab[(ret ^ s[i]) & 0xff] ^ (ret >> 8);
return ret;
}
diff --git a/src/utils_curl_stats.c b/src/utils_curl_stats.c
--- /dev/null
+++ b/src/utils_curl_stats.c
@@ -0,0 +1,248 @@
+/**
+ * collectd - src/utils_curl_stats.c
+ * Copyright (C) 2015 Sebastian 'tokkee' Harl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Sebastian Harl <sh@tokkee.org>
+ **/
+
+#include "collectd.h"
+
+#include "common.h"
+#include "utils_curl_stats.h"
+
+#include <stdbool.h>
+#include <stddef.h>
+
+struct curl_stats_s
+{
+ bool total_time;
+ bool namelookup_time;
+ bool connect_time;
+ bool pretransfer_time;
+ bool size_upload;
+ bool size_download;
+ bool speed_download;
+ bool speed_upload;
+ bool header_size;
+ bool request_size;
+ bool content_length_download;
+ bool content_length_upload;
+ bool starttransfer_time;
+ bool redirect_time;
+ bool redirect_count;
+ bool num_connects;
+ bool appconnect_time;
+};
+
+/*
+ * Private functions
+ */
+
+static int dispatch_gauge (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+ CURLcode code;
+ value_t v;
+
+ code = curl_easy_getinfo (curl, info, &v.gauge);
+ if (code != CURLE_OK)
+ return -1;
+
+ vl->values = &v;
+ vl->values_len = 1;
+
+ return plugin_dispatch_values (vl);
+} /* dispatch_gauge */
+
+/* dispatch a speed, in bytes/second */
+static int dispatch_speed (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+ CURLcode code;
+ value_t v;
+
+ code = curl_easy_getinfo (curl, info, &v.gauge);
+ if (code != CURLE_OK)
+ return -1;
+
+ v.gauge *= 8;
+
+ vl->values = &v;
+ vl->values_len = 1;
+
+ return plugin_dispatch_values (vl);
+} /* dispatch_speed */
+
+/* dispatch a size/count, reported as a long value */
+static int dispatch_size (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+ CURLcode code;
+ value_t v;
+ long raw;
+
+ code = curl_easy_getinfo (curl, info, &raw);
+ if (code != CURLE_OK)
+ return -1;
+
+ v.gauge = (double)raw;
+
+ vl->values = &v;
+ vl->values_len = 1;
+
+ return plugin_dispatch_values (vl);
+} /* dispatch_size */
+
+static struct {
+ const char *name;
+ const char *config_key;
+ size_t offset;
+
+ int (*dispatcher)(CURL *, CURLINFO, value_list_t *);
+ const char *type;
+ CURLINFO info;
+} field_specs[] = {
+#define SPEC(name, config_key, dispatcher, type, info) \
+ { #name, config_key, offsetof (curl_stats_t, name), dispatcher, type, info }
+
+ SPEC (total_time, "TotalTime", dispatch_gauge, "duration", CURLINFO_TOTAL_TIME),
+ SPEC (namelookup_time, "NamelookupTime", dispatch_gauge, "duration", CURLINFO_NAMELOOKUP_TIME),
+ SPEC (connect_time, "ConnectTime", dispatch_gauge, "duration", CURLINFO_CONNECT_TIME),
+ SPEC (pretransfer_time, "PretransferTime", dispatch_gauge, "duration", CURLINFO_PRETRANSFER_TIME),
+ SPEC (size_upload, "SizeUpload", dispatch_gauge, "bytes", CURLINFO_SIZE_UPLOAD),
+ SPEC (size_download, "SizeDownload", dispatch_gauge, "bytes", CURLINFO_SIZE_DOWNLOAD),
+ SPEC (speed_download, "SpeedDownload", dispatch_speed, "bitrate", CURLINFO_SPEED_DOWNLOAD),
+ SPEC (speed_upload, "SpeedUpload", dispatch_speed, "bitrate", CURLINFO_SPEED_UPLOAD),
+ SPEC (header_size, "HeaderSize", dispatch_size, "bytes", CURLINFO_HEADER_SIZE),
+ SPEC (request_size, "RequestSize", dispatch_size, "bytes", CURLINFO_REQUEST_SIZE),
+ SPEC (content_length_download, "ContentLengthDownload", dispatch_gauge, "bytes", CURLINFO_CONTENT_LENGTH_DOWNLOAD),
+ SPEC (content_length_upload, "ContentLengthUpload", dispatch_gauge, "bytes", CURLINFO_CONTENT_LENGTH_UPLOAD),
+ SPEC (starttransfer_time, "StarttransferTime", dispatch_gauge, "duration", CURLINFO_STARTTRANSFER_TIME),
+ SPEC (redirect_time, "RedirectTime", dispatch_gauge, "duration", CURLINFO_REDIRECT_TIME),
+ SPEC (redirect_count, "RedirectCount", dispatch_size, "count", CURLINFO_REDIRECT_COUNT),
+ SPEC (num_connects, "NumConnects", dispatch_size, "count", CURLINFO_NUM_CONNECTS),
+#ifdef HAVE_CURLINFO_APPCONNECT_TIME
+ SPEC (appconnect_time, "AppconnectTime", dispatch_gauge, "duration", CURLINFO_APPCONNECT_TIME),
+#endif
+
+#undef SPEC
+};
+
+static void enable_field (curl_stats_t *s, size_t offset)
+{
+ *(bool *)((char *)s + offset) = true;
+} /* enable_field */
+
+static bool field_enabled (curl_stats_t *s, size_t offset)
+{
+ return *(bool *)((char *)s + offset);
+} /* field_enabled */
+
+/*
+ * Public API
+ */
+curl_stats_t *curl_stats_from_config (oconfig_item_t *ci)
+{
+ curl_stats_t *s;
+
+ if (ci == NULL)
+ return NULL;
+
+ s = calloc (1, sizeof (*s));
+ if (s == NULL)
+ return NULL;
+
+ for (int i = 0; i < ci->children_num; ++i)
+ {
+ oconfig_item_t *c = ci->children + i;
+ size_t field;
+
+ _Bool enabled = 0;
+
+ for (field = 0; field < STATIC_ARRAY_SIZE (field_specs); ++field) {
+ if (! strcasecmp (c->key, field_specs[field].config_key))
+ break;
+ if (! strcasecmp (c->key, field_specs[field].name))
+ break;
+ }
+ if (field >= STATIC_ARRAY_SIZE (field_specs))
+ {
+ ERROR ("curl stats: Unknown field name %s", c->key);
+ free (s);
+ return NULL;
+ }
+
+
+ if (cf_util_get_boolean (c, &enabled) != 0) {
+ free (s);
+ return NULL;
+ }
+ if (enabled)
+ enable_field (s, field_specs[field].offset);
+ }
+
+ return s;
+} /* curl_stats_from_config */
+
+void curl_stats_destroy (curl_stats_t *s)
+{
+ if (s != NULL)
+ free (s);
+} /* curl_stats_destroy */
+
+int curl_stats_dispatch (curl_stats_t *s, CURL *curl,
+ const char *hostname, const char *plugin, const char *plugin_instance)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+
+ if (s == NULL)
+ return 0;
+ if ((curl == NULL) || (hostname == NULL) || (plugin == NULL))
+ {
+ ERROR ("curl stats: dispatch() called with missing arguments "
+ "(curl=%p; hostname=%s; plugin=%s)", curl,
+ hostname == NULL ? "<NULL>" : hostname,
+ plugin == NULL ? "<NULL>" : plugin);
+ return -1;
+ }
+
+ sstrncpy (vl.host, hostname, sizeof (vl.host));
+ sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
+ if (plugin_instance != NULL)
+ sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+
+ for (size_t field = 0; field < STATIC_ARRAY_SIZE (field_specs); ++field)
+ {
+ int status;
+
+ if (! field_enabled (s, field_specs[field].offset))
+ continue;
+
+ sstrncpy (vl.type, field_specs[field].type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, field_specs[field].name, sizeof (vl.type_instance));
+
+ vl.values = NULL;
+ vl.values_len = 0;
+ status = field_specs[field].dispatcher (curl, field_specs[field].info, &vl);
+ if (status < 0)
+ return status;
+ }
+
+ return 0;
+} /* curl_stats_dispatch */
diff --git a/src/utils_curl_stats.h b/src/utils_curl_stats.h
--- /dev/null
+++ b/src/utils_curl_stats.h
@@ -0,0 +1,56 @@
+/**
+ * collectd - src/utils_curl_stats.h
+ * Copyright (C) 2015 Sebastian 'tokkee' Harl
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Sebastian Harl <sh@tokkee.org>
+ **/
+
+#ifndef UTILS_CURL_STATS_H
+#define UTILS_CURL_STATS_H 1
+
+#include "plugin.h"
+
+#include <curl/curl.h>
+
+struct curl_stats_s;
+typedef struct curl_stats_s curl_stats_t;
+
+/*
+ * curl_stats_from_config allocates and constructs a cURL statistics object
+ * from the specified configuration which is expected to be a single block of
+ * boolean options named after cURL information fields. The boolean value
+ * indicates whether to collect the respective information.
+ *
+ * See http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html
+ */
+curl_stats_t *curl_stats_from_config (oconfig_item_t *ci);
+
+void curl_stats_destroy (curl_stats_t *s);
+
+/*
+ * curl_stats_dispatch dispatches performance values from the the specified
+ * cURL session to the daemon.
+ */
+int curl_stats_dispatch (curl_stats_t *s, CURL *curl,
+ const char *hostname, const char *plugin, const char *plugin_instance);
+
+#endif /* UTILS_CURL_STATS_H */
diff --git a/src/utils_db_query.c b/src/utils_db_query.c
index fcded6b414687f10d3773d7a42f58ad8c90581eb..bbee90aec6d70a750b323ffa4f2ec466cb1d8208 100644 (file)
--- a/src/utils_db_query.c
+++ b/src/utils_db_query.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_db_query.h"
/*
char *name;
char *statement;
void *user_data;
+ char *plugin_instance_from;
unsigned int min_version;
unsigned int max_version;
char **instances_buffer;
char **values_buffer;
char **metadata_buffer;
+ char *plugin_instance;
struct udb_result_preparation_area_s *next;
}; /* }}} */
struct udb_query_preparation_area_s /* {{{ */
{
size_t column_num;
+ size_t plugin_instance_pos;
char *host;
char *plugin;
char *db_name;
{
char **array;
size_t array_len;
- int i;
if (ci->values_num < 1)
{
return (-1);
}
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
if (ci->values[i].type != OCONFIG_TYPE_STRING)
{
}
array_len = *ret_array_len;
- array = (char **) realloc (*ret_array,
+ array = realloc (*ret_array,
sizeof (char *) * (array_len + ci->values_num));
if (array == NULL)
{
}
*ret_array = array;
- for (i = 0; i < ci->values_num; i++)
+ for (int i = 0; i < ci->values_num; i++)
{
array[array_len] = strdup (ci->values[i].value.string);
if (array[array_len] == NULL)
udb_query_t const *q, udb_query_preparation_area_t *q_area)
{
value_list_t vl = VALUE_LIST_INIT;
- size_t i;
- int status;
assert (r != NULL);
assert (r_area->ds != NULL);
assert (((size_t) r_area->ds->ds_num) == r->values_num);
assert (r->values_num > 0);
- vl.values = (value_t *) calloc (r->values_num, sizeof (value_t));
+ vl.values = calloc (r->values_num, sizeof (*vl.values));
if (vl.values == NULL)
{
- ERROR ("db query utils: malloc failed.");
+ ERROR ("db query utils: calloc failed.");
return (-1);
}
vl.values_len = r_area->ds->ds_num;
- for (i = 0; i < r->values_num; i++)
+ for (size_t i = 0; i < r->values_num; i++)
{
char *value_str = r_area->values_buffer[i];
ERROR ("db query utils: udb_result_submit: Parsing `%s' as %s failed.",
value_str, DS_TYPE_TO_STRING (r_area->ds->ds[i].type));
errno = EINVAL;
+ free (vl.values);
return (-1);
}
}
sstrncpy (vl.host, q_area->host, sizeof (vl.host));
sstrncpy (vl.plugin, q_area->plugin, sizeof (vl.plugin));
- sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
sstrncpy (vl.type, r->type, sizeof (vl.type));
+ /* Set vl.plugin_instance */
+ if (q->plugin_instance_from != NULL) {
+ sstrncpy (vl.plugin_instance, r_area->plugin_instance, sizeof (vl.plugin_instance));
+ }
+ else {
+ sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
+ }
+
/* Set vl.type_instance {{{ */
- if (r->instances_num <= 0)
+ if (r->instances_num == 0)
{
if (r->instance_prefix == NULL)
vl.type_instance[0] = 0;
return (-ENOMEM);
}
- for (i = 0; i < r->metadata_num; i++)
+ for (size_t i = 0; i < r->metadata_num; i++)
{
- status = meta_data_add_string (vl.meta, r->metadata[i],
+ int status = meta_data_add_string (vl.meta, r->metadata[i],
r_area->metadata_buffer[i]);
if (status != 0)
{
udb_result_preparation_area_t *r_area,
udb_query_t const *q, char **column_values)
{
- size_t i;
-
assert (r && q_area && r_area);
- for (i = 0; i < r->instances_num; i++)
+ for (size_t i = 0; i < r->instances_num; i++)
r_area->instances_buffer[i] = column_values[r_area->instances_pos[i]];
- for (i = 0; i < r->values_num; i++)
+ for (size_t i = 0; i < r->values_num; i++)
r_area->values_buffer[i] = column_values[r_area->values_pos[i]];
- for (i = 0; i < r->metadata_num; i++)
+ for (size_t i = 0; i < r->metadata_num; i++)
r_area->metadata_buffer[i] = column_values[r_area->metadata_pos[i]];
+ if (q->plugin_instance_from)
+ r_area->plugin_instance = column_values[q_area->plugin_instance_pos];
+
return udb_result_submit (r, r_area, q, q_area);
} /* }}} int udb_result_handle_result */
udb_result_preparation_area_t *prep_area,
char **column_names, size_t column_num)
{
- size_t i;
-
if ((r == NULL) || (prep_area == NULL))
return (-EINVAL);
BAIL_OUT (-1);
}
- if (((size_t) prep_area->ds->ds_num) != r->values_num)
+ if (prep_area->ds->ds_num != r->values_num)
{
ERROR ("db query utils: udb_result_prepare_result: The type `%s' "
- "requires exactly %i value%s, but the configuration specifies %zu.",
+ "requires exactly %zu value%s, but the configuration specifies %zu.",
r->type,
prep_area->ds->ds_num, (prep_area->ds->ds_num == 1) ? "" : "s",
r->values_num);
= (size_t *) calloc (r->instances_num, sizeof (size_t));
if (prep_area->instances_pos == NULL)
{
- ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+ ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
BAIL_OUT (-ENOMEM);
}
= (char **) calloc (r->instances_num, sizeof (char *));
if (prep_area->instances_buffer == NULL)
{
- ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+ ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
BAIL_OUT (-ENOMEM);
}
} /* if (r->instances_num > 0) */
= (size_t *) calloc (r->values_num, sizeof (size_t));
if (prep_area->values_pos == NULL)
{
- ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+ ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
BAIL_OUT (-ENOMEM);
}
= (char **) calloc (r->values_num, sizeof (char *));
if (prep_area->values_buffer == NULL)
{
- ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+ ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
BAIL_OUT (-ENOMEM);
}
= (size_t *) calloc (r->metadata_num, sizeof (size_t));
if (prep_area->metadata_pos == NULL)
{
- ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+ ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
BAIL_OUT (-ENOMEM);
}
= (char **) calloc (r->metadata_num, sizeof (char *));
if (prep_area->metadata_buffer == NULL)
{
- ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+ ERROR ("db query utils: udb_result_prepare_result: calloc failed.");
BAIL_OUT (-ENOMEM);
}
/* }}} */
- /* Determine the position of the instance columns {{{ */
- for (i = 0; i < r->instances_num; i++)
+ /* Determine the position of the plugin instance column {{{ */
+ for (size_t i = 0; i < r->instances_num; i++)
{
size_t j;
}
} /* }}} for (i = 0; i < r->instances_num; i++) */
+
/* Determine the position of the value columns {{{ */
- for (i = 0; i < r->values_num; i++)
+ for (size_t i = 0; i < r->values_num; i++)
{
size_t j;
} /* }}} for (i = 0; i < r->values_num; i++) */
/* Determine the position of the metadata columns {{{ */
- for (i = 0; i < r->metadata_num; i++)
+ for (size_t i = 0; i < r->metadata_num; i++)
{
size_t j;
static void udb_result_free (udb_result_t *r) /* {{{ */
{
- size_t i;
-
if (r == NULL)
return;
sfree (r->type);
+ sfree (r->instance_prefix);
- for (i = 0; i < r->instances_num; i++)
+ for (size_t i = 0; i < r->instances_num; i++)
sfree (r->instances[i]);
sfree (r->instances);
- for (i = 0; i < r->values_num; i++)
+ for (size_t i = 0; i < r->values_num; i++)
sfree (r->values[i]);
sfree (r->values);
- for (i = 0; i < r->metadata_num; i++)
+ for (size_t i = 0; i < r->metadata_num; i++)
sfree (r->metadata[i]);
sfree (r->metadata);
{
udb_result_t *r;
int status;
- int i;
if (ci->values_num != 0)
{
ci->values_num, (ci->values_num == 1) ? "" : "s");
}
- r = (udb_result_t *) malloc (sizeof (*r));
+ r = calloc (1, sizeof (*r));
if (r == NULL)
{
- ERROR ("db query utils: malloc failed.");
+ ERROR ("db query utils: calloc failed.");
return (-1);
}
- memset (r, 0, sizeof (*r));
r->type = NULL;
r->instance_prefix = NULL;
r->instances = NULL;
/* Fill the `udb_result_t' structure.. */
status = 0;
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
sfree (q->name);
sfree (q->statement);
+ sfree (q->plugin_instance_from);
udb_result_free (q->results);
udb_query_t *q;
int status;
- int i;
if ((ret_query_list == NULL) || (ret_query_list_len == NULL))
return (-EINVAL);
return (-1);
}
- q = (udb_query_t *) malloc (sizeof (*q));
+ q = calloc (1, sizeof (*q));
if (q == NULL)
{
- ERROR ("db query utils: malloc failed.");
+ ERROR ("db query utils: calloc failed.");
return (-1);
}
- memset (q, 0, sizeof (*q));
q->min_version = 0;
q->max_version = UINT_MAX;
+ q->statement = NULL;
+ q->results = NULL;
+ q->plugin_instance_from = NULL;
status = udb_config_set_string (&q->name, ci);
if (status != 0)
}
/* Fill the `udb_query_t' structure.. */
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
status = udb_config_set_uint (&q->min_version, child);
else if (strcasecmp ("MaxVersion", child->key) == 0)
status = udb_config_set_uint (&q->max_version, child);
+ else if (strcasecmp ("PluginInstanceFrom", child->key) == 0)
+ status = udb_config_set_string (&q->plugin_instance_from, child);
/* Call custom callbacks */
else if (cb != NULL)
{
udb_query_t **temp;
- temp = (udb_query_t **) realloc (query_list,
+ temp = realloc (query_list,
sizeof (*query_list) * (query_list_len + 1));
if (temp == NULL)
{
void udb_query_free (udb_query_t **query_list, size_t query_list_len) /* {{{ */
{
- size_t i;
-
if (query_list == NULL)
return;
- for (i = 0; i < query_list_len; i++)
+ for (size_t i = 0; i < query_list_len; i++)
udb_query_free_one (query_list[i]);
sfree (query_list);
udb_query_t **src_list, size_t src_list_len,
udb_query_t ***dst_list, size_t *dst_list_len)
{
- size_t i;
int num_added;
if ((name == NULL) || (src_list == NULL) || (dst_list == NULL)
}
num_added = 0;
- for (i = 0; i < src_list_len; i++)
+ for (size_t i = 0; i < src_list_len; i++)
{
udb_query_t **tmp_list;
size_t tmp_list_len;
continue;
tmp_list_len = *dst_list_len;
- tmp_list = (udb_query_t **) realloc (*dst_list, (tmp_list_len + 1)
+ tmp_list = realloc (*dst_list, (tmp_list_len + 1)
* sizeof (udb_query_t *));
if (tmp_list == NULL)
{
#if defined(COLLECT_DEBUG) && COLLECT_DEBUG /* {{{ */
do
{
- size_t i;
-
- for (i = 0; i < prep_area->column_num; i++)
+ for (size_t i = 0; i < prep_area->column_num; i++)
{
DEBUG ("db query utils: udb_query_handle_result (%s, %s): "
"column[%zu] = %s;",
#if defined(COLLECT_DEBUG) && COLLECT_DEBUG
do
{
- size_t i;
-
- for (i = 0; i < column_num; i++)
+ for (size_t i = 0; i < column_num; i++)
{
DEBUG ("db query utils: udb_query_prepare_result: "
"query = %s; column[%zu] = %s;",
} while (0);
#endif
+ /* Determine the position of the PluginInstance column {{{ */
+ if (q->plugin_instance_from != NULL)
+ {
+ size_t i;
+
+ for (i = 0; i < column_num; i++)
+ {
+ if (strcasecmp (q->plugin_instance_from, column_names[i]) == 0)
+ {
+ prep_area->plugin_instance_pos = i;
+ break;
+ }
+ }
+
+ if (i >= column_num)
+ {
+ ERROR ("db query utils: udb_query_prepare_result: "
+ "Column `%s' from `PluginInstanceFrom' could not be found.",
+ q->plugin_instance_from);
+ udb_query_finish_result (q, prep_area);
+ return (-ENOENT);
+ }
+ }
+ /* }}} */
+
for (r = q->results, r_area = prep_area->result_prep_areas;
r != NULL; r = r->next, r_area = r_area->next)
{
udb_result_preparation_area_t **next_r_area;
udb_result_t *r;
- q_area = malloc (sizeof (*q_area));
+ q_area = calloc (1, sizeof (*q_area));
if (q_area == NULL)
return NULL;
- memset (q_area, 0, sizeof (*q_area));
next_r_area = &q_area->result_prep_areas;
for (r = q->results; r != NULL; r = r->next)
{
udb_result_preparation_area_t *r_area;
- r_area = malloc (sizeof (*r_area));
+ r_area = calloc (1, sizeof (*r_area));
if (r_area == NULL)
{
udb_result_preparation_area_t *a = q_area->result_prep_areas;
return NULL;
}
- memset (r_area, 0, sizeof (*r_area));
-
*next_r_area = r_area;
next_r_area = &r_area->next;
}
diff --git a/src/utils_db_query.h b/src/utils_db_query.h
index 08b10bda2c2831424f2150580e53cbac48bda2ad..fe06de9e6f8825273a573d00130ab1cdb3b57f73 100644 (file)
--- a/src/utils_db_query.h
+++ b/src/utils_db_query.h
#ifndef UTILS_DB_QUERY_H
#define UTILS_DB_QUERY_H 1
-#include "configfile.h"
-
/*
* Data types
*/
typedef int (*udb_query_create_callback_t) (udb_query_t *q,
oconfig_item_t *ci);
-/*
+/*
* Public functions
*/
int udb_query_create (udb_query_t ***ret_query_list,
void udb_query_set_user_data (udb_query_t *q, void *user_data);
void *udb_query_get_user_data (udb_query_t *q);
-/*
+/*
* udb_query_check_version
*
* Returns 0 if the query is NOT suitable for `version' and >0 if the
diff --git a/src/utils_dns.c b/src/utils_dns.c
index 6abfde16fba0f5cd2da6e1da4f98832717f48519..3e80e8690efa3360c99a2e4a34509b93a76a23ca 100644 (file)
--- a/src/utils_dns.c
+++ b/src/utils_dns.c
#define _BSD_SOURCE
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
#if HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#endif
#if HAVE_NETINET_IP6_H
# include <netinet/ip6.h>
#endif
-#if HAVE_NETINET_IP_COMPAT_H
-# include <netinet/ip_compat.h>
-#endif
#if HAVE_NETINET_IF_ETHER_H
# include <netinet/if_ether.h>
#endif
/*
* Global variables
*/
-int qtype_counts[T_MAX];
-int opcode_counts[OP_MAX];
-int qclass_counts[C_MAX];
#if HAVE_PCAP_H
static pcap_t *pcap_obj = NULL;
static inline int ignore_list_match (const struct in6_addr *addr)
{
- ip_list_t *ptr;
-
- for (ptr = IgnoreList; ptr != NULL; ptr = ptr->next)
+ for (ip_list_t *ptr = IgnoreList; ptr != NULL; ptr = ptr->next)
if (cmp_in6_addr (addr, &ptr->addr) == 0)
return (1);
return (0);
if (ignore_list_match (addr) != 0)
return;
- new = malloc (sizeof (ip_list_t));
+ new = malloc (sizeof (*new));
if (new == NULL)
{
perror ("malloc");
void ignore_list_add_name (const char *name)
{
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
struct in6_addr addr;
int status;
if (status != 0)
return;
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
if (ai_ptr->ai_family == AF_INET)
{
#define RFC1035_MAXLABELSZ 63
static int
-rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
-)
+rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns)
{
off_t no = 0;
unsigned char c;
@@ -302,10 +289,10 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
static int loop_detect = 0;
if (loop_detect > 2)
return 4; /* compression loop */
- if (ns <= 0)
+ if (ns == 0)
return 4; /* probably compression loop */
do {
- if ((*off) >= sz)
+ if ((*off) >= ((off_t) sz))
break;
c = *(buf + (*off));
if (c > 191) {
@@ -317,11 +304,11 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
s = ntohs(s);
(*off) += sizeof(s);
/* Sanity check */
- if ((*off) >= sz)
+ if ((*off) >= ((off_t) sz))
return 1; /* message too short */
ptr = s & 0x3FFF;
/* Make sure the pointer is inside this message */
- if (ptr >= sz)
+ if (ptr >= ((off_t) sz))
return 2; /* bad compression ptr */
if (ptr < DNS_MSG_HDR_SZ)
return 2; /* bad compression ptr */
@@ -334,7 +321,6 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
* "(The 10 and 01 combinations are reserved for future use.)"
*/
return 3; /* reserved label/compression flags */
- break;
} else {
(*off)++;
len = (size_t) c;
@@ -355,7 +341,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
if (no > 0)
*(name + no - 1) = '\0';
/* make sure we didn't allow someone to overflow the name buffer */
- assert(no <= ns);
+ assert(no <= ((off_t) ns));
return 0;
}
qh.length = (uint16_t) len;
- /* gather stats */
- qtype_counts[qh.qtype]++;
- qclass_counts[qh.qclass]++;
- opcode_counts[qh.opcode]++;
-
if (Callback != NULL)
Callback (&qh);
return (0);
if (IPPROTO_UDP != ip->ip_p)
return 0;
- memcpy(buf, (void *) ip + offset, len - offset);
+ memcpy(buf, ((char *)ip) + offset, len - offset);
if (0 == handle_udp((struct udphdr *) buf, len - offset))
return 0;
return 1;
case ns_t_srv: return ("SRV");
case ns_t_atma: return ("ATMA");
case ns_t_naptr: return ("NAPTR");
+ case ns_t_opt: return ("OPT");
+# if __NAMESER >= 19991006
case ns_t_kx: return ("KX");
case ns_t_cert: return ("CERT");
case ns_t_a6: return ("A6");
case ns_t_dname: return ("DNAME");
case ns_t_sink: return ("SINK");
- case ns_t_opt: return ("OPT");
-# if __NAMESER >= 19991006
case ns_t_tsig: return ("TSIG");
# endif
+# if __NAMESER >= 20090302
+ case ns_t_apl: return ("APL");
+ case ns_t_ds: return ("DS");
+ case ns_t_sshfp: return ("SSHFP");
+ case ns_t_ipseckey: return ("IPSECKEY");
+ case ns_t_rrsig: return ("RRSIG");
+ case ns_t_nsec: return ("NSEC");
+ case ns_t_dnskey: return ("DNSKEY");
+ case ns_t_dhcid: return ("DHCID");
+ case ns_t_nsec3: return ("NSEC3");
+ case ns_t_nsec3param: return ("NSEC3PARAM");
+ case ns_t_hip: return ("HIP");
+ case ns_t_spf: return ("SPF");
case ns_t_ixfr: return ("IXFR");
+# endif
case ns_t_axfr: return ("AXFR");
case ns_t_mailb: return ("MAILB");
case ns_t_maila: return ("MAILA");
case ns_t_any: return ("ANY");
+# if __NAMESER >= 19991006
case ns_t_zxfr: return ("ZXFR");
-/* #endif __NAMESER >= 19991006 */
+# endif
+# if __NAMESER >= 20090302
+ case ns_t_dlv: return ("DLV");
+# endif
+/* #endif __NAMESER >= 19991001 */
#elif (defined (__BIND)) && (__BIND >= 19950621)
case T_A: return ("A"); /* 1 ... */
case T_NS: return ("NS");
default:
ssnprintf (buf, sizeof (buf), "#%i", t);
return (buf);
- }; /* switch (t) */
- /* NOTREACHED */
- return (NULL);
+ } /* switch (t) */
}
const char *opcode_str (int o)
switch (o) {
case 0:
return "Query";
- break;
case 1:
return "Iquery";
- break;
case 2:
return "Status";
- break;
case 4:
return "Notify";
- break;
case 5:
return "Update";
- break;
default:
ssnprintf(buf, sizeof (buf), "Opcode%d", o);
return buf;
}
- /* NOTREACHED */
}
const char *rcode_str (int rcode)
ssnprintf (buf, sizeof (buf), "RCode%i", rcode);
return (buf);
}
- /* Never reached */
- return (NULL);
} /* const char *rcode_str (int rcode) */
#if 0
diff --git a/src/utils_dns.h b/src/utils_dns.h
index 83f0ea403e9809ab68c9261299119aa1537278d1..5c547c610a29ed91f3ef76c8e60128f872aa42d6 100644 (file)
--- a/src/utils_dns.h
+++ b/src/utils_dns.h
* Copyright (C) 2006 Florian octo Forster
* Copyright (C) 2002 The Measurement Factory, Inc.
* 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,
#define DNS_MSG_HDR_SZ 12
#define T_MAX 65536
-#define OP_MAX 16
-#define C_MAX 65536
#define MAX_QNAME_SZ 512
struct rfc1035_header_s {
};
typedef struct rfc1035_header_s rfc1035_header_t;
-extern int qtype_counts[T_MAX];
-extern int opcode_counts[OP_MAX];
-extern int qclass_counts[C_MAX];
-
#if HAVE_PCAP_H
void dnstop_set_pcap_obj (pcap_t *po);
#endif
diff --git a/src/utils_fbhash.c b/src/utils_fbhash.c
index cbd150610205255a8a20478a324175a7feebd35a..893bfbd49bded329e7b320cadd28c3da8c42bd5f 100644 (file)
--- a/src/utils_fbhash.c
+++ b/src/utils_fbhash.c
**/
#include "collectd.h"
-#include "plugin.h"
-#include <pthread.h>
+#include "plugin.h"
#include "utils_fbhash.h"
#include "utils_avltree.h"
{
FILE *fh;
char buffer[4096];
- struct flock fl;
+ struct flock fl = { 0 };
c_avl_tree_t *tree;
int status;
if (fh == NULL)
return (-1);
- memset (&fl, 0, sizeof (fl));
fl.l_type = F_RDLCK;
fl.l_whence = SEEK_SET;
- fl.l_start = 0;
- fl.l_len = 0; /* == entire file */
/* TODO: Lock file? -> fcntl */
status = fcntl (fileno (fh), F_SETLK, &fl);
return (-1);
}
- tree = c_avl_create ((void *) strcmp);
+ tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
if (tree == NULL)
{
fclose (fh);
static int fbh_check_file (fbhash_t *h) /* {{{ */
{
- struct stat statbuf;
+ struct stat statbuf = { 0 };
int status;
- memset (&statbuf, 0, sizeof (statbuf));
-
status = stat (h->filename, &statbuf);
if (status != 0)
return (-1);
if (file == NULL)
return (NULL);
- h = malloc (sizeof (*h));
+ h = calloc (1, sizeof (*h));
if (h == NULL)
return (NULL);
- memset (h, 0, sizeof (*h));
h->filename = strdup (file);
if (h->filename == NULL)
index 0098051434c27056ee171b78eb9126c6f5938edc..b53f199b242adb24de5ce322b6ad2a2c377a32f1 100644 (file)
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
static void gr_copy_escape_part (char *dst, const char *src, size_t dst_len,
char escape_char)
{
- size_t i;
-
memset (dst, 0, dst_len);
if (src == NULL)
return;
- for (i = 0; i < dst_len; i++)
+ for (size_t i = 0; i < dst_len; i++)
{
if (src[i] == 0)
{
static void escape_graphite_string (char *buffer, char escape_char)
{
- char *head;
-
assert (strchr(GRAPHITE_FORBIDDEN, escape_char) == NULL);
- for (head = buffer + strcspn(buffer, GRAPHITE_FORBIDDEN);
+ for (char *head = buffer + strcspn(buffer, GRAPHITE_FORBIDDEN);
*head != '\0';
head += strcspn(head, GRAPHITE_FORBIDDEN))
*head = escape_char;
unsigned int flags)
{
int status = 0;
- int i;
int buffer_pos = 0;
gauge_t *rates = NULL;
if (flags & GRAPHITE_STORE_RATES)
rates = uc_get_rate (ds, vl);
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
char const *ds_name = NULL;
char key[10*DATA_MAX_NAME_LEN];
index 398defbeabab0b31c8de7916df1ba2b9e86eca8c..60576dacb913d363947e40f1111d7cd701c33e13 100644 (file)
#define UTILS_FORMAT_GRAPHITE_H 1
#include "collectd.h"
+
#include "plugin.h"
#define GRAPHITE_STORE_RATES 0x01
index 020d80beacb5f8401d26ec891a202cd2da226db1..5b5fcdf0536170b5cae56c3230f90e7e95995dc9 100644 (file)
--- a/src/utils_format_json.c
+++ b/src/utils_format_json.c
/**
* collectd - src/utils_format_json.c
- * Copyright (C) 2009 Florian octo Forster
+ * Copyright (C) 2009-2015 Florian octo Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
**/
#include "collectd.h"
+
+#include "utils_format_json.h"
+
#include "plugin.h"
#include "common.h"
-
#include "utils_cache.h"
-#include "utils_format_json.h"
+
+#if HAVE_LIBYAJL
+# include <yajl/yajl_common.h>
+# include <yajl/yajl_gen.h>
+# if HAVE_YAJL_YAJL_VERSION_H
+# include <yajl/yajl_version.h>
+# endif
+# if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+# define HAVE_YAJL_V2 1
+# endif
+#endif
static int json_escape_string (char *buffer, size_t buffer_size, /* {{{ */
const char *string)
{
- size_t src_pos;
size_t dst_pos;
if ((buffer == NULL) || (string == NULL))
/* Escape special characters */
BUFFER_ADD ('"');
- for (src_pos = 0; string[src_pos] != 0; src_pos++)
+ for (size_t src_pos = 0; string[src_pos] != 0; src_pos++)
{
if ((string[src_pos] == '"')
|| (string[src_pos] == '\\'))
const data_set_t *ds, const value_list_t *vl, int store_rates)
{
size_t offset = 0;
- int i;
gauge_t *rates = NULL;
memset (buffer, 0, buffer_size);
} while (0)
BUFFER_ADD ("[");
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if (i > 0)
BUFFER_ADD (",");
const data_set_t *ds)
{
size_t offset = 0;
- int i;
memset (buffer, 0, buffer_size);
} while (0)
BUFFER_ADD ("[");
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if (i > 0)
BUFFER_ADD (",");
const data_set_t *ds)
{
size_t offset = 0;
- int i;
memset (buffer, 0, buffer_size);
} while (0)
BUFFER_ADD ("[");
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if (i > 0)
BUFFER_ADD (",");
{
size_t offset = 0;
int status;
- size_t i;
buffer[0] = 0;
offset += ((size_t) status); \
} while (0)
- for (i = 0; i < keys_num; ++i)
+ for (size_t i = 0; i < keys_num; ++i)
{
int type;
char *key = keys[i];
}
} /* for (keys) */
- if (offset <= 0)
+ if (offset == 0)
return (ENOENT);
buffer[0] = '{'; /* replace leading ',' */
char **keys = NULL;
size_t keys_num;
int status;
- size_t i;
if ((buffer == NULL) || (buffer_size == 0) || (meta == NULL))
return (EINVAL);
status = meta_data_keys_to_json (buffer, buffer_size, meta, keys, keys_num);
- for (i = 0; i < keys_num; ++i)
+ for (size_t i = 0; i < keys_num; ++i)
sfree (keys[i]);
sfree (keys);
store_rates, (*ret_buffer_free) - 2));
} /* }}} int format_json_value_list */
+#if HAVE_LIBYAJL
+static int json_add_string (yajl_gen g, char const *str) /* {{{ */
+{
+ if (str == NULL)
+ return (int) yajl_gen_null (g);
+
+ return (int) yajl_gen_string (g, (unsigned char const *) str, (unsigned int) strlen (str));
+} /* }}} int json_add_string */
+
+#define JSON_ADD(g, str) do { \
+ yajl_gen_status status = json_add_string (g, str); \
+ if (status != yajl_gen_status_ok) { return -1; } \
+} while (0)
+
+#define JSON_ADDF(g, format, ...) do { \
+ char *str = ssnprintf_alloc (format, __VA_ARGS__); \
+ yajl_gen_status status = json_add_string (g, str); \
+ free (str); \
+ if (status != yajl_gen_status_ok) { return -1; } \
+} while (0)
+
+static int format_json_meta (yajl_gen g, notification_meta_t *meta) /* {{{ */
+{
+ if (meta == NULL)
+ return 0;
+
+ JSON_ADD (g, meta->name);
+ switch (meta->type)
+ {
+ case NM_TYPE_STRING:
+ JSON_ADD (g, meta->nm_value.nm_string);
+ break;
+ case NM_TYPE_SIGNED_INT:
+ JSON_ADDF (g, "%"PRIi64, meta->nm_value.nm_signed_int);
+ break;
+ case NM_TYPE_UNSIGNED_INT:
+ JSON_ADDF (g, "%"PRIu64, meta->nm_value.nm_unsigned_int);
+ break;
+ case NM_TYPE_DOUBLE:
+ JSON_ADDF (g, JSON_GAUGE_FORMAT, meta->nm_value.nm_double);
+ break;
+ case NM_TYPE_BOOLEAN:
+ JSON_ADD (g, meta->nm_value.nm_boolean ? "true" : "false");
+ break;
+ default:
+ ERROR ("format_json_meta: unknown meta data type %d (name \"%s\")", meta->type, meta->name);
+ yajl_gen_null (g);
+ }
+
+ return format_json_meta (g, meta->next);
+} /* }}} int format_json_meta */
+
+static int format_time (yajl_gen g, cdtime_t t) /* {{{ */
+{
+ char buffer[RFC3339NANO_SIZE] = "";
+
+ if (rfc3339nano (buffer, sizeof (buffer), t) != 0)
+ return -1;
+
+ JSON_ADD (g, buffer);
+ return 0;
+} /* }}} int format_time */
+
+static int format_alert (yajl_gen g, notification_t const *n) /* {{{ */
+{
+ yajl_gen_array_open (g);
+ yajl_gen_map_open (g); /* BEGIN alert */
+
+ /*
+ * labels
+ */
+ JSON_ADD (g, "labels");
+ yajl_gen_map_open (g); /* BEGIN labels */
+
+ JSON_ADD (g, "alertname");
+ if (strncmp (n->plugin, n->type, strlen (n->plugin)) == 0)
+ JSON_ADDF (g, "collectd_%s", n->type);
+ else
+ JSON_ADDF (g, "collectd_%s_%s", n->plugin, n->type);
+
+ JSON_ADD (g, "instance");
+ JSON_ADD (g, n->host);
+
+ /* mangling of plugin instance and type instance into labels is copied from
+ * the Prometheus collectd exporter. */
+ if (strlen (n->plugin_instance) > 0)
+ {
+ JSON_ADD (g, n->plugin);
+ JSON_ADD (g, n->plugin_instance);
+ }
+ if (strlen (n->type_instance) > 0)
+ {
+ if (strlen (n->plugin_instance) > 0)
+ JSON_ADD (g, "type");
+ else
+ JSON_ADD (g, n->plugin);
+ JSON_ADD (g, n->type_instance);
+ }
+
+ JSON_ADD (g, "severity");
+ JSON_ADD (g, (n->severity == NOTIF_FAILURE) ? "FAILURE"
+ : (n->severity == NOTIF_WARNING) ? "WARNING"
+ : (n->severity == NOTIF_OKAY) ? "OKAY"
+ : "UNKNOWN");
+
+ JSON_ADD (g, "service");
+ JSON_ADD (g, "collectd");
+
+ yajl_gen_map_close (g); /* END labels */
+
+ /*
+ * annotations
+ */
+ JSON_ADD (g, "annotations");
+ yajl_gen_map_open (g); /* BEGIN annotations */
+
+ JSON_ADD (g, "summary");
+ JSON_ADD (g, n->message);
+
+ if (format_json_meta (g, n->meta) != 0)
+ return -1;
+
+ yajl_gen_map_close (g); /* END annotations */
+
+ JSON_ADD (g, "startsAt");
+ format_time (g, n->time);
+
+ yajl_gen_map_close (g); /* END alert */
+ yajl_gen_array_close (g);
+
+ return 0;
+} /* }}} format_alert */
+
+/*
+ * Format (prometheus/alertmanager v1):
+ *
+ * [{
+ * "labels": {
+ * "alertname": "collectd_cpu",
+ * "instance": "host.example.com",
+ * "severity": "FAILURE",
+ * "service": "collectd",
+ * "cpu": "0",
+ * "type": "wait"
+ * },
+ * "annotations": {
+ * "summary": "...",
+ * // meta
+ * },
+ * "startsAt": <rfc3339 time>,
+ * "endsAt": <rfc3339 time>, // not used
+ * }]
+ */
+int format_json_notification (char *buffer, size_t buffer_size, /* {{{ */
+ notification_t const *n)
+{
+ yajl_gen g;
+ unsigned char const *out;
+#if HAVE_YAJL_V2
+ size_t unused_out_len;
+#else
+ unsigned int unused_out_len;
+#endif
+
+ if ((buffer == NULL) || (n == NULL))
+ return EINVAL;
+
+#if HAVE_YAJL_V2
+ g = yajl_gen_alloc (NULL);
+ if (g == NULL)
+ return -1;
+# if COLLECT_DEBUG
+ yajl_gen_config (g, yajl_gen_beautify, 1);
+ yajl_gen_config (g, yajl_gen_validate_utf8, 1);
+# endif
+
+#else /* !HAVE_YAJL_V2 */
+ yajl_gen_config conf = { 0 };
+# if COLLECT_DEBUG
+ conf.beautify = 1;
+ conf.indentString = " ";
+# endif
+ g = yajl_gen_alloc (&conf, NULL);
+ if (g == NULL)
+ return -1;
+#endif
+
+ if (format_alert (g, n) != 0)
+ {
+ yajl_gen_clear (g);
+ yajl_gen_free (g);
+ return -1;
+ }
+
+ /* copy to output buffer */
+ yajl_gen_get_buf (g, &out, &unused_out_len);
+ sstrncpy (buffer, (void *) out, buffer_size);
+
+ yajl_gen_clear (g);
+ yajl_gen_free (g);
+ return 0;
+} /* }}} format_json_notification */
+#else
+int format_json_notification (char *buffer, size_t buffer_size, /* {{{ */
+ notification_t const *n)
+{
+ ERROR ("format_json_notification: Not available (requires libyajl).");
+ return ENOTSUP;
+} /* }}} int format_json_notification */
+#endif
+
/* vim: set sw=2 sts=2 et fdm=marker : */
index f1fbb6e72766d7895446f322644ecedb4c70e617..a3eda30413b87b7a364640ef44623d2e3c2f4a72 100644 (file)
--- a/src/utils_format_json.h
+++ b/src/utils_format_json.h
#define UTILS_FORMAT_JSON_H 1
#include "collectd.h"
+
#include "plugin.h"
#ifndef JSON_GAUGE_FORMAT
const data_set_t *ds, const value_list_t *vl, int store_rates);
int format_json_finalize (char *buffer,
size_t *ret_buffer_fill, size_t *ret_buffer_free);
+int format_json_notification (char *buffer, size_t buffer_size,
+ notification_t const *n);
#endif /* UTILS_FORMAT_JSON_H */
diff --git a/src/utils_format_json_test.c b/src/utils_format_json_test.c
--- /dev/null
@@ -0,0 +1,182 @@
+/**
+ * collectd - src/utils_format_json_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+/* Workaround for Solaris 10 defining label_t
+ * Issue #1301
+ */
+
+#include "config.h"
+#if KERNEL_SOLARIS
+# ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200112L
+# endif
+# undef __EXTENSIONS__
+#endif
+
+#include "collectd.h"
+
+#include "testing.h"
+#include "utils_format_json.h"
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+
+#include <yajl/yajl_common.h>
+#include <yajl/yajl_parse.h>
+#if HAVE_YAJL_YAJL_VERSION_H
+# include <yajl/yajl_version.h>
+#endif
+#if YAJL_MAJOR > 1
+# define HAVE_YAJL_V2 1
+#endif
+
+typedef struct
+{
+ char const *key;
+ char const *value;
+} label_t;
+
+typedef struct
+{
+ label_t *expected_labels;
+ size_t expected_labels_num;
+
+ label_t *current_label;
+} test_case_t;
+
+#if HAVE_YAJL_V2
+static int test_map_key (void *ctx, unsigned char const *key, size_t key_len)
+#else
+static int test_map_key (void *ctx, unsigned char const *key, unsigned int key_len)
+#endif
+{
+ test_case_t *c = ctx;
+ size_t i;
+
+ c->current_label = NULL;
+ for (i = 0; i < c->expected_labels_num; i++)
+ {
+ label_t *l = c->expected_labels + i;
+ if ((strlen (l->key) == key_len)
+ && (strncmp (l->key, (char const *) key, key_len) == 0))
+ {
+ c->current_label = l;
+ break;
+ }
+ }
+
+ return 1; /* continue */
+}
+
+static int expect_label (char const *name, char const *got, char const *want)
+{
+ _Bool ok = (strcmp (got, want) == 0);
+ char msg[1024];
+
+ if (ok)
+ snprintf (msg, sizeof (msg), "label[\"%s\"] = \"%s\"", name, got);
+ else
+ snprintf (msg, sizeof (msg), "label[\"%s\"] = \"%s\", want \"%s\"", name, got, want);
+
+ OK1 (ok, msg);
+ return 0;
+}
+
+#if HAVE_YAJL_V2
+static int test_string (void *ctx, unsigned char const *value, size_t value_len)
+#else
+static int test_string (void *ctx, unsigned char const *value, unsigned int value_len)
+#endif
+{
+ test_case_t *c = ctx;
+
+ if (c->current_label != NULL)
+ {
+ label_t *l = c->current_label;
+ char *got;
+ int status;
+
+ got = malloc (value_len + 1);
+ memmove (got, value, value_len);
+ got[value_len] = 0;
+
+ status = expect_label (l->key, got, l->value);
+
+ free (got);
+
+ if (status != 0)
+ return 0; /* abort */
+ }
+
+ return 1; /* continue */
+}
+
+static int expect_json_labels (char *json, label_t *labels, size_t labels_num)
+{
+ yajl_callbacks funcs = {
+ .yajl_string = test_string,
+ .yajl_map_key = test_map_key,
+ };
+
+ test_case_t c = { labels, labels_num, NULL };
+
+ yajl_handle hndl;
+#if HAVE_YAJL_V2
+ CHECK_NOT_NULL (hndl = yajl_alloc (&funcs, /* alloc = */ NULL, &c));
+#else
+ CHECK_NOT_NULL (hndl = yajl_alloc (&funcs, /* config = */ NULL, /* alloc = */ NULL, &c));
+#endif
+ OK (yajl_parse (hndl, (unsigned char *) json, strlen (json)) == yajl_status_ok);
+
+ yajl_free (hndl);
+ return 0;
+}
+
+DEF_TEST(notification)
+{
+ label_t labels[] = {
+ {"summary", "this is a message"},
+ {"alertname", "collectd_unit_test"},
+ {"instance", "example.com"},
+ {"service", "collectd"},
+ {"unit", "case"},
+ };
+
+ /* 1448284606.125 ^= 1555083754651779072 */
+ notification_t n = { NOTIF_WARNING, 1555083754651779072ULL, "this is a message",
+ "example.com", "unit", "", "test", "case", NULL };
+
+ char got[1024];
+ CHECK_ZERO (format_json_notification (got, sizeof (got), &n));
+ // printf ("got = \"%s\";\n", got);
+
+ return expect_json_labels (got, labels, STATIC_ARRAY_SIZE (labels));
+}
+
+int main (void)
+{
+ RUN_TEST(notification);
+
+ END_TEST;
+}
diff --git a/src/utils_format_kairosdb.c b/src/utils_format_kairosdb.c
--- /dev/null
@@ -0,0 +1,378 @@
+/**
+ * collectd - src/utils_format_kairosdb.c
+ * Copyright (C) 2016 Aurelien beorn Rougemont
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Aurelien beorn Rougemont <beorn at gandi dot net>
+ **/
+
+
+#include "collectd.h"
+
+#include "plugin.h"
+#include "common.h"
+
+#include "utils_cache.h"
+#include "utils_format_kairosdb.h"
+
+
+/* This is the KAIROSDB format for write_http output
+ *
+ * Target format
+ * [
+ * {
+ * "name":"collectd.vmem"
+ * "datapoints":
+ * [
+ * [1453897164060, 97.000000]
+ * ],
+ * "tags":
+ * {
+ * "host": "fqdn.domain.tld",
+ * "plugin_instance": "vmpage_number",
+ * "type": "kernel_stack",
+ * "ds": "value"
+ * ""
+ * }
+ * }
+ * ]
+ */
+
+static int kairosdb_escape_string (char *buffer, size_t buffer_size, /* {{{ */
+ const char *string)
+{
+ size_t dst_pos;
+
+ if ((buffer == NULL) || (string == NULL))
+ return (-EINVAL);
+
+ if (buffer_size < 3)
+ return (-ENOMEM);
+
+ dst_pos = 0;
+
+#define BUFFER_ADD(c) do { \
+ if (dst_pos >= (buffer_size - 1)) { \
+ buffer[buffer_size - 1] = 0; \
+ return (-ENOMEM); \
+ } \
+ buffer[dst_pos] = (c); \
+ dst_pos++; \
+} while (0)
+
+ /* Escape special characters */
+ /* authorize -_. and alpha num but also escapes " */
+ BUFFER_ADD ('"');
+ for (size_t src_pos = 0; string[src_pos] != 0; src_pos++)
+ {
+ if (isalnum(string[src_pos]) ||
+ 0x2d == string[src_pos] ||
+ 0x2e == string[src_pos] ||
+ 0x5f == string[src_pos])
+ BUFFER_ADD (tolower(string[src_pos]));
+ } /* for */
+ BUFFER_ADD ('"');
+ buffer[dst_pos] = 0;
+
+#undef BUFFER_ADD
+
+ return (0);
+} /* }}} int kairosdb_escape_string */
+
+static int values_to_kairosdb (char *buffer, size_t buffer_size, /* {{{ */
+ const data_set_t *ds, const value_list_t *vl, int store_rates,
+ size_t ds_idx)
+{
+ size_t offset = 0;
+ gauge_t *rates = NULL;
+
+ memset (buffer, 0, buffer_size);
+
+#define BUFFER_ADD(...) do { \
+ int status; \
+ status = ssnprintf (buffer + offset, buffer_size - offset, \
+ __VA_ARGS__); \
+ if (status < 1) \
+ { \
+ sfree(rates); \
+ return (-1); \
+ } \
+ else if (((size_t) status) >= (buffer_size - offset)) \
+ { \
+ sfree(rates); \
+ return (-ENOMEM); \
+ } \
+ else \
+ offset += ((size_t) status); \
+} while (0)
+
+ if (ds->ds[ds_idx].type == DS_TYPE_GAUGE)
+ {
+ if (isfinite (vl->values[ds_idx].gauge))
+ {
+ BUFFER_ADD ("[[");
+ BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+ BUFFER_ADD (",");
+ BUFFER_ADD (JSON_GAUGE_FORMAT, vl->values[ds_idx].gauge);
+ }
+ else
+ {
+ DEBUG ("utils_format_kairosdb: invalid vl->values[ds_idx].gauge for %s|%s|%s|%s|%s",
+ vl->plugin,
+ vl->plugin_instance,
+ vl->type,
+ vl->type_instance,
+ ds->ds[ds_idx].name);
+ return (-1);
+ }
+ }
+ else if (store_rates)
+ {
+ if (rates == NULL)
+ rates = uc_get_rate (ds, vl);
+ if (rates == NULL)
+ {
+ WARNING ("utils_format_kairosdb: uc_get_rate failed for %s|%s|%s|%s|%s",
+ vl->plugin,
+ vl->plugin_instance,
+ vl->type,
+ vl->type_instance,
+ ds->ds[ds_idx].name);
+
+ return (-1);
+ }
+
+ if (isfinite (rates[ds_idx]))
+ {
+ BUFFER_ADD ("[[");
+ BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+ BUFFER_ADD (",");
+ BUFFER_ADD (JSON_GAUGE_FORMAT, rates[ds_idx]);
+ }
+ else
+ {
+ WARNING ("utils_format_kairosdb: invalid rates[ds_idx] for %s|%s|%s|%s|%s",
+ vl->plugin,
+ vl->plugin_instance,
+ vl->type,
+ vl->type_instance,
+ ds->ds[ds_idx].name);
+ sfree(rates);
+ return (-1);
+ }
+ }
+ else if (ds->ds[ds_idx].type == DS_TYPE_COUNTER)
+ {
+ BUFFER_ADD ("[[");
+ BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+ BUFFER_ADD (",");
+ BUFFER_ADD ("%llu", vl->values[ds_idx].counter);
+ }
+ else if (ds->ds[ds_idx].type == DS_TYPE_DERIVE)
+ {
+ BUFFER_ADD ("[[");
+ BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+ BUFFER_ADD (",");
+ BUFFER_ADD ("%"PRIi64, vl->values[ds_idx].derive);
+ }
+ else if (ds->ds[ds_idx].type == DS_TYPE_ABSOLUTE)
+ {
+ BUFFER_ADD ("[[");
+ BUFFER_ADD ("%"PRIu64, CDTIME_T_TO_MS (vl->time));
+ BUFFER_ADD (",");
+ BUFFER_ADD ("%"PRIu64, vl->values[ds_idx].absolute);
+ }
+ else
+ {
+ ERROR ("format_kairosdb: Unknown data source type: %i",
+ ds->ds[ds_idx].type);
+ sfree (rates);
+ return (-1);
+ }
+ BUFFER_ADD ("]]");
+
+#undef BUFFER_ADD
+
+ DEBUG ("format_kairosdb: values_to_kairosdb: buffer = %s;", buffer);
+ sfree(rates);
+ return (0);
+} /* }}} int values_to_kairosdb */
+
+static int value_list_to_kairosdb (char *buffer, size_t buffer_size, /* {{{ */
+ const data_set_t *ds, const value_list_t *vl, int store_rates)
+{
+ char temp[512];
+ size_t offset = 0;
+ int status;
+
+ memset (buffer, 0, buffer_size);
+
+#define BUFFER_ADD(...) do { \
+ status = ssnprintf (buffer + offset, buffer_size - offset, \
+ __VA_ARGS__); \
+ if (status < 1) \
+ return (-1); \
+ else if (((size_t) status) >= (buffer_size - offset)) \
+ return (-ENOMEM); \
+ else \
+ offset += ((size_t) status); \
+} while (0)
+
+#define BUFFER_ADD_KEYVAL(key, value) do { \
+ status = kairosdb_escape_string (temp, sizeof (temp), (value)); \
+ if (status != 0) \
+ return (status); \
+ BUFFER_ADD (",\"%s\": %s", (key), temp); \
+} while (0)
+
+ for (size_t i = 0; i < ds->ds_num; i++)
+ {
+ /* All value lists have a leading comma. The first one will be replaced with
+ * a square bracket in `format_kairosdb_finalize'. */
+ BUFFER_ADD (",{");
+
+ BUFFER_ADD ("\"name\":\"collectd");
+
+ BUFFER_ADD (".%s", vl->plugin);
+
+ status = values_to_kairosdb (temp, sizeof (temp), ds, vl, store_rates, i);
+ if (status != 0)
+ return (status);
+
+ BUFFER_ADD ("\", \"datapoints\": %s", temp);
+
+ /*
+ * Now adds meta data to metric as tags
+ */
+
+ memset (temp, 0, sizeof(temp));
+
+ BUFFER_ADD (", \"tags\":\{");
+
+ BUFFER_ADD ("\"host\": \"%s\"", vl->host);
+ if (strlen(vl->plugin_instance))
+ BUFFER_ADD_KEYVAL ("plugin_instance", vl->plugin_instance);
+ BUFFER_ADD_KEYVAL ("type", vl->type);
+ if (strlen(vl->type_instance))
+ BUFFER_ADD_KEYVAL ("type_instance", vl->type_instance);
+ if (ds->ds_num != 1)
+ BUFFER_ADD_KEYVAL ("ds", ds->ds[i].name);
+ BUFFER_ADD ("}}");
+ } /* for ds->ds_num */
+
+#undef BUFFER_ADD_KEYVAL
+#undef BUFFER_ADD
+
+ DEBUG ("format_kairosdb: value_list_to_kairosdb: buffer = %s;", buffer);
+
+ return (0);
+} /* }}} int value_list_to_kairosdb */
+
+static int format_kairosdb_value_list_nocheck (char *buffer, /* {{{ */
+ size_t *ret_buffer_fill, size_t *ret_buffer_free,
+ const data_set_t *ds, const value_list_t *vl,
+ int store_rates, size_t temp_size)
+{
+ char temp[temp_size];
+ int status;
+
+ status = value_list_to_kairosdb (temp, sizeof (temp), ds, vl, store_rates);
+ if (status != 0)
+ return (status);
+ temp_size = strlen (temp);
+
+ memcpy (buffer + (*ret_buffer_fill), temp, temp_size + 1);
+ (*ret_buffer_fill) += temp_size;
+ (*ret_buffer_free) -= temp_size;
+
+ return (0);
+} /* }}} int format_kairosdb_value_list_nocheck */
+
+int format_kairosdb_initialize (char *buffer, /* {{{ */
+ size_t *ret_buffer_fill, size_t *ret_buffer_free)
+{
+ size_t buffer_fill;
+ size_t buffer_free;
+
+ if ((buffer == NULL) || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL))
+ return (-EINVAL);
+
+ buffer_fill = *ret_buffer_fill;
+ buffer_free = *ret_buffer_free;
+
+ buffer_free = buffer_fill + buffer_free;
+ buffer_fill = 0;
+
+ if (buffer_free < 3)
+ return (-ENOMEM);
+
+ memset (buffer, 0, buffer_free);
+ *ret_buffer_fill = buffer_fill;
+ *ret_buffer_free = buffer_free;
+
+ return (0);
+} /* }}} int format_kairosdb_initialize */
+
+int format_kairosdb_finalize (char *buffer, /* {{{ */
+ size_t *ret_buffer_fill, size_t *ret_buffer_free)
+{
+ size_t pos;
+
+ if ((buffer == NULL) || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL))
+ return (-EINVAL);
+
+ if (*ret_buffer_free < 2)
+ return (-ENOMEM);
+
+ /* Replace the leading comma added in `value_list_to_kairosdb' with a square
+ * bracket. */
+ if (buffer[0] != ',')
+ return (-EINVAL);
+ buffer[0] = '[';
+
+ pos = *ret_buffer_fill;
+ buffer[pos] = ']';
+ buffer[pos+1] = 0;
+
+ (*ret_buffer_fill)++;
+ (*ret_buffer_free)--;
+
+ return (0);
+} /* }}} int format_kairosdb_finalize */
+
+int format_kairosdb_value_list (char *buffer, /* {{{ */
+ size_t *ret_buffer_fill, size_t *ret_buffer_free,
+ const data_set_t *ds, const value_list_t *vl, int store_rates)
+{
+ if ((buffer == NULL)
+ || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL)
+ || (ds == NULL) || (vl == NULL))
+ return (-EINVAL);
+
+ if (*ret_buffer_free < 3)
+ return (-ENOMEM);
+
+ return (format_kairosdb_value_list_nocheck (buffer,
+ ret_buffer_fill, ret_buffer_free, ds, vl,
+ store_rates, (*ret_buffer_free) - 2));
+} /* }}} int format_kairosdb_value_list */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_format_kairosdb.h b/src/utils_format_kairosdb.h
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * collectd - src/utils_format_kairosdb.h
+ * Copyright (C) 2016 Aurelien Rougemont
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Aurelien beorn Rougemont <beorn at gandi dot net>
+ **/
+
+#ifndef UTILS_FORMAT_KAIROSDB_H
+#define UTILS_FORMAT_KAIROSDB_H 1
+
+#include "collectd.h"
+
+#include "plugin.h"
+
+#ifndef JSON_GAUGE_FORMAT
+# define JSON_GAUGE_FORMAT GAUGE_FORMAT
+#endif
+
+int format_kairosdb_initialize (char *buffer,
+ size_t *ret_buffer_fill, size_t *ret_buffer_free);
+int format_kairosdb_value_list (char *buffer,
+ size_t *ret_buffer_fill, size_t *ret_buffer_free,
+ const data_set_t *ds, const value_list_t *vl, int store_rates);
+int format_kairosdb_finalize (char *buffer,
+ size_t *ret_buffer_fill, size_t *ret_buffer_free);
+
+#endif /* UTILS_FORMAT_KAIROSDB_H */
diff --git a/src/utils_latency.c b/src/utils_latency.c
index ca7d5fab3d582672554f344fb9ed60791fdbb1f1..c67752a376b67d1475ef0bc1c45e61aa7064ee58 100644 (file)
--- a/src/utils_latency.c
+++ b/src/utils_latency.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "utils_latency.h"
#include "common.h"
if (lc->num > 0) // if the histogram has data then iterate else skip
{
double width_change_ratio = ((double) old_bin_width) / ((double) new_bin_width);
- size_t i;
- for (i = 0; i < HISTOGRAM_NUM_BINS; i++)
+ for (size_t i = 0; i < HISTOGRAM_NUM_BINS; i++)
{
size_t new_bin = (size_t) (((double) i) * width_change_ratio);
if (i == new_bin)
{
latency_counter_t *lc;
- lc = malloc (sizeof (*lc));
+ lc = calloc (1, sizeof (*lc));
if (lc == NULL)
return (NULL);
- memset (lc, 0, sizeof (*lc));
- latency_counter_reset (lc);
lc->bin_width = HISTOGRAM_DEFAULT_BIN_WIDTH;
+ latency_counter_reset (lc);
return (lc);
} /* }}} latency_counter_t *latency_counter_create */
return;
cdtime_t bin_width = lc->bin_width;
+ cdtime_t max_bin = (lc->max - 1) / lc->bin_width;
+
+/*
+ If max latency is REDUCE_THRESHOLD times less than histogram's range,
+ then cut it in half. REDUCE_THRESHOLD must be >= 2.
+ Value of 4 is selected to reduce frequent changes of bin width.
+*/
+#define REDUCE_THRESHOLD 4
+ if ((lc->num > 0) && (lc->bin_width >= HISTOGRAM_DEFAULT_BIN_WIDTH * 2)
+ && (max_bin < HISTOGRAM_NUM_BINS / REDUCE_THRESHOLD))
+ {
+ /* new bin width will be the previous power of 2 */
+ bin_width = bin_width / 2;
+
+ DEBUG("utils_latency: latency_counter_reset: max_latency = %.3f; "
+ "max_bin = %"PRIu64"; old_bin_width = %.3f; new_bin_width = %.3f;",
+ CDTIME_T_TO_DOUBLE (lc->max),
+ max_bin,
+ CDTIME_T_TO_DOUBLE (lc->bin_width),
+ CDTIME_T_TO_DOUBLE (bin_width));
+ }
+
memset (lc, 0, sizeof (*lc));
/* preserve bin width */
diff --git a/src/utils_latency.h b/src/utils_latency.h
index 2cfa71b6d8eb838e0cd643dcac860f71a7f4b3e3..cb56b082524c87c33f34cf7836b01851bd8176f6 100644 (file)
--- a/src/utils_latency.h
+++ b/src/utils_latency.h
**/
#include "collectd.h"
+
#include "utils_time.h"
struct latency_counter_s;
diff --git a/src/utils_latency_test.c b/src/utils_latency_test.c
--- /dev/null
+++ b/src/utils_latency_test.c
@@ -0,0 +1,107 @@
+/**
+ * collectd - src/utils_latency_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#define DBL_PRECISION 1e-9
+
+#include "common.h" /* for STATIC_ARRAY_SIZE */
+#include "collectd.h"
+
+#include "testing.h"
+#include "utils_time.h"
+#include "utils_latency.h"
+
+DEF_TEST(simple)
+{
+ struct {
+ double val;
+ double min;
+ double max;
+ double sum;
+ double avg;
+ } cases[] = {
+ /* val min max sum avg */
+ {0.5, 0.5, 0.5, 0.5, 0.5},
+ {0.3, 0.3, 0.5, 0.8, 0.4},
+ {0.7, 0.3, 0.7, 1.5, 0.5},
+ {2.5, 0.3, 2.5, 4.0, 1.0},
+ { 99, 0.3, 99, 103, 20.6},
+ /* { -1, 0.3, 99, 103, 20.6}, see issue #1139 */
+ };
+ latency_counter_t *l;
+
+ CHECK_NOT_NULL (l = latency_counter_create ());
+
+ for (size_t i = 0; i < STATIC_ARRAY_SIZE (cases); i++) {
+ printf ("# case %zu: DOUBLE_TO_CDTIME_T(%g) = %"PRIu64"\n",
+ i, cases[i].val, DOUBLE_TO_CDTIME_T (cases[i].val));
+ latency_counter_add (l, DOUBLE_TO_CDTIME_T (cases[i].val));
+
+ EXPECT_EQ_DOUBLE (cases[i].min, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+ EXPECT_EQ_DOUBLE (cases[i].max, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+ EXPECT_EQ_DOUBLE (cases[i].sum, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+ EXPECT_EQ_DOUBLE (cases[i].avg, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+ }
+
+ latency_counter_destroy (l);
+ return 0;
+}
+
+DEF_TEST(percentile)
+{
+ latency_counter_t *l;
+
+ CHECK_NOT_NULL (l = latency_counter_create ());
+
+ for (size_t i = 0; i < 100; i++) {
+ latency_counter_add (l, TIME_T_TO_CDTIME_T (((time_t) i) + 1));
+ }
+
+ EXPECT_EQ_DOUBLE ( 1.0, CDTIME_T_TO_DOUBLE (latency_counter_get_min (l)));
+ EXPECT_EQ_DOUBLE (100.0, CDTIME_T_TO_DOUBLE (latency_counter_get_max (l)));
+ EXPECT_EQ_DOUBLE (100.0 * 101.0 / 2.0, CDTIME_T_TO_DOUBLE (latency_counter_get_sum (l)));
+ EXPECT_EQ_DOUBLE ( 50.5, CDTIME_T_TO_DOUBLE (latency_counter_get_average (l)));
+
+ EXPECT_EQ_DOUBLE (50.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 50.0)));
+ EXPECT_EQ_DOUBLE (80.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 80.0)));
+ EXPECT_EQ_DOUBLE (95.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 95.0)));
+ EXPECT_EQ_DOUBLE (99.0, CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (l, 99.0)));
+
+ CHECK_ZERO (latency_counter_get_percentile (l, -1.0));
+ CHECK_ZERO (latency_counter_get_percentile (l, 101.0));
+
+ latency_counter_destroy (l);
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(simple);
+ RUN_TEST(percentile);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/utils_lua.c b/src/utils_lua.c
--- /dev/null
+++ b/src/utils_lua.c
@@ -0,0 +1,322 @@
+/**
+ * collectd - src/utils_lua.c
+ * Copyright (C) 2010 Florian Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Florian Forster <octo at collectd.org>
+ **/
+
+/* <lua5.1/luaconf.h> defines a macro using "sprintf". Although not used here,
+ * GCC will complain about the macro definition. */
+#define DONT_POISON_SPRINTF_YET
+
+#include "utils_lua.h"
+#include "common.h"
+
+static int ltoc_values(lua_State *L, /* {{{ */
+ const data_set_t *ds, value_t *ret_values) {
+ if (!lua_istable(L, -1)) {
+ WARNING("ltoc_values: not a table");
+ return (-1);
+ }
+
+ /* Push initial key */
+ lua_pushnil(L); /* +1 = 1 */
+ size_t i = 0;
+ while (lua_next(L, -2) != 0) /* -1+2 = 2 || -1 = 0 */
+ {
+ if (i >= ds->ds_num) {
+ lua_pop(L, 2); /* -2 = 0 */
+ i++;
+ break;
+ }
+
+ ret_values[i] = luaC_tovalue(L, -1, ds->ds[i].type);
+
+ /* Pop the value */
+ lua_pop(L, 1); /* -1 = 1 */
+ i++;
+ } /* while (lua_next) */
+
+ if (i != ds->ds_num) {
+ WARNING("ltoc_values: invalid size for datasource \"%s\": expected %zu, "
+ "got %zu",
+ ds->type, ds->ds_num, i);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int ltoc_values */
+
+static int ltoc_table_values(lua_State *L, int idx, /* {{{ */
+ const data_set_t *ds, value_list_t *vl) {
+ /* We're only called from "luaC_tovaluelist", which ensures that "idx" is an
+ * absolute index (i.e. a positive number) */
+ assert(idx > 0);
+
+ lua_getfield(L, idx, "values");
+ if (!lua_istable(L, -1)) {
+ WARNING("utils_lua: ltoc_table_values: The \"values\" member is a %s "
+ "value, not a table.",
+ lua_typename(L, lua_type(L, -1)));
+ lua_pop(L, 1);
+ return (-1);
+ }
+
+ vl->values_len = ds->ds_num;
+ vl->values = calloc(vl->values_len, sizeof(*vl->values));
+ if (vl->values == NULL) {
+ ERROR("utils_lua: calloc failed.");
+ vl->values_len = 0;
+ lua_pop(L, 1);
+ return (-1);
+ }
+
+ int status = ltoc_values(L, ds, vl->values);
+
+ lua_pop(L, 1);
+
+ if (status != 0) {
+ vl->values_len = 0;
+ sfree(vl->values);
+ }
+
+ return (status);
+} /* }}} int ltoc_table_values */
+
+static int luaC_pushvalues(lua_State *L, const data_set_t *ds,
+ const value_list_t *vl) /* {{{ */
+{
+ assert(vl->values_len == ds->ds_num);
+
+ lua_newtable(L);
+ for (size_t i = 0; i < vl->values_len; i++) {
+ lua_pushinteger(L, (lua_Integer)i + 1);
+ luaC_pushvalue(L, vl->values[i], ds->ds[i].type);
+ lua_settable(L, -3);
+ }
+
+ return (0);
+} /* }}} int luaC_pushvalues */
+
+static int luaC_pushdstypes(lua_State *L, const data_set_t *ds) /* {{{ */
+{
+ lua_newtable(L);
+ for (size_t i = 0; i < ds->ds_num; i++) {
+ lua_pushinteger(L, (lua_Integer)i);
+ lua_pushstring(L, DS_TYPE_TO_STRING(ds->ds[i].type));
+ lua_settable(L, -3);
+ }
+
+ return (0);
+} /* }}} int luaC_pushdstypes */
+
+static int luaC_pushdsnames(lua_State *L, const data_set_t *ds) /* {{{ */
+{
+ lua_newtable(L);
+ for (size_t i = 0; i < ds->ds_num; i++) {
+ lua_pushinteger(L, (lua_Integer)i);
+ lua_pushstring(L, ds->ds[i].name);
+ lua_settable(L, -3);
+ }
+
+ return (0);
+} /* }}} int luaC_pushdsnames */
+
+/*
+ * Public functions
+ */
+cdtime_t luaC_tocdtime(lua_State *L, int idx) /* {{{ */
+{
+ if (!lua_isnumber(L, /* stack pos = */ idx))
+ return (0);
+
+ double d = lua_tonumber(L, idx);
+
+ return (DOUBLE_TO_CDTIME_T(d));
+} /* }}} int ltoc_table_cdtime */
+
+int luaC_tostringbuffer(lua_State *L, int idx, /* {{{ */
+ char *buffer, size_t buffer_size) {
+ const char *str = lua_tostring(L, idx);
+ if (str == NULL)
+ return (-1);
+
+ sstrncpy(buffer, str, buffer_size);
+ return (0);
+} /* }}} int luaC_tostringbuffer */
+
+value_t luaC_tovalue(lua_State *L, int idx, int ds_type) /* {{{ */
+{
+ value_t v = { 0 };
+
+ if (!lua_isnumber(L, idx))
+ return (v);
+
+ if (ds_type == DS_TYPE_GAUGE)
+ v.gauge = (gauge_t)lua_tonumber(L, /* stack pos = */ -1);
+ else if (ds_type == DS_TYPE_DERIVE)
+ v.derive = (derive_t)lua_tointeger(L, /* stack pos = */ -1);
+ else if (ds_type == DS_TYPE_COUNTER)
+ v.counter = (counter_t)lua_tointeger(L, /* stack pos = */ -1);
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ v.absolute = (absolute_t)lua_tointeger(L, /* stack pos = */ -1);
+
+ return (v);
+} /* }}} value_t luaC_tovalue */
+
+value_list_t *luaC_tovaluelist(lua_State *L, int idx) /* {{{ */
+{
+#if COLLECT_DEBUG
+ int stack_top_before = lua_gettop(L);
+#endif
+
+ /* Convert relative indexes to absolute indexes, so it doesn't change when we
+ * push / pop stuff. */
+ if (idx < 1)
+ idx += lua_gettop(L) + 1;
+
+ /* Check that idx is in the valid range */
+ if ((idx < 1) || (idx > lua_gettop(L))) {
+ DEBUG("luaC_tovaluelist: idx(%d), top(%d)", idx, stack_top_before);
+ return (NULL);
+ }
+
+ value_list_t *vl = calloc(1, sizeof(*vl));
+ if (vl == NULL) {
+ DEBUG("luaC_tovaluelist: calloc failed");
+ return (NULL);
+ }
+
+ /* Push initial key */
+ lua_pushnil(L);
+ while (lua_next(L, idx) != 0) {
+ const char *key = lua_tostring(L, -2);
+
+ if (key == NULL) {
+ DEBUG("luaC_tovaluelist: Ignoring non-string key.");
+ } else if (strcasecmp("host", key) == 0)
+ luaC_tostringbuffer(L, -1, vl->host, sizeof(vl->host));
+ else if (strcasecmp("plugin", key) == 0)
+ luaC_tostringbuffer(L, -1, vl->plugin, sizeof(vl->plugin));
+ else if (strcasecmp("plugin_instance", key) == 0)
+ luaC_tostringbuffer(L, -1, vl->plugin_instance,
+ sizeof(vl->plugin_instance));
+ else if (strcasecmp("type", key) == 0)
+ luaC_tostringbuffer(L, -1, vl->type, sizeof(vl->type));
+ else if (strcasecmp("type_instance", key) == 0)
+ luaC_tostringbuffer(L, -1, vl->type_instance,
+ sizeof(vl->type_instance));
+ else if (strcasecmp("time", key) == 0)
+ vl->time = luaC_tocdtime(L, -1);
+ else if (strcasecmp("interval", key) == 0)
+ vl->interval = luaC_tocdtime(L, -1);
+ else if (strcasecmp("values", key) == 0) {
+ /* This key is not handled here, because we have to assure "type" is read
+ * first. */
+ } else {
+ DEBUG("luaC_tovaluelist: Ignoring unknown key \"%s\".", key);
+ }
+
+ /* Pop the value */
+ lua_pop(L, 1);
+ }
+
+ const data_set_t *ds = plugin_get_ds(vl->type);
+ if (ds == NULL) {
+ INFO("utils_lua: Unable to lookup type \"%s\".", vl->type);
+ sfree(vl);
+ return (NULL);
+ }
+
+ int status = ltoc_table_values(L, idx, ds, vl);
+ if (status != 0) {
+ WARNING("utils_lua: ltoc_table_values failed.");
+ sfree(vl);
+ return (NULL);
+ }
+
+#if COLLECT_DEBUG
+ assert(stack_top_before == lua_gettop(L));
+#endif
+ return (vl);
+} /* }}} value_list_t *luaC_tovaluelist */
+
+int luaC_pushcdtime(lua_State *L, cdtime_t t) /* {{{ */
+{
+ double d = CDTIME_T_TO_DOUBLE(t);
+
+ lua_pushnumber(L, (lua_Number)d);
+ return (0);
+} /* }}} int luaC_pushcdtime */
+
+int luaC_pushvalue(lua_State *L, value_t v, int ds_type) /* {{{ */
+{
+ if (ds_type == DS_TYPE_GAUGE)
+ lua_pushnumber(L, (lua_Number)v.gauge);
+ else if (ds_type == DS_TYPE_DERIVE)
+ lua_pushinteger(L, (lua_Integer)v.derive);
+ else if (ds_type == DS_TYPE_COUNTER)
+ lua_pushinteger(L, (lua_Integer)v.counter);
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ lua_pushinteger(L, (lua_Integer)v.absolute);
+ else
+ return (-1);
+ return (0);
+} /* }}} int luaC_pushvalue */
+
+int luaC_pushvaluelist(lua_State *L, const data_set_t *ds,
+ const value_list_t *vl) /* {{{ */
+{
+ lua_newtable(L);
+
+ lua_pushstring(L, vl->host);
+ lua_setfield(L, -2, "host");
+
+ lua_pushstring(L, vl->plugin);
+ lua_setfield(L, -2, "plugin");
+ lua_pushstring(L, vl->plugin_instance);
+ lua_setfield(L, -2, "plugin_instance");
+
+ lua_pushstring(L, vl->type);
+ lua_setfield(L, -2, "type");
+ lua_pushstring(L, vl->type_instance);
+ lua_setfield(L, -2, "type_instance");
+
+ luaC_pushvalues(L, ds, vl);
+ lua_setfield(L, -2, "values");
+
+ luaC_pushdstypes(L, ds);
+ lua_setfield(L, -2, "dstypes");
+
+ luaC_pushdsnames(L, ds);
+ lua_setfield(L, -2, "dsnames");
+
+ luaC_pushcdtime(L, vl->time);
+ lua_setfield(L, -2, "time");
+
+ luaC_pushcdtime(L, vl->interval);
+ lua_setfield(L, -2, "interval");
+
+ return (0);
+} /* }}} int luaC_pushvaluelist */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_lua.h b/src/utils_lua.h
--- /dev/null
+++ b/src/utils_lua.h
@@ -0,0 +1,56 @@
+/**
+ * collectd - src/utils_lua.h
+ * Copyright (C) 2010 Florian Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Florian Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_LUA_H
+#define UTILS_LUA_H 1
+
+#include "collectd.h"
+#include "plugin.h"
+
+#ifndef DONT_POISON_SPRINTF_YET
+#error "Files including utils_lua.h need to define DONT_POISON_SPRINTF_YET."
+#endif
+#include <lua.h>
+
+/*
+ * access functions (stack -> C)
+ */
+cdtime_t luaC_tocdtime(lua_State *L, int idx);
+int luaC_tostringbuffer(lua_State *L, int idx, char *buffer,
+ size_t buffer_size);
+value_t luaC_tovalue(lua_State *L, int idx, int ds_type);
+value_list_t *luaC_tovaluelist(lua_State *L, int idx);
+
+/*
+ * push functions (C -> stack)
+ */
+int luaC_pushcdtime(lua_State *L, cdtime_t t);
+int luaC_pushvalue(lua_State *L, value_t v, int ds_type);
+int luaC_pushvaluelist(lua_State *L, const data_set_t *ds,
+ const value_list_t *vl);
+
+#endif /* UTILS_LUA_H */
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_mount.c b/src/utils_mount.c
index 37b52d683ceb4e27154c67140e8cd73111b050da..e527c258a9c1938c0072b3a137d89c60ab5c0a43 100644 (file)
--- a/src/utils_mount.c
+++ b/src/utils_mount.c
#define _GNU_SOURCE
#include "collectd.h"
+
#include "utils_mount.h"
#if HAVE_XFS_XQM_H
FILE *procpt;
char uuid[16], *label = NULL;
char device[110];
- int firstPass;
int handleOnFirst;
if(uuidCache) {
return;
}
- for(firstPass = 1; firstPass >= 0; firstPass--) {
+ for(int firstPass = 1; firstPass >= 0; firstPass--) {
fseek(procpt, 0, SEEK_SET);
while(fgets(line, sizeof(line), procpt)) {
if(sscanf(line, " %d %d %d %[^\n ]",
get_spec_by_uuid(const char *s)
{
char uuid[16];
- int i;
if(strlen(s) != 36
|| s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') {
goto bad_uuid;
}
- for(i=0; i<16; i++) {
+ for(int i=0; i<16; i++) {
if(*s == '-') {
s++;
}
static cu_mount_t *cu_mount_listmntent (void)
{
cu_mount_t *last = *list;
- struct tabmntent *p;
struct mntent *mnt;
struct tabmntent *mntlist;
#endif /* COLLECT_DEBUG */
}
- for(p = mntlist; p; p = p->next) {
+ for(struct tabmntent *p = mntlist; p; p = p->next) {
char *loop = NULL, *device = NULL;
mnt = p->ment;
STRUCT_STATFS *buf;
int num;
- int i;
cu_mount_t *first = NULL;
cu_mount_t *last = NULL;
return (NULL);
}
- if ((buf = (STRUCT_STATFS *) malloc (bufsize * sizeof (STRUCT_STATFS)))
- == NULL)
+ if ((buf = calloc (bufsize, sizeof (*buf))) == NULL)
return (NULL);
- memset (buf, '\0', bufsize * sizeof (STRUCT_STATFS));
/* The bufsize needs to be passed in bytes. Really. This is not in the
* manpage.. -octo */
return (NULL);
}
- for (i = 0; i < num; i++)
+ for (int i = 0; i < num; i++)
{
- if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+ if ((new = calloc (1, sizeof (*new))) == NULL)
break;
- memset (new, '\0', sizeof (cu_mount_t));
-
+
/* Copy values from `struct mnttab' */
new->dir = sstrdup (buf[i].f_mntonname);
new->spec_device = sstrdup (buf[i].f_mntfromname);
while (getmntent (fp, &mt) == 0)
{
- if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+ if ((new = calloc (1, sizeof (*new))) == NULL)
break;
- memset (new, '\0', sizeof (cu_mount_t));
-
+
/* Copy values from `struct mnttab' */
new->dir = sstrdup (mt.mnt_mountp);
new->spec_device = sstrdup (mt.mnt_special);
while (getmntent_r (fp, &me, mntbuf, sizeof (mntbuf) ))
{
- if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+ if ((new = calloc (1, sizeof (*new))) == NULL)
break;
- memset (new, '\0', sizeof (cu_mount_t));
/* Copy values from `struct mntent *' */
new->dir = sstrdup (me.mnt_dir);
while ((me = getmntent (fp)) != NULL)
{
- if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+ if ((new = calloc (1, sizeof (*new))) == NULL)
break;
- memset (new, '\0', sizeof (cu_mount_t));
-
+
/* Copy values from `struct mntent *' */
new->dir = sstrdup (me->mnt_dir);
new->spec_device = sstrdup (me->mnt_fsname);
void cu_mount_freelist (cu_mount_t *list)
{
- cu_mount_t *this;
cu_mount_t *next;
- for (this = list; this != NULL; this = next)
+ for (cu_mount_t *this = list; this != NULL; this = next)
{
next = this->next;
} /* void cu_mount_freelist(cu_mount_t *list) */
char *
-cu_mount_checkoption(char *line, char *keyword, int full)
+cu_mount_checkoption(char *line, const char *keyword, int full)
{
char *line2, *l2, *p1, *p2;
int l;
} /* char *cu_mount_checkoption(char *line, char *keyword, int full) */
char *
-cu_mount_getoptionvalue(char *line, char *keyword)
+cu_mount_getoptionvalue(char *line, const char *keyword)
{
char *r;
if((p-r) == 1) {
return NULL;
}
- m = (char *)smalloc(p-r+1);
+ m = smalloc(p-r+1);
sstrncpy(m, r, p-r+1);
return m;
}
}
return r;
-} /* char *cu_mount_getoptionvalue(char *line, char *keyword) */
+} /* char *cu_mount_getoptionvalue(char *line, const char *keyword) */
int
cu_mount_type(const char *type)
diff --git a/src/utils_mount.h b/src/utils_mount.h
index 7518188dee7e048793802fac33f6824a90d3e434..0a5c980f39be58cd87df3d06667e220677d788af 100644 (file)
--- a/src/utils_mount.h
+++ b/src/utils_mount.h
allocated by *list and *list itself as well.
*/
-char *cu_mount_checkoption(char *line, char *keyword, int full);
+char *cu_mount_checkoption(char *line, const char *keyword, int full);
/*
DESCRIPTION
The cu_mount_checkoption() function is a replacement of
maybe you might want to try cu_mount_getoptionvalue()...
*/
-char *cu_mount_getoptionvalue(char *line, char *keyword);
+char *cu_mount_getoptionvalue(char *line, const char *keyword);
/*
DESCRIPTION
The cu_mount_getoptionvalue() function can be used to grab
diff --git a/src/utils_mount_test.c b/src/utils_mount_test.c
index a16b262c268b254581c22383d907dc6392bdf379..c084debe46381d54e6ffb95cff612e392930ced6 100644 (file)
--- a/src/utils_mount_test.c
+++ b/src/utils_mount_test.c
* Florian octo Forster <octo at collectd.org>
*/
-#include "testing.h"
#include "collectd.h"
+
+#include "common.h"
+#include "testing.h"
#include "utils_mount.h"
#if HAVE_LIBKSTAT
{
char line_opts[] = "foo=one,bar=two,qux=three";
char line_bool[] = "one,two,three";
-
- STREQ ("one", cu_mount_getoptionvalue (line_opts, "foo="));
- STREQ ("two", cu_mount_getoptionvalue (line_opts, "bar="));
- STREQ ("three", cu_mount_getoptionvalue (line_opts, "qux="));
- OK (NULL == cu_mount_getoptionvalue (line_opts, "unknown="));
-
- STREQ ("", cu_mount_getoptionvalue (line_bool, "one"));
- STREQ ("", cu_mount_getoptionvalue (line_bool, "two"));
- STREQ ("", cu_mount_getoptionvalue (line_bool, "three"));
- OK (NULL == cu_mount_getoptionvalue (line_bool, "four"));
+ char *v;
+
+ EXPECT_EQ_STR ("one", v = cu_mount_getoptionvalue (line_opts, "foo="));
+ sfree (v);
+ EXPECT_EQ_STR ("two", v = cu_mount_getoptionvalue (line_opts, "bar="));
+ sfree (v);
+ EXPECT_EQ_STR ("three", v = cu_mount_getoptionvalue (line_opts, "qux="));
+ sfree (v);
+ OK (NULL == (v = cu_mount_getoptionvalue (line_opts, "unknown=")));
+ sfree (v);
+
+ EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "one"));
+ sfree (v);
+ EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "two"));
+ sfree (v);
+ EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "three"));
+ sfree (v);
+ OK (NULL == (v = cu_mount_getoptionvalue (line_bool, "four")));
+ sfree (v);
return (0);
}
index 7f06f2959133fe46724344184d890a5d52befd9a..3652a666c2a73ef99a9c5563d712937cf88ffec0 100644 (file)
--- a/src/utils_parse_option.c
+++ b/src/utils_parse_option.c
**/
#include "collectd.h"
-#include "common.h"
-#include "plugin.h"
+
#include "utils_parse_option.h"
int parse_string (char **ret_buffer, char **ret_string)
buffer++;
}
}
-
+
/* Eat up trailing spaces */
while (isspace ((int) *buffer))
buffer++;
diff --git a/src/utils_rrdcreate.c b/src/utils_rrdcreate.c
index 5add32373cd3d91f861265df88dc459d4bb57c99..884de8f9a77308e521a08ce2da4898492882bb47 100644 (file)
--- a/src/utils_rrdcreate.c
+++ b/src/utils_rrdcreate.c
**/
#include "collectd.h"
+
#include "common.h"
#include "utils_rrdcreate.h"
};
static int rra_timespans_num = STATIC_ARRAY_SIZE (rra_timespans);
-static char *rra_types[] =
+static const char *const rra_types[] =
{
"AVERAGE",
"MIN",
};
static int rra_types_num = STATIC_ARRAY_SIZE (rra_types);
-#if !defined(HAVE_THREADSAFE_LIBRRD) || !HAVE_THREADSAFE_LIBRRD
+#if !defined(HAVE_THREADSAFE_LIBRRD)
static pthread_mutex_t librrd_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
*/
static void rra_free (int rra_num, char **rra_def) /* {{{ */
{
- int i;
-
- for (i = 0; i < rra_num; i++)
+ for (int i = 0; i < rra_num; i++)
{
sfree (rra_def[i]);
}
sfree (args->filename);
if (args->argv != NULL)
{
- int i;
- for (i = 0; i < args->argc; i++)
+ for (int i = 0; i < args->argc; i++)
sfree (args->argv[i]);
sfree (args->argv);
}
{
srrd_create_args_t *args;
- args = malloc (sizeof (*args));
+ args = calloc (1, sizeof (*args));
if (args == NULL)
{
- ERROR ("srrd_create_args_create: malloc failed.");
+ ERROR ("srrd_create_args_create: calloc failed.");
return (NULL);
}
- memset (args, 0, sizeof (*args));
args->filename = NULL;
args->pdp_step = pdp_step;
args->last_up = last_up;
int cdp_num;
int cdp_len;
- int i, j;
/* The stepsize we use here: If it is user-set, use it. If not, use the
* interval of the value-list. */
rra_max = rts_num * rra_types_num;
assert (rra_max > 0);
- if ((rra_def = malloc ((rra_max + 1) * sizeof (*rra_def))) == NULL)
+ if ((rra_def = calloc (rra_max + 1, sizeof (*rra_def))) == NULL)
return (-1);
- memset (rra_def, 0, (rra_max + 1) * sizeof (*rra_def));
rra_num = 0;
cdp_len = 0;
- for (i = 0; i < rts_num; i++)
+ for (int i = 0; i < rts_num; i++)
{
int span = rts[i];
cdp_num = (int) ceil (((double) span)
/ ((double) (cdp_len * ss)));
- for (j = 0; j < rra_types_num; j++)
+ for (int j = 0; j < rra_types_num; j++)
{
char buffer[128];
int status;
static void ds_free (int ds_num, char **ds_def) /* {{{ */
{
- int i;
-
- for (i = 0; i < ds_num; i++)
+ for (int i = 0; i < ds_num; i++)
if (ds_def[i] != NULL)
free (ds_def[i]);
free (ds_def);
const rrdcreate_config_t *cfg)
{
char **ds_def;
- int ds_num;
+ size_t ds_num;
char min[32];
char max[32];
assert (ds->ds_num > 0);
- ds_def = malloc (ds->ds_num * sizeof (*ds_def));
+ ds_def = calloc (ds->ds_num, sizeof (*ds_def));
if (ds_def == NULL)
{
char errbuf[1024];
- ERROR ("rrdtool plugin: malloc failed: %s",
+ ERROR ("rrdtool plugin: calloc failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
- memset (ds_def, 0, ds->ds_num * sizeof (*ds_def));
for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
{
data_source_t *d = ds->ds + ds_num;
- char *type;
+ const char *type;
int status;
ds_def[ds_num] = NULL;
return (-1);
}
- if (ds_num <= 0)
+ if (ds_num == 0)
{
sfree (ds_def);
return (0);
char last_up_str[16];
new_argc = 6 + argc;
- new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+ new_argv = malloc ((new_argc + 1) * sizeof (*new_argv));
if (new_argv == NULL)
{
ERROR ("rrdtool plugin: malloc failed.");
argc = ds_num + rra_num;
- if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
+ if ((argv = malloc (sizeof (*argv) * (argc + 1))) == NULL)
{
char errbuf[1024];
ERROR ("cu_rrd_create_file failed: %s",
diff --git a/src/utils_vl_lookup.c b/src/utils_vl_lookup.c
index f85910e1737e7b5d1c328a6e9e15896be2d60d99..2ca9ddf8e551bd43691dd9b3f4b5d0f3c54188b9 100644 (file)
--- a/src/utils_vl_lookup.c
+++ b/src/utils_vl_lookup.c
#include "collectd.h"
+
#include <pthread.h>
#include <regex.h>
assert (sizeof (match_part->str) > len);
/* strip trailing slash */
match_part->str[len - 2] = 0;
-
+
status = regcomp (&match_part->regex, match_part->str,
/* flags = */ REG_EXTENDED);
if (status != 0)
return (EINVAL);
}
match_part->is_regex = 1;
-
+
return (0);
} /* }}} int lu_copy_ident_to_match_part */
{
user_obj_t *user_obj;
- user_obj = malloc (sizeof (*user_obj));
+ user_obj = calloc (1, sizeof (*user_obj));
if (user_obj == NULL)
{
- ERROR ("utils_vl_lookup: malloc failed.");
+ ERROR ("utils_vl_lookup: calloc failed.");
return (NULL);
}
- memset (user_obj, 0, sizeof (*user_obj));
user_obj->next = NULL;
user_obj->user_obj = obj->cb_user_class (ds, vl, user_class->user_class);
{
user_class_list_t *ptr;
int retval = 0;
-
+
for (ptr = user_class_list; ptr != NULL; ptr = ptr->next)
{
int status;
return (NULL);
}
- by_type = malloc (sizeof (*by_type));
+ by_type = calloc (1, sizeof (*by_type));
if (by_type == NULL)
{
- ERROR ("utils_vl_lookup: malloc failed.");
+ ERROR ("utils_vl_lookup: calloc failed.");
sfree (type_copy);
return (NULL);
}
- memset (by_type, 0, sizeof (*by_type));
by_type->wildcard_plugin_list = NULL;
-
- by_type->by_plugin_tree = c_avl_create ((void *) strcmp);
+
+ by_type->by_plugin_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
if (by_type->by_plugin_tree == NULL)
{
ERROR ("utils_vl_lookup: c_avl_create failed.");
sfree (type_copy);
return (NULL);
}
-
+
return (by_type);
} /* }}} by_type_entry_t *lu_search_by_type */
obj->cb_free_class (user_class_list->entry.user_class);
user_class_list->entry.user_class = NULL;
+#define CLEAR_FIELD(field) do { \
+ if (user_class_list->entry.match.field.is_regex) { \
+ regfree (&user_class_list->entry.match.field.regex); \
+ user_class_list->entry.match.field.is_regex = 0; \
+ } \
+} while (0)
+
+ CLEAR_FIELD (host);
+ CLEAR_FIELD (plugin);
+ CLEAR_FIELD (plugin_instance);
+ CLEAR_FIELD (type);
+ CLEAR_FIELD (type_instance);
+
+#undef CLEAR_FIELD
+
lu_destroy_user_obj (obj, user_class_list->entry.user_obj_list);
user_class_list->entry.user_obj_list = NULL;
pthread_mutex_destroy (&user_class_list->entry.lock);
static void lu_destroy_by_type (lookup_t *obj, /* {{{ */
by_type_entry_t *by_type)
{
-
+
while (42)
{
char *plugin = NULL;
lookup_free_class_callback_t cb_free_class,
lookup_free_obj_callback_t cb_free_obj)
{
- lookup_t *obj = malloc (sizeof (*obj));
+ lookup_t *obj = calloc (1, sizeof (*obj));
if (obj == NULL)
{
- ERROR ("utils_vl_lookup: malloc failed.");
+ ERROR ("utils_vl_lookup: calloc failed.");
return (NULL);
}
- memset (obj, 0, sizeof (*obj));
- obj->by_type_tree = c_avl_create ((void *) strcmp);
+ obj->by_type_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
if (obj->by_type_tree == NULL)
{
ERROR ("utils_vl_lookup: c_avl_create failed.");
if (by_type == NULL)
return (-1);
- user_class_obj = malloc (sizeof (*user_class_obj));
+ user_class_obj = calloc (1, sizeof (*user_class_obj));
if (user_class_obj == NULL)
{
- ERROR ("utils_vl_lookup: malloc failed.");
+ ERROR ("utils_vl_lookup: calloc failed.");
return (ENOMEM);
}
- memset (user_class_obj, 0, sizeof (*user_class_obj));
pthread_mutex_init (&user_class_obj->entry.lock, /* attr = */ NULL);
user_class_obj->entry.user_class = user_class;
lu_copy_ident_to_match (&user_class_obj->entry.match, ident, group_by);
return (status);
retval += status;
}
-
+
return (retval);
} /* }}} lookup_search */
index 6a2676a89e1d8ccee1cddc6735d2f5e7d9335ff7..44660638c4234b79a85e77566f338b7383f33bcd 100644 (file)
* Florian Forster <octo at collectd.org>
**/
-#include "testing.h"
#include "collectd.h"
+
+#include "testing.h"
#include "utils_vl_lookup.h"
static _Bool expect_new_obj = 0;
identifier_t *class = user_class;
identifier_t *obj;
- OK(expect_new_obj);
+ assert (expect_new_obj);
memcpy (&last_class_ident, class, sizeof (last_class_ident));
-
+
obj = malloc (sizeof (*obj));
strncpy (obj->host, vl->host, sizeof (obj->host));
strncpy (obj->plugin, vl->plugin, sizeof (obj->plugin));
return ((void *) obj);
}
-static void checked_lookup_add (lookup_t *obj, /* {{{ */
+static int checked_lookup_add (lookup_t *obj, /* {{{ */
char const *host,
char const *plugin, char const *plugin_instance,
char const *type, char const *type_instance,
identifier_t ident;
void *user_class;
- memset (&ident, 0, sizeof (ident));
strncpy (ident.host, host, sizeof (ident.host));
strncpy (ident.plugin, plugin, sizeof (ident.plugin));
strncpy (ident.plugin_instance, plugin_instance, sizeof (ident.plugin_instance));
memmove (user_class, &ident, sizeof (ident));
OK(lookup_add (obj, &ident, group_by, user_class) == 0);
-} /* }}} void test_add */
+ return 0;
+} /* }}} int checked_lookup_add */
static int checked_lookup_search (lookup_t *obj,
char const *host,
return (status);
}
-static lookup_t *checked_lookup_create (void)
-{
- lookup_t *obj = lookup_create (
- lookup_class_callback,
- lookup_obj_callback,
- (void *) free,
- (void *) free);
- OK(obj != NULL);
- return (obj);
-}
-
DEF_TEST(group_by_specific_host)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/.*/", "test", "", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_search (obj, "host0", "test", "", "test", "0",
DEF_TEST(group_by_any_host)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/.*/", "/.*/", "/.*/", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_search (obj, "host0", "plugin0", "", "test", "0",
DEF_TEST(multiple_lookups)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
int status;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
+
checked_lookup_add (obj, "/.*/", "plugin0", "", "test", "/.*/", LU_GROUP_BY_HOST);
checked_lookup_add (obj, "/.*/", "/.*/", "", "test", "ti0", LU_GROUP_BY_HOST);
DEF_TEST(regex)
{
- lookup_t *obj = checked_lookup_create ();
+ lookup_t *obj;
+ CHECK_NOT_NULL (obj = lookup_create (
+ lookup_class_callback, lookup_obj_callback, (void *) free, (void *) free));
checked_lookup_add (obj, "/^db[0-9]\\./", "cpu", "/.*/", "cpu", "/.*/",
LU_GROUP_BY_TYPE_INSTANCE);
diff --git a/src/uuid.c b/src/uuid.c
index 2df6063984c04b09ebc6365a38144f33c61692f8..8bae376103f0328ec9fb20763ee70c668217e928 100644 (file)
--- a/src/uuid.c
+++ b/src/uuid.c
/**
* collectd - src/uuid.c
* Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2015 Ruben Kerkhof
*
* 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 "collectd.h"
+
#include "common.h"
-#include "configfile.h"
#include "plugin.h"
-#if HAVE_LIBHAL
+#if HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+#if HAVE_LIBHAL_H
#include <libhal.h>
#endif
{
int len;
- if (!uuid) return 0;
+ if (!uuid)
+ return (0);
len = strlen (uuid);
if (len < UUID_PRINTABLE_COMPACT_LENGTH)
- return 0;
+ return (0);
while (*uuid) {
- if (!isxdigit ((int)*uuid) && *uuid != '-') return 0;
+ if (!isxdigit ((int)*uuid) && *uuid != '-')
+ return (0);
uuid++;
}
- return 1;
+ return (1);
}
static char *
if (!looks_like_a_uuid (fields[1]))
continue;
- return strdup (fields[1]);
+ return (strdup (fields[1]));
}
- return NULL;
+ return (NULL);
}
static char *
uuid_get_from_dmidecode(void)
{
- FILE *dmidecode = popen("dmidecode 2>/dev/null", "r");
+ FILE *dmidecode = popen("dmidecode -t system 2>/dev/null", "r");
char *uuid;
- if (!dmidecode) {
- return NULL;
- }
-
+ if (!dmidecode)
+ return (NULL);
+
uuid = uuid_parse_dmidecode(dmidecode);
pclose(dmidecode);
- return uuid;
+ return (uuid);
+}
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+static char *
+uuid_get_from_sysctlbyname(const char *name)
+{
+ char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1];
+ size_t len = sizeof (uuid);
+ if (sysctlbyname(name, &uuid, &len, NULL, 0) == -1)
+ return NULL;
+ return (strdup (uuid));
}
+#elif defined(__OpenBSD__)
+static char *
+uuid_get_from_sysctl(void)
+{
+ char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1];
+ size_t len = sizeof (uuid);
+ int mib[2];
-#if HAVE_LIBHAL
+ mib[0] = CTL_HW;
+ mib[1] = HW_UUID;
+
+ if (sysctl(mib, 2, uuid, &len, NULL, 0) == -1)
+ return NULL;
+ return (strdup (uuid));
+}
+#endif
+
+#if HAVE_LIBHAL_H
#define UUID_PATH "/org/freedesktop/Hal/devices/computer"
#define UUID_PROPERTY "smbios.system.uuid"
dbus_error_init(&error);
- if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) ) {
+ if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)))
goto bailout_nobus;
- }
ctx = libhal_ctx_new();
libhal_ctx_set_dbus_connection(ctx, con);
- if (!libhal_ctx_init(ctx, &error)) {
+ if (!libhal_ctx_init(ctx, &error))
goto bailout;
- }
if (!libhal_device_property_exists(ctx,
UUID_PATH,
UUID_PROPERTY,
- &error)) {
+ &error))
goto bailout;
- }
char *uuid = libhal_device_get_property_string(ctx,
UUID_PATH,
UUID_PROPERTY,
&error);
- if (looks_like_a_uuid (uuid)) {
- return uuid;
- }
+ if (looks_like_a_uuid (uuid))
+ return (uuid);
bailout:
{
DBusError ctxerror;
dbus_error_init(&ctxerror);
- if (!(libhal_ctx_shutdown(ctx, &ctxerror))) {
+ if (!(libhal_ctx_shutdown(ctx, &ctxerror)))
dbus_error_free(&ctxerror);
- }
}
libhal_ctx_free(ctx);
- //dbus_connection_unref(con);
bailout_nobus:
- if (dbus_error_is_set(&error)) {
- /*printf("Error %s\n", error.name);*/
+ if (dbus_error_is_set(&error))
dbus_error_free(&error);
- }
- return NULL;
+ return (NULL);
}
#endif
file = fopen (path, "r");
if (file == NULL)
- return NULL;
+ return (NULL);
if (!fgets(uuid, sizeof(uuid), file)) {
fclose(file);
- return NULL;
+ return (NULL);
}
fclose(file);
strstripnewline (uuid);
- return strdup (uuid);
+ return (strdup (uuid));
}
static char *
char *uuid;
/* Check /etc/uuid / UUIDFile before any other method. */
- if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL){
- return uuid;
- }
+ if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL)
+ return (uuid);
+
+#if defined(__APPLE__)
+ if ((uuid = uuid_get_from_sysctlbyname("kern.uuid")) != NULL)
+ return (uuid);
+#elif defined(__FreeBSD__)
+ if ((uuid = uuid_get_from_sysctlbyname("kern.hostuuid")) != NULL)
+ return (uuid);
+#elif defined(__NetBSD__)
+ if ((uuid = uuid_get_from_sysctlbyname("machdep.dmi.system-uuid")) != NULL)
+ return (uuid);
+#elif defined(__OpenBSD__)
+ if ((uuid = uuid_get_from_sysctl()) != NULL)
+ return (uuid);
+#elif defined(__linux__)
+ if ((uuid = uuid_get_from_file("/sys/class/dmi/id/product_uuid")) != NULL)
+ return (uuid);
+#endif
-#if HAVE_LIBHAL
- if ((uuid = uuid_get_from_hal()) != NULL) {
- return uuid;
- }
+#if HAVE_LIBHAL_H
+ if ((uuid = uuid_get_from_hal()) != NULL)
+ return (uuid);
#endif
- if ((uuid = uuid_get_from_dmidecode()) != NULL) {
- return uuid;
- }
+ if ((uuid = uuid_get_from_dmidecode()) != NULL)
+ return (uuid);
- if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL) {
- return uuid;
- }
+#if defined(__linux__)
+ if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL)
+ return (uuid);
+#endif
- return NULL;
+ return (NULL);
}
static int
if (strcasecmp (key, "UUIDFile") == 0) {
char *tmp = strdup (value);
if (tmp == NULL)
- return -1;
+ return (-1);
sfree (uuidfile);
uuidfile = tmp;
- } else {
- return 1;
+ return (0);
}
- return 0;
+ return (1);
}
static int
if (uuid) {
sstrncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
sfree (uuid);
- return 0;
+ return (0);
}
WARNING ("uuid: could not read UUID using any known method");
- return 0;
+ return (0);
}
void module_register (void)
diff --git a/src/valgrind.FreeBSD.suppress b/src/valgrind.FreeBSD.suppress
--- /dev/null
@@ -0,0 +1,8 @@
+{
+ strlen_bogus_invalid_read_after_strdup
+ Memcheck:Addr4
+ fun:parse_value
+ fun:parse_values
+ fun:test_parse_values
+ fun:main
+}
diff --git a/src/varnish.c b/src/varnish.c
index a138d1813ffaa5109a9310714744a3404e9d6891..6cc092c0041eac9fcb028e179610f1c4cf40606e 100644 (file)
--- a/src/varnish.c
+++ b/src/varnish.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#if HAVE_VARNISH_V4
#include <vapi/vsm.h>
{
struct VSM_data *vd;
const c_varnish_stats_t *stats;
+ _Bool ok;
user_config_t *conf;
}
#if HAVE_VARNISH_V3
- if (VSC_Open (vd, /* diag = */ 1))
+ ok = (VSC_Open (vd, /* diag = */ 1) == 0);
#else /* if HAVE_VARNISH_V4 */
- if (VSM_Open (vd))
+ ok = (VSM_Open (vd) == 0);
#endif
+ if (!ok)
{
VSM_Delete (vd);
ERROR ("varnish plugin: Unable to open connection.");
static int varnish_init (void) /* {{{ */
{
user_config_t *conf;
- user_data_t ud;
if (have_instance)
return (0);
- conf = malloc (sizeof (*conf));
+ conf = calloc (1, sizeof (*conf));
if (conf == NULL)
return (ENOMEM);
- memset (conf, 0, sizeof (*conf));
/* Default settings: */
conf->instance = NULL;
varnish_config_apply_default (conf);
- ud.data = conf;
- ud.free_func = varnish_config_free;
+ user_data_t ud = {
+ .data = conf,
+ .free_func = varnish_config_free
+ };
plugin_register_complex_read (/* group = */ "varnish",
/* name = */ "varnish/localhost",
/* callback = */ varnish_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user data = */ &ud);
return (0);
user_config_t *conf;
user_data_t ud;
char callback_name[DATA_MAX_NAME_LEN];
- int i;
- conf = malloc (sizeof (*conf));
+ conf = calloc (1, sizeof (*conf));
if (conf == NULL)
return (ENOMEM);
- memset (conf, 0, sizeof (*conf));
conf->instance = NULL;
varnish_config_apply_default (conf);
return (EINVAL);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
cf_util_get_boolean (child, &conf->collect_connections);
else if (strcasecmp ("CollectESI", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_esi);
-#ifdef HAVE_VARNISH_V3
else if (strcasecmp ("CollectDirectorDNS", child->key) == 0)
+#ifdef HAVE_VARNISH_V3
cf_util_get_boolean (child, &conf->collect_dirdns);
+#else
+ WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v3");
#endif
else if (strcasecmp ("CollectBackend", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_backend);
cf_util_get_boolean (child, &conf->collect_hcb);
else if (strcasecmp ("CollectObjects", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_objects);
-#if HAVE_VARNISH_V2
else if (strcasecmp ("CollectPurge", child->key) == 0)
+#if HAVE_VARNISH_V2
cf_util_get_boolean (child, &conf->collect_purge);
#else
+ WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v2");
+#endif
else if (strcasecmp ("CollectBan", child->key) == 0)
+#if HAVE_VARNISH_V2
+ WARNING ("Varnish plugin: \"%s\" is not available for Varnish %s.", child->key, "v2");
+#else
cf_util_get_boolean (child, &conf->collect_ban);
#endif
else if (strcasecmp ("CollectSession", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_shm);
else if (strcasecmp ("CollectSMS", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_sms);
-#if HAVE_VARNISH_V2
else if (strcasecmp ("CollectSMA", child->key) == 0)
+#if HAVE_VARNISH_V2
cf_util_get_boolean (child, &conf->collect_sma);
+#else
+ WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v2");
+#endif
else if (strcasecmp ("CollectSM", child->key) == 0)
+#if HAVE_VARNISH_V2
cf_util_get_boolean (child, &conf->collect_sm);
+#else
+ WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v2");
#endif
else if (strcasecmp ("CollectStruct", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_struct);
else if (strcasecmp ("CollectTotals", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_totals);
-#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
else if (strcasecmp ("CollectUptime", child->key) == 0)
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
cf_util_get_boolean (child, &conf->collect_uptime);
+#else
+ WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v3 and v4");
#endif
else if (strcasecmp ("CollectVCL", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_vcl);
else if (strcasecmp ("CollectWorkers", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_workers);
-#if HAVE_VARNISH_V4
else if (strcasecmp ("CollectVSM", child->key) == 0)
+#if HAVE_VARNISH_V4
cf_util_get_boolean (child, &conf->collect_vsm);
+#else
+ WARNING ("Varnish plugin: \"%s\" is available for Varnish %s only.", child->key, "v4");
#endif
else
{
plugin_register_complex_read (/* group = */ "varnish",
/* name = */ callback_name,
/* callback = */ varnish_read,
- /* interval = */ NULL,
+ /* interval = */ 0,
/* user data = */ &ud);
have_instance = 1;
static int varnish_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/virt.c b/src/virt.c
index c9355c4a1cd961417ce8611befb2c1454c488bfe..c1c77bcf135e18ed7e0feff620868915b2a89614 100644 (file)
--- a/src/virt.c
+++ b/src/virt.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_ignorelist.h"
#include "utils_complain.h"
};
static enum plginst_field plugin_instance_format[PLGINST_MAX_FIELDS] =
- { plginst_name };
+ { plginst_none };
/* InterfaceFormat. */
enum if_field {
static void
init_value_list (value_list_t *vl, virDomainPtr dom)
{
- int i, n;
+ int n;
const char *name;
char uuid[VIR_UUID_STRING_BUFLEN];
vl->host[0] = '\0';
/* Construct the hostname field according to HostnameFormat. */
- for (i = 0; i < HF_MAX_FIELDS; ++i) {
+ for (int i = 0; i < HF_MAX_FIELDS; ++i) {
if (hostname_format[i] == hf_none)
continue;
vl->host[sizeof (vl->host) - 1] = '\0';
/* Construct the plugin instance field according to PluginInstanceFormat. */
- for (i = 0; i < PLGINST_MAX_FIELDS; ++i) {
+ for (int i = 0; i < PLGINST_MAX_FIELDS; ++i) {
if (plugin_instance_format[i] == plginst_none)
continue;
if (strcasecmp (key, "HostnameFormat") == 0) {
char *value_copy;
char *fields[HF_MAX_FIELDS];
- int i, n;
+ int n;
value_copy = strdup (value);
if (value_copy == NULL) {
return -1;
}
- for (i = 0; i < n; ++i) {
+ for (int i = 0; i < n; ++i) {
if (strcasecmp (fields[i], "hostname") == 0)
hostname_format[i] = hf_hostname;
else if (strcasecmp (fields[i], "name") == 0)
}
sfree (value_copy);
- for (i = n; i < HF_MAX_FIELDS; ++i)
+ for (int i = n; i < HF_MAX_FIELDS; ++i)
hostname_format[i] = hf_none;
return 0;
if (strcasecmp (key, "PluginInstanceFormat") == 0) {
char *value_copy;
char *fields[PLGINST_MAX_FIELDS];
- int i, n;
+ int n;
value_copy = strdup (value);
if (value_copy == NULL) {
return -1;
}
- for (i = 0; i < n; ++i) {
- if (strcasecmp (fields[i], "name") == 0)
+ for (int i = 0; i < n; ++i) {
+ if (strcasecmp (fields[i], "none") == 0) {
+ plugin_instance_format[i] = plginst_none;
+ break;
+ } else if (strcasecmp (fields[i], "name") == 0)
plugin_instance_format[i] = plginst_name;
else if (strcasecmp (fields[i], "uuid") == 0)
plugin_instance_format[i] = plginst_uuid;
}
sfree (value_copy);
- for (i = n; i < PLGINST_MAX_FIELDS; ++i)
+ for (int i = n; i < PLGINST_MAX_FIELDS; ++i)
plugin_instance_format[i] = plginst_none;
return 0;
lv_read (void)
{
time_t t;
- int i;
if (conn == NULL) {
/* `conn_string == NULL' is acceptable. */
}
#if 0
- for (i = 0; i < nr_domains; ++i)
+ for (int i = 0; i < nr_domains; ++i)
fprintf (stderr, "domain %s\n", virDomainGetName (domains[i]));
- for (i = 0; i < nr_block_devices; ++i)
+ for (int i = 0; i < nr_block_devices; ++i)
fprintf (stderr, "block device %d %s:%s\n",
i, virDomainGetName (block_devices[i].dom),
block_devices[i].path);
- for (i = 0; i < nr_interface_devices; ++i)
+ for (int i = 0; i < nr_interface_devices; ++i)
fprintf (stderr, "interface device %d %s:%s\n",
i, virDomainGetName (interface_devices[i].dom),
interface_devices[i].path);
#endif
/* Get CPU usage, memory, VCPU usage for each domain. */
- for (i = 0; i < nr_domains; ++i) {
+ for (int i = 0; i < nr_domains; ++i) {
virDomainInfo info;
virVcpuInfoPtr vinfo = NULL;
virDomainMemoryStatPtr minfo = NULL;
int status;
- int j;
status = virDomainGetInfo (domains[i], &info);
if (status != 0)
continue;
}
- for (j = 0; j < info.nrVirtCpu; ++j)
+ for (int j = 0; j < info.nrVirtCpu; ++j)
vcpu_submit (vinfo[j].cpuTime,
domains[i], vinfo[j].number, "virt_vcpu");
continue;
}
- status = virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);
+ status = virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);
if (status < 0) {
ERROR ("virt plugin: virDomainMemoryStats failed with status %i.",
continue;
}
- for (j = 0; j < status; j++) {
+ for (int j = 0; j < status; j++) {
memory_stats_submit ((gauge_t) minfo[j].val * 1024, domains[i], minfo[j].tag);
}
/* Get block device stats for each domain. */
- for (i = 0; i < nr_block_devices; ++i) {
+ for (int i = 0; i < nr_block_devices; ++i) {
struct _virDomainBlockStats stats;
if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path,
} /* for (nr_block_devices) */
/* Get interface stats for each domain. */
- for (i = 0; i < nr_interface_devices; ++i) {
+ for (int i = 0; i < nr_interface_devices; ++i) {
struct _virDomainInterfaceStats stats;
char *display_name = NULL;
}
if (n > 0) {
- int i;
int *domids;
/* Get list of domains. */
- domids = malloc (sizeof (int) * n);
- if (domids == 0) {
+ domids = malloc (sizeof (*domids) * n);
+ if (domids == NULL) {
ERROR (PLUGIN_NAME " plugin: malloc failed.");
return -1;
}
free_domains ();
/* Fetch each domain and add it to the list, unless ignore. */
- for (i = 0; i < n; ++i) {
+ for (int i = 0; i < n; ++i) {
virDomainPtr dom = NULL;
const char *name;
char *xml = NULL;
xmlDocPtr xml_doc = NULL;
xmlXPathContextPtr xpath_ctx = NULL;
xmlXPathObjectPtr xpath_obj = NULL;
- int j;
dom = virDomainLookupByID (conn, domids[i]);
if (dom == NULL) {
xpath_obj->nodesetval == NULL)
goto cont;
- for (j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) {
+ for (int j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) {
xmlNodePtr node;
char *path = NULL;
xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval;
- for (j = 0; j < xml_interfaces->nodeNr; ++j) {
+ for (int j = 0; j < xml_interfaces->nodeNr; ++j) {
char *path = NULL;
char *address = NULL;
xmlNodePtr xml_interface;
xml_interface = xml_interfaces->nodeTab[j];
if (!xml_interface) continue;
- xmlNodePtr child = NULL;
- for (child = xml_interface->children; child; child = child->next) {
+ for (xmlNodePtr child = xml_interface->children; child; child = child->next) {
if (child->type != XML_ELEMENT_NODE) continue;
if (xmlStrEqual(child->name, (const xmlChar *) "target")) {
}
static void
-free_domains ()
+free_domains (void)
{
- int i;
-
if (domains) {
- for (i = 0; i < nr_domains; ++i)
+ for (int i = 0; i < nr_domains; ++i)
virDomainFree (domains[i]);
sfree (domains);
}
}
static void
-free_block_devices ()
+free_block_devices (void)
{
- int i;
-
if (block_devices) {
- for (i = 0; i < nr_block_devices; ++i)
+ for (int i = 0; i < nr_block_devices; ++i)
sfree (block_devices[i].path);
sfree (block_devices);
}
}
static void
-free_interface_devices ()
+free_interface_devices (void)
{
- int i;
-
if (interface_devices) {
- for (i = 0; i < nr_interface_devices; ++i) {
+ for (int i = 0; i < nr_interface_devices; ++i) {
sfree (interface_devices[i].path);
sfree (interface_devices[i].address);
sfree (interface_devices[i].number);
diff --git a/src/vmem.c b/src/vmem.c
index 7bb0433cb233f1865bb747d3e5d700437c9df7ca..46ffa13b1108582b3de120decc22180cf569c2d3 100644 (file)
--- a/src/vmem.c
+++ b/src/vmem.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
if (fields[1] == endptr)
continue;
- /*
+ /*
* Number of pages
*
* The total number of {inst} pages, e. g dirty pages.
}
}
- /*
+ /*
* Page in and page outs. For memory and swap.
*/
else if (strcmp ("pgpgin", key) == 0)
diff --git a/src/vserver.c b/src/vserver.c
index 54b3623f4b02758df80473207744b8754224fa0a..806fd921a7fca07dd531a91d0819c3c9d2126505 100644 (file)
--- a/src/vserver.c
+++ b/src/vserver.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
if (proc == NULL)
{
char errbuf[1024];
- ERROR ("vserver plugin: fopen (%s): %s", PROCDIR,
+ ERROR ("vserver plugin: fopen (%s): %s", PROCDIR,
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
len = ssnprintf (file, sizeof (file), PROCDIR "/%s", dent->d_name);
if ((len < 0) || (len >= BUFSIZE))
continue;
-
+
status = stat (file, &statbuf);
if (status != 0)
{
file, sstrerror (errno, errbuf, sizeof (errbuf)));
continue;
}
-
+
if (!S_ISDIR (statbuf.st_mode))
continue;
{
derive_t rx;
derive_t tx;
- char *type_instance;
+ const char *type_instance;
if (strsplit (buffer, cols, 4) < 4)
continue;
if (2 == n)
{
- char *type_instance;
+ const char *type_instance;
gauge_t value;
if (0 == strcmp (cols[0], "nr_threads:"))
while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
{
- char *type = "vs_memory";
- char *type_instance;
+ const char *type = "vs_memory";
+ const char *type_instance;
gauge_t value;
if (strsplit (buffer, cols, 2) < 2)
diff --git a/src/wireless.c b/src/wireless.c
index f2a3cf5832de46792371fbc2ff499ac42efaa114..b998462598fd764c1214ebf5c7d07a7fae81a44d 100644 (file)
--- a/src/wireless.c
+++ b/src/wireless.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
/*
* dbm = 10 * log_{10} (1000 * power / W)
- * power = 10^(dbm/10) * W/1000
+ * power = 10^(dbm/10) * W/1000
*/
watt = pow (10.0, (dbm / 10.0)) / 1000.0;
double quality;
double power;
double noise;
-
+
char *fields[8];
int numfields;
diff --git a/src/write_graphite.c b/src/write_graphite.c
index a7eef3fb435616ca6093207c385eb8ba90a104a2..787445d50678227c96e39013e03a47269a94ecb3 100644 (file)
--- a/src/write_graphite.c
+++ b/src/write_graphite.c
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
-#include "utils_cache.h"
#include "utils_complain.h"
#include "utils_format_graphite.h"
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
-#include <sys/socket.h>
#include <netdb.h>
#ifndef WG_DEFAULT_NODE
pthread_mutex_t send_lock;
c_complain_t init_complaint;
cdtime_t last_connect_time;
+
+ /* Force reconnect useful for load balanced environments */
+ cdtime_t last_reconnect_time;
+ cdtime_t reconnect_interval;
+ _Bool reconnect_interval_reached;
};
+/* wg_force_reconnect_check closes cb->sock_fd when it was open for longer
+ * than cb->reconnect_interval. Must hold cb->send_lock when calling. */
+static void wg_force_reconnect_check (struct wg_callback *cb)
+{
+ cdtime_t now;
+
+ if (cb->reconnect_interval == 0)
+ return;
+
+ /* check if address changes if addr_timeout */
+ now = cdtime ();
+ if ((now - cb->last_reconnect_time) < cb->reconnect_interval)
+ return;
+
+ /* here we should close connection on next */
+ close (cb->sock_fd);
+ cb->sock_fd = -1;
+ cb->last_reconnect_time = now;
+ cb->reconnect_interval_reached = 1;
+
+ INFO ("write_graphite plugin: Connection closed after %.3f seconds.",
+ CDTIME_T_TO_DOUBLE (now - cb->last_reconnect_time));
+}
/*
* Functions
static int wg_send_buffer (struct wg_callback *cb)
{
- ssize_t status = 0;
+ ssize_t status;
+
+ if (cb->sock_fd < 0)
+ return (-1);
status = swrite (cb->sock_fd, cb->send_buf, strlen (cb->send_buf));
if (status != 0)
{
- const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
-
if (cb->log_send_errors)
{
char errbuf[1024];
ERROR ("write_graphite plugin: send to %s:%s (%s) failed with status %zi (%s)",
- cb->node, cb->service, protocol,
+ cb->node, cb->service, cb->protocol,
status, sstrerror (errno, errbuf, sizeof (errbuf)));
}
return (0);
}
- if (cb->send_buf_fill <= 0)
+ if (cb->send_buf_fill == 0)
{
cb->send_buf_init_time = cdtime ();
return (0);
static int wg_callback_init (struct wg_callback *cb)
{
- struct addrinfo ai_hints;
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
cdtime_t now;
int status;
- const char *node = cb->node ? cb->node : WG_DEFAULT_NODE;
- const char *service = cb->service ? cb->service : WG_DEFAULT_SERVICE;
- const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
-
char connerr[1024] = "";
if (cb->sock_fd > 0)
return (EAGAIN);
cb->last_connect_time = now;
- memset (&ai_hints, 0, sizeof (ai_hints));
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG
+ };
- if (0 == strcasecmp ("tcp", protocol))
+ if (0 == strcasecmp ("tcp", cb->protocol))
ai_hints.ai_socktype = SOCK_STREAM;
else
ai_hints.ai_socktype = SOCK_DGRAM;
- ai_list = NULL;
-
- status = getaddrinfo (node, service, &ai_hints, &ai_list);
+ status = getaddrinfo (cb->node, cb->service, &ai_hints, &ai_list);
if (status != 0)
{
ERROR ("write_graphite plugin: getaddrinfo (%s, %s, %s) failed: %s",
- node, service, protocol, gai_strerror (status));
+ cb->node, cb->service, cb->protocol, gai_strerror (status));
return (-1);
}
assert (ai_list != NULL);
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
cb->sock_fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
ai_ptr->ai_protocol);
continue;
}
+ set_sock_opts (cb->sock_fd);
+
status = connect (cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
if (status != 0)
{
sstrerror (errno, connerr, sizeof (connerr));
c_complain (LOG_ERR, &cb->init_complaint,
"write_graphite plugin: Connecting to %s:%s via %s failed. "
- "The last error was: %s", node, service, protocol, connerr);
+ "The last error was: %s", cb->node, cb->service, cb->protocol, connerr);
return (-1);
}
else
{
c_release (LOG_INFO, &cb->init_complaint,
"write_graphite plugin: Successfully connected to %s:%s via %s.",
- node, service, protocol);
+ cb->node, cb->service, cb->protocol);
}
- wg_reset_buffer (cb);
+ /* wg_force_reconnect_check does not flush the buffer before closing a
+ * sending socket, so only call wg_reset_buffer() if the socket was closed
+ * for a different reason (tracked in cb->reconnect_interval_reached). */
+ if (!cb->reconnect_interval_reached || (cb->send_buf_free == 0))
+ wg_reset_buffer (cb);
+ else
+ cb->reconnect_interval_reached = 0;
return (0);
}
pthread_mutex_lock (&cb->send_lock);
+ wg_force_reconnect_check (cb);
+
if (cb->sock_fd < 0)
{
status = wg_callback_init (cb);
cb->send_buf_free -= message_len;
DEBUG ("write_graphite plugin: [%s]:%s (%s) buf %zu/%zu (%.1f %%) \"%s\"",
- cb->node,
- cb->service,
- cb->protocol,
+ cb->node, cb->service, cb->protocol,
cb->send_buf_fill, sizeof (cb->send_buf),
100.0 * ((double) cb->send_buf_fill) / ((double) sizeof (cb->send_buf)),
message);
static int wg_write_messages (const data_set_t *ds, const value_list_t *vl,
struct wg_callback *cb)
{
- char buffer[WG_SEND_BUF_SIZE];
+ char buffer[WG_SEND_BUF_SIZE] = { 0 };
int status;
if (0 != strcmp (ds->type, vl->type))
return -1;
}
- memset (buffer, 0, sizeof (buffer));
status = format_graphite (buffer, sizeof (buffer), ds, vl,
cb->prefix, cb->postfix, cb->escape_char, cb->format_flags);
if (status != 0) /* error message has been printed already. */
static int config_set_char (char *dest,
oconfig_item_t *ci)
{
- char buffer[4];
+ char buffer[4] = { 0 };
int status;
- memset (buffer, 0, sizeof (buffer));
-
status = cf_util_get_string_buffer (ci, buffer, sizeof (buffer));
if (status != 0)
return (status);
static int wg_config_node (oconfig_item_t *ci)
{
struct wg_callback *cb;
- user_data_t user_data;
char callback_name[DATA_MAX_NAME_LEN];
- int i;
int status = 0;
- cb = malloc (sizeof (*cb));
+ cb = calloc (1, sizeof (*cb));
if (cb == NULL)
{
- ERROR ("write_graphite plugin: malloc failed.");
+ ERROR ("write_graphite plugin: calloc failed.");
return (-1);
}
- memset (cb, 0, sizeof (*cb));
cb->sock_fd = -1;
cb->name = NULL;
- cb->node = NULL;
- cb->service = NULL;
- cb->protocol = NULL;
+ cb->node = strdup (WG_DEFAULT_NODE);
+ cb->service = strdup (WG_DEFAULT_SERVICE);
+ cb->protocol = strdup (WG_DEFAULT_PROTOCOL);
+ cb->last_reconnect_time = cdtime();
+ cb->reconnect_interval = 0;
+ cb->reconnect_interval_reached = 0;
cb->log_send_errors = WG_DEFAULT_LOG_SEND_ERRORS;
cb->prefix = NULL;
cb->postfix = NULL;
pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
C_COMPLAIN_INIT (&cb->init_complaint);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
status = -1;
}
}
+ else if (strcasecmp ("ReconnectInterval", child->key) == 0)
+ cf_util_get_cdtime (child, &cb->reconnect_interval);
else if (strcasecmp ("LogSendErrors", child->key) == 0)
cf_util_get_boolean (child, &cb->log_send_errors);
else if (strcasecmp ("Prefix", child->key) == 0)
/* FIXME: Legacy configuration syntax. */
if (cb->name == NULL)
ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s/%s/%s",
- cb->node != NULL ? cb->node : WG_DEFAULT_NODE,
- cb->service != NULL ? cb->service : WG_DEFAULT_SERVICE,
- cb->protocol != NULL ? cb->protocol : WG_DEFAULT_PROTOCOL);
+ cb->node, cb->service, cb->protocol);
else
ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s",
cb->name);
- memset (&user_data, 0, sizeof (user_data));
- user_data.data = cb;
- user_data.free_func = wg_callback_free;
- plugin_register_write (callback_name, wg_write, &user_data);
+ user_data_t ud = {
+ .data = cb,
+ .free_func = wg_callback_free
+ };
+
+ plugin_register_write (callback_name, wg_write, &ud);
- user_data.free_func = NULL;
- plugin_register_flush (callback_name, wg_flush, &user_data);
+ ud.free_func = NULL;
+ plugin_register_flush (callback_name, wg_flush, &ud);
return (0);
}
static int wg_config (oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/write_http.c b/src/write_http.c
index 65197e6c64f1fcedda9e4b75a52a82ffe49860a5..f8cc4e8df5627a946e0e431087a55b6f7dae5495 100644 (file)
--- a/src/write_http.c
+++ b/src/write_http.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
-#include "utils_cache.h"
#include "utils_format_json.h"
-
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
+#include "utils_format_kairosdb.h"
#include <curl/curl.h>
char *clientkeypass;
long sslversion;
_Bool store_rates;
+ _Bool log_http_error;
int low_speed_limit;
time_t low_speed_time;
int timeout;
-#define WH_FORMAT_COMMAND 0
-#define WH_FORMAT_JSON 1
+#define WH_FORMAT_COMMAND 0
+#define WH_FORMAT_JSON 1
+#define WH_FORMAT_KAIROSDB 2
int format;
+ _Bool send_metrics;
+ _Bool send_notifications;
CURL *curl;
struct curl_slist *headers;
};
typedef struct wh_callback_s wh_callback_t;
+static void wh_log_http_error (wh_callback_t *cb)
+{
+ if (!cb->log_http_error)
+ return;
+
+ long http_code = 0;
+
+ curl_easy_getinfo (cb->curl, CURLINFO_RESPONSE_CODE, &http_code);
+
+ if (http_code != 200)
+ INFO ("write_http plugin: HTTP Error code: %lu", http_code);
+}
+
static void wh_reset_buffer (wh_callback_t *cb) /* {{{ */
{
+ if ((cb == NULL) || (cb->send_buffer == NULL))
+ return;
+
memset (cb->send_buffer, 0, cb->send_buffer_size);
cb->send_buffer_free = cb->send_buffer_size;
cb->send_buffer_fill = 0;
cb->send_buffer_init_time = cdtime ();
- if (cb->format == WH_FORMAT_JSON)
+ if (cb->format == WH_FORMAT_JSON || cb->format == WH_FORMAT_KAIROSDB)
{
format_json_initialize (cb->send_buffer,
&cb->send_buffer_fill,
}
} /* }}} wh_reset_buffer */
-static int wh_send_buffer (wh_callback_t *cb) /* {{{ */
+/* must hold cb->send_lock when calling */
+static int wh_post_nolock (wh_callback_t *cb, char const *data) /* {{{ */
{
int status = 0;
- curl_easy_setopt (cb->curl, CURLOPT_POSTFIELDS, cb->send_buffer);
+ curl_easy_setopt (cb->curl, CURLOPT_POSTFIELDS, data);
status = curl_easy_perform (cb->curl);
+
+ wh_log_http_error (cb);
+
if (status != CURLE_OK)
{
ERROR ("write_http plugin: curl_easy_perform failed with "
status, cb->curl_errbuf);
}
return (status);
-} /* }}} wh_send_buffer */
+} /* }}} wh_post_nolock */
static int wh_callback_init (wh_callback_t *cb) /* {{{ */
{
curl_easy_setopt (cb->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
- cb->headers = NULL;
cb->headers = curl_slist_append (cb->headers, "Accept: */*");
- if (cb->format == WH_FORMAT_JSON)
+ if (cb->format == WH_FORMAT_JSON || cb->format == WH_FORMAT_KAIROSDB)
cb->headers = curl_slist_append (cb->headers, "Content-Type: application/json");
else
cb->headers = curl_slist_append (cb->headers, "Content-Type: text/plain");
if (cb->pass != NULL)
credentials_size += strlen (cb->pass);
- cb->credentials = (char *) malloc (credentials_size);
+ cb->credentials = malloc (credentials_size);
if (cb->credentials == NULL)
{
ERROR ("curl plugin: malloc failed.");
if (cb->format == WH_FORMAT_COMMAND)
{
- if (cb->send_buffer_fill <= 0)
+ if (cb->send_buffer_fill == 0)
{
cb->send_buffer_init_time = cdtime ();
return (0);
}
- status = wh_send_buffer (cb);
+ status = wh_post_nolock (cb, cb->send_buffer);
wh_reset_buffer (cb);
}
- else if (cb->format == WH_FORMAT_JSON)
+ else if (cb->format == WH_FORMAT_JSON || cb->format == WH_FORMAT_KAIROSDB)
{
if (cb->send_buffer_fill <= 2)
{
return (status);
}
- status = wh_send_buffer (cb);
+ status = wh_post_nolock (cb, cb->send_buffer);
wh_reset_buffer (cb);
}
else
pthread_mutex_lock (&cb->send_lock);
- if (cb->curl == NULL)
+ if (wh_callback_init (cb) != 0)
{
- status = wh_callback_init (cb);
- if (status != 0)
- {
- ERROR ("write_http plugin: wh_callback_init failed.");
- pthread_mutex_unlock (&cb->send_lock);
- return (-1);
- }
+ ERROR ("write_http plugin: wh_callback_init failed.");
+ pthread_mutex_unlock (&cb->send_lock);
+ return (-1);
}
status = wh_flush_nolock (timeout, cb);
cb = data;
- wh_flush_nolock (/* timeout = */ 0, cb);
+ if (cb->send_buffer != NULL)
+ wh_flush_nolock (/* timeout = */ 0, cb);
if (cb->curl != NULL)
{
@@ -345,7 +362,11 @@ static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{
int status;
- if (0 != strcmp (ds->type, vl->type)) {
+ /* sanity checks, primarily to make static analyzers happy. */
+ if ((cb == NULL) || (cb->send_buffer == NULL))
+ return -1;
+
+ if (strcmp (ds->type, vl->type) != 0) {
ERROR ("write_http plugin: DS type does not match "
"value list type");
return -1;
@@ -380,16 +401,11 @@ static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{
}
pthread_mutex_lock (&cb->send_lock);
-
- if (cb->curl == NULL)
+ if (wh_callback_init (cb) != 0)
{
- status = wh_callback_init (cb);
- if (status != 0)
- {
- ERROR ("write_http plugin: wh_callback_init failed.");
- pthread_mutex_unlock (&cb->send_lock);
- return (-1);
- }
+ ERROR ("write_http plugin: wh_callback_init failed.");
+ pthread_mutex_unlock (&cb->send_lock);
+ return (-1);
}
if (command_len >= cb->send_buffer_free)
@@ -427,6 +443,55 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ *
{
int status;
+ pthread_mutex_lock (&cb->send_lock);
+ if (wh_callback_init (cb) != 0)
+ {
+ ERROR ("write_http plugin: wh_callback_init failed.");
+ pthread_mutex_unlock (&cb->send_lock);
+ return (-1);
+ }
+
+ status = format_json_value_list (cb->send_buffer,
+ &cb->send_buffer_fill,
+ &cb->send_buffer_free,
+ ds, vl, cb->store_rates);
+ if (status == -ENOMEM)
+ {
+ status = wh_flush_nolock (/* timeout = */ 0, cb);
+ if (status != 0)
+ {
+ wh_reset_buffer (cb);
+ pthread_mutex_unlock (&cb->send_lock);
+ return (status);
+ }
+
+ status = format_json_value_list (cb->send_buffer,
+ &cb->send_buffer_fill,
+ &cb->send_buffer_free,
+ ds, vl, cb->store_rates);
+ }
+ if (status != 0)
+ {
+ pthread_mutex_unlock (&cb->send_lock);
+ return (status);
+ }
+
+ DEBUG ("write_http plugin: <%s> buffer %zu/%zu (%g%%)",
+ cb->location,
+ cb->send_buffer_fill, cb->send_buffer_size,
+ 100.0 * ((double) cb->send_buffer_fill) / ((double) cb->send_buffer_size));
+
+ /* Check if we have enough space for this command. */
+ pthread_mutex_unlock (&cb->send_lock);
+
+ return (0);
+} /* }}} int wh_write_json */
+
+static int wh_write_kairosdb (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+ wh_callback_t *cb)
+{
+ int status;
+
pthread_mutex_lock (&cb->send_lock);
if (cb->curl == NULL)
@@ -440,11 +505,11 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ *
}
}
- status = format_json_value_list (cb->send_buffer,
+ status = format_kairosdb_value_list (cb->send_buffer,
&cb->send_buffer_fill,
&cb->send_buffer_free,
ds, vl, cb->store_rates);
- if (status == (-ENOMEM))
+ if (status == -ENOMEM)
{
status = wh_flush_nolock (/* timeout = */ 0, cb);
if (status != 0)
@@ -454,7 +519,7 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ *
return (status);
}
- status = format_json_value_list (cb->send_buffer,
+ status = format_kairosdb_value_list (cb->send_buffer,
&cb->send_buffer_fill,
&cb->send_buffer_free,
ds, vl, cb->store_rates);
@@ -474,7 +539,7 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ *
pthread_mutex_unlock (&cb->send_lock);
return (0);
-} /* }}} int wh_write_json */
+} /* }}} int wh_write_kairosdb */
static int wh_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
user_data_t *user_data)
return (-EINVAL);
cb = user_data->data;
+ assert (cb->send_metrics);
- if (cb->format == WH_FORMAT_JSON)
+ switch(cb->format) {
+ case WH_FORMAT_JSON:
status = wh_write_json (ds, vl, cb);
- else
+ break;
+ case WH_FORMAT_KAIROSDB:
+ status = wh_write_kairosdb (ds, vl, cb);
+ break;
+ default:
status = wh_write_command (ds, vl, cb);
-
+ break;
+ }
return (status);
} /* }}} int wh_write */
+static int wh_notify (notification_t const *n, user_data_t *ud) /* {{{ */
+{
+ wh_callback_t *cb;
+ char alert[4096];
+ int status;
+
+ if ((ud == NULL) || (ud->data == NULL))
+ return (EINVAL);
+
+ cb = ud->data;
+ assert (cb->send_notifications);
+
+ status = format_json_notification (alert, sizeof (alert), n);
+ if (status != 0)
+ {
+ ERROR ("write_http plugin: formatting notification failed");
+ return status;
+ }
+
+ pthread_mutex_lock (&cb->send_lock);
+ if (wh_callback_init (cb) != 0)
+ {
+ ERROR ("write_http plugin: wh_callback_init failed.");
+ pthread_mutex_unlock (&cb->send_lock);
+ return (-1);
+ }
+
+ status = wh_post_nolock (cb, alert);
+ pthread_mutex_unlock (&cb->send_lock);
+
+ return (status);
+} /* }}} int wh_notify */
+
static int config_set_format (wh_callback_t *cb, /* {{{ */
oconfig_item_t *ci)
{
cb->format = WH_FORMAT_COMMAND;
else if (strcasecmp ("JSON", string) == 0)
cb->format = WH_FORMAT_JSON;
+ else if (strcasecmp ("KAIROSDB", string) == 0)
+ cb->format = WH_FORMAT_KAIROSDB;
else
{
ERROR ("write_http plugin: Invalid format string: %s",
return (0);
} /* }}} int config_set_format */
+static int wh_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
+ oconfig_item_t *ci)
+{
+ struct curl_slist *temp = NULL;
+ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("write_http plugin: `%s' needs exactly one string argument.", name);
+ return (-1);
+ }
+
+ temp = curl_slist_append(*dest, ci->values[0].value.string);
+ if (temp == NULL)
+ return (-1);
+
+ *dest = temp;
+
+ return (0);
+} /* }}} int wh_config_append_string */
+
static int wh_config_node (oconfig_item_t *ci) /* {{{ */
{
wh_callback_t *cb;
int buffer_size = 0;
- user_data_t user_data;
char callback_name[DATA_MAX_NAME_LEN];
- int i;
+ int status = 0;
- cb = malloc (sizeof (*cb));
+ cb = calloc (1, sizeof (*cb));
if (cb == NULL)
{
- ERROR ("write_http plugin: malloc failed.");
+ ERROR ("write_http plugin: calloc failed.");
return (-1);
}
- memset (cb, 0, sizeof (*cb));
cb->verify_peer = 1;
cb->verify_host = 1;
cb->format = WH_FORMAT_COMMAND;
cb->sslversion = CURL_SSLVERSION_DEFAULT;
cb->low_speed_limit = 0;
cb->timeout = 0;
+ cb->log_http_error = 0;
cb->headers = NULL;
+ cb->send_metrics = 1;
+ cb->send_notifications = 0;
pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
if (strcasecmp ("URL", ci->key) == 0)
cf_util_get_string (ci, &cb->location);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("URL", child->key) == 0)
- cf_util_get_string (child, &cb->location);
+ status = cf_util_get_string (child, &cb->location);
else if (strcasecmp ("User", child->key) == 0)
- cf_util_get_string (child, &cb->user);
+ status = cf_util_get_string (child, &cb->user);
else if (strcasecmp ("Password", child->key) == 0)
- cf_util_get_string (child, &cb->pass);
+ status = cf_util_get_string (child, &cb->pass);
else if (strcasecmp ("VerifyPeer", child->key) == 0)
- cf_util_get_boolean (child, &cb->verify_peer);
+ status = cf_util_get_boolean (child, &cb->verify_peer);
else if (strcasecmp ("VerifyHost", child->key) == 0)
- cf_util_get_boolean (child, &cb->verify_host);
+ status = cf_util_get_boolean (child, &cb->verify_host);
else if (strcasecmp ("CACert", child->key) == 0)
- cf_util_get_string (child, &cb->cacert);
+ status = cf_util_get_string (child, &cb->cacert);
else if (strcasecmp ("CAPath", child->key) == 0)
- cf_util_get_string (child, &cb->capath);
+ status = cf_util_get_string (child, &cb->capath);
else if (strcasecmp ("ClientKey", child->key) == 0)
- cf_util_get_string (child, &cb->clientkey);
+ status = cf_util_get_string (child, &cb->clientkey);
else if (strcasecmp ("ClientCert", child->key) == 0)
- cf_util_get_string (child, &cb->clientcert);
+ status = cf_util_get_string (child, &cb->clientcert);
else if (strcasecmp ("ClientKeyPass", child->key) == 0)
- cf_util_get_string (child, &cb->clientkeypass);
+ status = cf_util_get_string (child, &cb->clientkeypass);
else if (strcasecmp ("SSLVersion", child->key) == 0)
{
char *value = NULL;
- cf_util_get_string (child, &value);
+ status = cf_util_get_string (child, &value);
+ if (status != 0)
+ break;
if (value == NULL || strcasecmp ("default", value) == 0)
cb->sslversion = CURL_SSLVERSION_DEFAULT;
cb->sslversion = CURL_SSLVERSION_TLSv1_2;
#endif
else
+ {
ERROR ("write_http plugin: Invalid SSLVersion "
"option: %s.", value);
+ status = EINVAL;
+ }
sfree(value);
}
else if (strcasecmp ("Format", child->key) == 0)
- config_set_format (cb, child);
+ status = config_set_format (cb, child);
+ else if (strcasecmp ("Metrics", child->key) == 0)
+ cf_util_get_boolean (child, &cb->send_metrics);
+ else if (strcasecmp ("Notifications", child->key) == 0)
+ cf_util_get_boolean (child, &cb->send_notifications);
else if (strcasecmp ("StoreRates", child->key) == 0)
- cf_util_get_boolean (child, &cb->store_rates);
+ status = cf_util_get_boolean (child, &cb->store_rates);
else if (strcasecmp ("BufferSize", child->key) == 0)
- cf_util_get_int (child, &buffer_size);
+ status = cf_util_get_int (child, &buffer_size);
else if (strcasecmp ("LowSpeedLimit", child->key) == 0)
- cf_util_get_int (child, &cb->low_speed_limit);
+ status = cf_util_get_int (child, &cb->low_speed_limit);
else if (strcasecmp ("Timeout", child->key) == 0)
- cf_util_get_int (child, &cb->timeout);
+ status = cf_util_get_int (child, &cb->timeout);
+ else if (strcasecmp ("LogHttpError", child->key) == 0)
+ status = cf_util_get_boolean (child, &cb->log_http_error);
+ else if (strcasecmp ("Header", child->key) == 0)
+ status = wh_config_append_string ("Header", &cb->headers, child);
else
{
ERROR ("write_http plugin: Invalid configuration "
"option: %s.", child->key);
+ status = EINVAL;
}
+
+ if (status != 0)
+ break;
+ }
+
+ if (status != 0)
+ {
+ wh_callback_free (cb);
+ return (status);
}
if (cb->location == NULL)
return (-1);
}
+ if (!cb->send_metrics && !cb->send_notifications)
+ {
+ ERROR ("write_http plugin: Neither metrics nor notifications "
+ "are enabled for \"%s\".", cb->name);
+ wh_callback_free (cb);
+ return (-1);
+ }
+
if (cb->low_speed_limit > 0)
cb->low_speed_time = CDTIME_T_TO_TIME_T(plugin_get_interval());
DEBUG ("write_http: Registering write callback '%s' with URL '%s'",
callback_name, cb->location);
- memset (&user_data, 0, sizeof (user_data));
- user_data.data = cb;
- user_data.free_func = NULL;
- plugin_register_flush (callback_name, wh_flush, &user_data);
+ user_data_t user_data = {
+ .data = cb,
+ .free_func = wh_callback_free,
+ };
+
+ if (cb->send_metrics)
+ {
+ plugin_register_write (callback_name, wh_write, &user_data);
+ user_data.free_func = NULL;
+
+ plugin_register_flush (callback_name, wh_flush, &user_data);
+ }
- user_data.free_func = wh_callback_free;
- plugin_register_write (callback_name, wh_write, &user_data);
+ if (cb->send_notifications)
+ {
+ plugin_register_notification (callback_name, wh_notify, &user_data);
+ user_data.free_func = NULL;
+ }
return (0);
} /* }}} int wh_config_node */
static int wh_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/write_kafka.c b/src/write_kafka.c
index eaaf171262bd0b06ef07e0ddb8e32056bb9d873b..6d826c25ba213ad9acf6ae1f8a56a16e62fceeab 100644 (file)
--- a/src/write_kafka.c
+++ b/src/write_kafka.c
#include "plugin.h"
#include "common.h"
-#include "configfile.h"
-#include "utils_cache.h"
#include "utils_cmd_putval.h"
#include "utils_format_graphite.h"
#include "utils_format_json.h"
-#include "utils_crc32.h"
#include <stdint.h>
#include <librdkafka/rdkafka.h>
-#include <pthread.h>
-#include <zlib.h>
#include <errno.h>
struct kafka_topic_context {
#define KAFKA_FORMAT_JSON 0
#define KAFKA_FORMAT_COMMAND 1
#define KAFKA_FORMAT_GRAPHITE 2
- uint8_t format;
+ uint8_t format;
unsigned int graphite_flags;
_Bool store_rates;
rd_kafka_topic_conf_t *conf;
rd_kafka_topic_t *topic;
rd_kafka_conf_t *kafka_conf;
rd_kafka_t *kafka;
- int has_key;
- uint32_t key;
+ char *key;
char *prefix;
char *postfix;
char escape_char;
char *topic_name;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
static int kafka_handle(struct kafka_topic_context *);
}
#endif
+static uint32_t kafka_hash(const char *keydata, size_t keylen)
+{
+ uint32_t hash = 5381;
+ for (; keylen > 0; keylen--)
+ hash = ((hash << 5) + hash) + keydata[keylen - 1];
+ return hash;
+}
+
+/* 31 bit -> 4 byte -> 8 byte hex string + null byte */
+#define KAFKA_RANDOM_KEY_SIZE 9
+#define KAFKA_RANDOM_KEY_BUFFER (char[KAFKA_RANDOM_KEY_SIZE]) {""}
+static char *kafka_random_key(char buffer[static KAFKA_RANDOM_KEY_SIZE])
+{
+ ssnprintf(buffer, KAFKA_RANDOM_KEY_SIZE, "%08lX", (unsigned long) mrand48());
+ return buffer;
+}
+
static int32_t kafka_partition(const rd_kafka_topic_t *rkt,
const void *keydata, size_t keylen,
int32_t partition_cnt, void *p, void *m)
{
- uint32_t key = *((uint32_t *)keydata );
+ uint32_t key = kafka_hash(keydata, keylen);
uint32_t target = key % partition_cnt;
- int32_t i = partition_cnt;
+ int32_t i = partition_cnt;
while (--i > 0 && !rd_kafka_topic_partition_available(rkt, target)) {
target = (target + 1) % partition_cnt;
if ((ctx->kafka = rd_kafka_new(RD_KAFKA_PRODUCER, conf,
errbuf, sizeof(errbuf))) == NULL) {
- ERROR("write_kafka plugin: cannot create kafka handle.");
- return 1;
+ ERROR("write_kafka plugin: cannot create kafka handle.");
+ return 1;
}
- rd_kafka_conf_destroy(ctx->kafka_conf);
- ctx->kafka_conf = NULL;
+ rd_kafka_conf_destroy(ctx->kafka_conf);
+ ctx->kafka_conf = NULL;
- INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
+ INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
-#ifdef HAVE_LIBRDKAFKA_LOGGER
- rd_kafka_set_logger(ctx->kafka, kafka_log);
+#if defined(HAVE_LIBRDKAFKA_LOGGER) && !defined(HAVE_LIBRDKAFKA_LOG_CB)
+ rd_kafka_set_logger(ctx->kafka, kafka_log);
#endif
}
if (ctx->topic == NULL ) {
- if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
+ if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
ERROR("write_kafka plugin: cannot duplicate kafka topic config");
return 1;
- }
+ }
- if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
- topic_conf)) == NULL) {
- ERROR("write_kafka plugin: cannot create topic : %s\n",
- rd_kafka_err2str(rd_kafka_errno2err(errno)));
- return errno;
- }
+ if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
+ topic_conf)) == NULL) {
+ ERROR("write_kafka plugin: cannot create topic : %s\n",
+ rd_kafka_err2str(rd_kafka_errno2err(errno)));
+ return errno;
+ }
- rd_kafka_topic_conf_destroy(ctx->conf);
- ctx->conf = NULL;
+ rd_kafka_topic_conf_destroy(ctx->conf);
+ ctx->conf = NULL;
- INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
+ INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
}
return(0);
} /* }}} int kafka_handle */
static int kafka_write(const data_set_t *ds, /* {{{ */
- const value_list_t *vl,
- user_data_t *ud)
+ const value_list_t *vl,
+ user_data_t *ud)
{
- int status = 0;
- uint32_t key;
- char buffer[8192];
- size_t bfree = sizeof(buffer);
- size_t bfill = 0;
- size_t blen = 0;
- struct kafka_topic_context *ctx = ud->data;
+ int status = 0;
+ void *key;
+ size_t keylen = 0;
+ char buffer[8192];
+ size_t bfree = sizeof(buffer);
+ size_t bfill = 0;
+ size_t blen = 0;
+ struct kafka_topic_context *ctx = ud->data;
if ((ds == NULL) || (vl == NULL) || (ctx == NULL))
return EINVAL;
blen = strlen(buffer);
break;
case KAFKA_FORMAT_JSON:
-
format_json_initialize(buffer, &bfill, &bfree);
format_json_value_list(buffer, &bfill, &bfree, ds, vl,
ctx->store_rates);
return -1;
}
- /*
- * We partition our stream by metric name
- */
- if (ctx->has_key)
- key = ctx->key;
- else
- key = rand();
+ key = (ctx->key != NULL)
+ ? ctx->key
+ : kafka_random_key(KAFKA_RANDOM_KEY_BUFFER);
+ keylen = strlen (key);
rd_kafka_produce(ctx->topic, RD_KAFKA_PARTITION_UA,
RD_KAFKA_MSG_F_COPY, buffer, blen,
- &key, sizeof(key), NULL);
+ key, keylen, NULL);
- return status;
+ return status;
} /* }}} int kafka_write */
static void kafka_topic_context_free(void *p) /* {{{ */
{
- struct kafka_topic_context *ctx = p;
+ struct kafka_topic_context *ctx = p;
- if (ctx == NULL)
- return;
+ if (ctx == NULL)
+ return;
if (ctx->topic_name != NULL)
sfree(ctx->topic_name);
static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{ */
{
int status;
- int i;
struct kafka_topic_context *tctx;
char *key = NULL;
char *val;
char callback_name[DATA_MAX_NAME_LEN];
char errbuf[1024];
- user_data_t ud;
- oconfig_item_t *child;
+ oconfig_item_t *child;
rd_kafka_conf_res_t ret;
- if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
- ERROR ("write_kafka plugin: calloc failed.");
+ if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
+ ERROR ("write_kafka plugin: calloc failed.");
return;
- }
+ }
tctx->escape_char = '.';
tctx->store_rates = 1;
tctx->format = KAFKA_FORMAT_JSON;
+ tctx->key = NULL;
if ((tctx->kafka_conf = rd_kafka_conf_dup(conf)) == NULL) {
sfree(tctx);
@@ -298,48 +305,41 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
goto errout;
}
- for (i = 0; i < ci->children_num; i++) {
- /*
- * The code here could be simplified but makes room
- * for easy adding of new options later on.
- */
- child = &ci->children[i];
- status = 0;
-
- if (strcasecmp ("Property", child->key) == 0) {
- if (child->values_num != 2) {
- WARNING("kafka properties need both a key and a value.");
+ for (int i = 0; i < ci->children_num; i++) {
+ /*
+ * The code here could be simplified but makes room
+ * for easy adding of new options later on.
+ */
+ child = &ci->children[i];
+ status = 0;
+
+ if (strcasecmp ("Property", child->key) == 0) {
+ if (child->values_num != 2) {
+ WARNING("kafka properties need both a key and a value.");
goto errout;
- }
- if (child->values[0].type != OCONFIG_TYPE_STRING ||
- child->values[1].type != OCONFIG_TYPE_STRING) {
- WARNING("kafka properties needs string arguments.");
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka properties needs string arguments.");
goto errout;
- }
+ }
key = child->values[0].value.string;
val = child->values[1].value.string;
ret = rd_kafka_topic_conf_set(tctx->conf,key, val,
errbuf, sizeof(errbuf));
if (ret != RD_KAFKA_CONF_OK) {
- WARNING("cannot set kafka topic property %s to %s: %s.",
+ WARNING("cannot set kafka topic property %s to %s: %s.",
key, val, errbuf);
goto errout;
- }
-
- } else if (strcasecmp ("Key", child->key) == 0) {
- char *tmp_buf = NULL;
- status = cf_util_get_string(child, &tmp_buf);
- if (status != 0) {
- WARNING("write_kafka plugin: invalid key supplied");
- break;
}
- if (strcasecmp(tmp_buf, "Random") != 0) {
- tctx->has_key = 1;
- tctx->key = crc32_buffer((u_char *)tmp_buf, strlen(tmp_buf));
+ } else if (strcasecmp ("Key", child->key) == 0) {
+ if (cf_util_get_string (child, &tctx->key) != 0)
+ continue;
+ if (strcasecmp ("Random", tctx->key) == 0) {
+ sfree(tctx->key);
+ tctx->key = strdup (kafka_random_key (KAFKA_RANDOM_KEY_BUFFER));
}
- sfree(tmp_buf);
-
} else if (strcasecmp ("Format", child->key) == 0) {
status = cf_util_get_string(child, &key);
if (status != 0)
@@ -402,14 +402,16 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
ssnprintf(callback_name, sizeof(callback_name),
"write_kafka/%s", tctx->topic_name);
- ud.data = tctx;
- ud.free_func = kafka_topic_context_free;
+ user_data_t ud = {
+ .data = tctx,
+ .free_func = kafka_topic_context_free
+ };
- status = plugin_register_write (callback_name, kafka_write, &ud);
- if (status != 0) {
- WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
- "failed with status %i.",
- callback_name, status);
+ status = plugin_register_write (callback_name, kafka_write, &ud);
+ if (status != 0) {
+ WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
+ "failed with status %i.",
+ callback_name, status);
goto errout;
}
@@ -422,14 +424,13 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
if (tctx->conf != NULL)
rd_kafka_topic_conf_destroy(tctx->conf);
if (tctx->kafka_conf != NULL)
- rd_kafka_conf_destroy(tctx->kafka_conf);
+ rd_kafka_conf_destroy(tctx->kafka_conf);
sfree(tctx);
} /* }}} int kafka_config_topic */
static int kafka_config(oconfig_item_t *ci) /* {{{ */
{
- int i;
- oconfig_item_t *child;
+ oconfig_item_t *child;
rd_kafka_conf_t *conf;
rd_kafka_conf_res_t ret;
char errbuf[1024];
WARNING("cannot allocate kafka configuration.");
return -1;
}
- for (i = 0; i < ci->children_num; i++) {
- child = &ci->children[i];
+ for (int i = 0; i < ci->children_num; i++) {
+ child = &ci->children[i];
- if (strcasecmp("Topic", child->key) == 0) {
- kafka_config_topic (conf, child);
- } else if (strcasecmp(child->key, "Property") == 0) {
- char *key = NULL;
- char *val = NULL;
+ if (strcasecmp("Topic", child->key) == 0) {
+ kafka_config_topic (conf, child);
+ } else if (strcasecmp(child->key, "Property") == 0) {
+ char *key = NULL;
+ char *val = NULL;
- if (child->values_num != 2) {
- WARNING("kafka properties need both a key and a value.");
+ if (child->values_num != 2) {
+ WARNING("kafka properties need both a key and a value.");
goto errout;
- }
- if (child->values[0].type != OCONFIG_TYPE_STRING ||
- child->values[1].type != OCONFIG_TYPE_STRING) {
- WARNING("kafka properties needs string arguments.");
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka properties needs string arguments.");
goto errout;
- }
- if ((key = strdup(child->values[0].value.string)) == NULL) {
- WARNING("cannot allocate memory for attribute key.");
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
goto errout;
- }
- if ((val = strdup(child->values[1].value.string)) == NULL) {
- WARNING("cannot allocate memory for attribute value.");
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
+ sfree(key);
goto errout;
- }
+ }
ret = rd_kafka_conf_set(conf, key, val, errbuf, sizeof(errbuf));
if (ret != RD_KAFKA_CONF_OK) {
WARNING("cannot set kafka property %s to %s: %s",
key, val, errbuf);
+ sfree(key);
+ sfree(val);
goto errout;
}
- sfree(key);
- sfree(val);
- } else {
- WARNING ("write_kafka plugin: Ignoring unknown "
- "configuration option \"%s\" at top level.",
- child->key);
- }
- }
+ sfree(key);
+ sfree(val);
+ } else {
+ WARNING ("write_kafka plugin: Ignoring unknown "
+ "configuration option \"%s\" at top level.",
+ child->key);
+ }
+ }
if (conf != NULL)
rd_kafka_conf_destroy(conf);
return (0);
void module_register(void)
{
- plugin_register_complex_config ("write_kafka", kafka_config);
+ plugin_register_complex_config ("write_kafka", kafka_config);
}
-
-/* vim: set sw=8 sts=8 ts=8 noet : */
diff --git a/src/write_log.c b/src/write_log.c
index e37aae9fd594fcce3ecd6d5abac7a6fb33adf32c..b0dc6f11cca43072ed7a094ba6ef3c2f2e6ac794 100644 (file)
--- a/src/write_log.c
+++ b/src/write_log.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_format_graphite.h"
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
-#include <sys/socket.h>
#include <netdb.h>
#define WL_BUF_SIZE 8192
static int wl_write_messages (const data_set_t *ds, const value_list_t *vl)
{
- char buffer[WL_BUF_SIZE];
+ char buffer[WL_BUF_SIZE] = { 0 };
int status;
if (0 != strcmp (ds->type, vl->type))
return -1;
}
- memset (buffer, 0, sizeof (buffer));
status = format_graphite (buffer, sizeof (buffer), ds, vl,
NULL, NULL, '_', 0);
if (status != 0) /* error message has been printed already. */
} /* int wl_write_messages */
static int wl_write (const data_set_t *ds, const value_list_t *vl,
- user_data_t *user_data)
+ __attribute__ ((unused)) user_data_t *user_data)
{
int status;
diff --git a/src/write_mongodb.c b/src/write_mongodb.c
index 24151ceb720a3a29a055a0a24e7cdc6993661d45..6d5f37943ea330c369fc6f871777aa8f7887e6e3 100644 (file)
--- a/src/write_mongodb.c
+++ b/src/write_mongodb.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
-#include "configfile.h"
#include "utils_cache.h"
-#include <pthread.h>
-
#if HAVE_STDINT_H
# define MONGO_HAVE_STDINT 1
#else
{
bson *ret;
gauge_t *rates;
- int i;
ret = bson_alloc (); /* matched by bson_dealloc() */
if (ret == NULL)
bson_append_string (ret, "type_instance", vl->type_instance);
bson_append_start_array (ret, "values"); /* {{{ */
- for (i = 0; i < ds->ds_num; i++)
+ for (int i = 0; i < ds->ds_num; i++)
{
char key[16];
bson_append_finish_array (ret); /* }}} values */
bson_append_start_array (ret, "dstypes"); /* {{{ */
- for (i = 0; i < ds->ds_num; i++)
+ for (int i = 0; i < ds->ds_num; i++)
{
char key[16];
bson_append_finish_array (ret); /* }}} dstypes */
bson_append_start_array (ret, "dsnames"); /* {{{ */
- for (i = 0; i < ds->ds_num; i++)
+ for (int i = 0; i < ds->ds_num; i++)
{
char key[16];
{
wm_node_t *node;
int status;
- int i;
- node = malloc (sizeof (*node));
+ node = calloc (1, sizeof (*node));
if (node == NULL)
return (ENOMEM);
- memset (node, 0, sizeof (*node));
mongo_init (node->conn);
node->host = NULL;
node->store_rates = 1;
return (status);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
if (status == 0)
{
char cb_name[DATA_MAX_NAME_LEN];
- user_data_t ud;
ssnprintf (cb_name, sizeof (cb_name), "write_mongodb/%s", node->name);
- ud.data = node;
- ud.free_func = wm_config_free;
+ user_data_t ud = {
+ .data = node,
+ .free_func = wm_config_free
+ };
status = plugin_register_write (cb_name, wm_write, &ud);
INFO ("write_mongodb plugin: registered write plugin %s %d",cb_name,status);
static int wm_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/write_redis.c b/src/write_redis.c
index cdea3060023b462df6b7bdb0d40d0a64fad02b78..c16537c25f91d96763a757535cb1279bc5f7cade 100644 (file)
--- a/src/write_redis.c
+++ b/src/write_redis.c
/**
* collectd - src/write_redis.c
- * Copyright (C) 2010 Florian Forster
+ * Copyright (C) 2010-2015 Florian Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
-#include "configfile.h"
-#include <pthread.h>
#include <sys/time.h>
#include <hiredis/hiredis.h>
+#ifndef REDIS_DEFAULT_PREFIX
+# define REDIS_DEFAULT_PREFIX "collectd/"
+#endif
+
struct wr_node_s
{
char name[DATA_MAX_NAME_LEN];
char *host;
int port;
struct timeval timeout;
+ char *prefix;
+ int database;
+ int max_set_size;
+ _Bool store_rates;
redisContext *conn;
pthread_mutex_t lock;
wr_node_t *node = ud->data;
char ident[512];
char key[512];
- char value[512];
+ char value[512] = { 0 };
char time[24];
size_t value_size;
char *value_ptr;
status = FORMAT_VL (ident, sizeof (ident), vl);
if (status != 0)
return (status);
- ssnprintf (key, sizeof (key), "collectd/%s", ident);
+ ssnprintf (key, sizeof (key), "%s%s",
+ (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+ ident);
ssnprintf (time, sizeof (time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
- memset (value, 0, sizeof (value));
value_size = sizeof (value);
value_ptr = &value[0];
- status = format_values (value_ptr, value_size, ds, vl, /* store rates = */ 0);
+ status = format_values (value_ptr, value_size, ds, vl, node->store_rates);
if (status != 0)
return (status);
pthread_mutex_unlock (&node->lock);
return (-1);
}
+
+ rr = redisCommand(node->conn, "SELECT %d", node->database);
+ if (rr == NULL)
+ WARNING("SELECT command error. database:%d message:%s", node->database, node->conn->errstr);
+ else
+ freeReplyObject (rr);
}
rr = redisCommand (node->conn, "ZADD %s %s %s", key, time, value);
else
freeReplyObject (rr);
+ if (node->max_set_size >= 0)
+ {
+ rr = redisCommand (node->conn, "ZREMRANGEBYRANK %s %d %d", key, 0, (-1 * node->max_set_size) - 1);
+ if (rr == NULL)
+ WARNING("ZREMRANGEBYRANK command error. key:%s message:%s", key, node->conn->errstr);
+ else
+ freeReplyObject (rr);
+ }
+
/* TODO(octo): This is more overhead than necessary. Use the cache and
* metadata to determine if it is a new metric and call SADD only once for
* each metric. */
- rr = redisCommand (node->conn, "SADD collectd/values %s", ident);
+ rr = redisCommand (node->conn, "SADD %svalues %s",
+ (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
+ ident);
if (rr==NULL)
WARNING("SADD command error. ident:%s message:%s", ident, node->conn->errstr);
else
wr_node_t *node;
int timeout;
int status;
- int i;
- node = malloc (sizeof (*node));
+ node = calloc (1, sizeof (*node));
if (node == NULL)
return (ENOMEM);
- memset (node, 0, sizeof (*node));
node->host = NULL;
node->port = 0;
node->timeout.tv_sec = 0;
node->timeout.tv_usec = 1000;
node->conn = NULL;
+ node->prefix = NULL;
+ node->database = 0;
+ node->max_set_size = -1;
+ node->store_rates = 1;
pthread_mutex_init (&node->lock, /* attr = */ NULL);
status = cf_util_get_string_buffer (ci, node->name, sizeof (node->name));
return (status);
}
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
status = cf_util_get_int (child, &timeout);
if (status == 0) node->timeout.tv_usec = timeout;
}
+ else if (strcasecmp ("Prefix", child->key) == 0) {
+ status = cf_util_get_string (child, &node->prefix);
+ }
+ else if (strcasecmp ("Database", child->key) == 0) {
+ status = cf_util_get_int (child, &node->database);
+ }
+ else if (strcasecmp ("MaxSetSize", child->key) == 0) {
+ status = cf_util_get_int (child, &node->max_set_size);
+ }
+ else if (strcasecmp ("StoreRates", child->key) == 0) {
+ status = cf_util_get_boolean (child, &node->store_rates);
+ }
else
WARNING ("write_redis plugin: Ignoring unknown config option \"%s\".",
child->key);
if (status == 0)
{
char cb_name[DATA_MAX_NAME_LEN];
- user_data_t ud;
ssnprintf (cb_name, sizeof (cb_name), "write_redis/%s", node->name);
- ud.data = node;
- ud.free_func = wr_config_free;
+ user_data_t ud = {
+ .data = node,
+ .free_func = wr_config_free
+ };
status = plugin_register_write (cb_name, wr_write, &ud);
}
static int wr_config (oconfig_item_t *ci) /* {{{ */
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/write_riemann.c b/src/write_riemann.c
index a6effa348b28dd67d92bb603998e3bd2b2568416..92c8d0caa11b571f4bd1cc957899cd33ff5d7b5e 100644 (file)
--- a/src/write_riemann.c
+++ b/src/write_riemann.c
* collectd - src/write_riemann.c
* Copyright (C) 2012,2013 Pierre-Yves Ritschard
* Copyright (C) 2013 Florian octo Forster
+ * Copyright (C) 2015,2016 Gergely Nagy
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* Authors:
* Pierre-Yves Ritschard <pyr at spootnik.org>
* Florian octo Forster <octo at collectd.org>
+ * Gergely Nagy <algernon at madhouse-project.org>
*/
#include "collectd.h"
-#include "plugin.h"
#include "common.h"
-#include "configfile.h"
+#include "plugin.h"
#include "utils_cache.h"
-#include "riemann.pb-c.h"
+#include "utils_complain.h"
#include "write_riemann_threshold.h"
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netdb.h>
+#include <riemann/riemann-client.h>
-#define RIEMANN_HOST "localhost"
-#define RIEMANN_PORT "5555"
-#define RIEMANN_TTL_FACTOR 2.0
-#define RIEMANN_BATCH_MAX 8192
+#define RIEMANN_HOST "localhost"
+#define RIEMANN_PORT 5555
+#define RIEMANN_TTL_FACTOR 2.0
+#define RIEMANN_BATCH_MAX 8192
struct riemann_host {
- char *name;
- char *event_service_prefix;
-#define F_CONNECT 0x01
- uint8_t flags;
- pthread_mutex_t lock;
- _Bool batch_mode;
- _Bool notifications;
- _Bool check_thresholds;
- _Bool store_rates;
- _Bool always_append_ds;
- char *node;
- char *service;
- _Bool use_tcp;
- int s;
- double ttl_factor;
- Msg *batch_msg;
- cdtime_t batch_init;
- int batch_max;
- int reference_count;
+ c_complain_t init_complaint;
+ char *name;
+ char *event_service_prefix;
+ pthread_mutex_t lock;
+ _Bool batch_mode;
+ _Bool notifications;
+ _Bool check_thresholds;
+ _Bool store_rates;
+ _Bool always_append_ds;
+ char *node;
+ int port;
+ riemann_client_type_t client_type;
+ riemann_client_t *client;
+ double ttl_factor;
+ cdtime_t batch_init;
+ int batch_max;
+ int batch_timeout;
+ int reference_count;
+ riemann_message_t *batch_msg;
+ char *tls_ca_file;
+ char *tls_cert_file;
+ char *tls_key_file;
+ struct timeval timeout;
};
-static char **riemann_tags;
-static size_t riemann_tags_num;
-static char **riemann_attrs;
-static size_t riemann_attrs_num;
-
-static void riemann_event_protobuf_free (Event *event) /* {{{ */
-{
- size_t i;
-
- if (event == NULL)
- return;
-
- sfree (event->state);
- sfree (event->service);
- sfree (event->host);
- sfree (event->description);
-
- strarray_free (event->tags, event->n_tags);
- event->tags = NULL;
- event->n_tags = 0;
-
- for (i = 0; i < event->n_attributes; i++)
- {
- sfree (event->attributes[i]->key);
- sfree (event->attributes[i]->value);
- sfree (event->attributes[i]);
- }
- sfree (event->attributes);
- event->n_attributes = 0;
-
- sfree (event);
-} /* }}} void riemann_event_protobuf_free */
-
-static void riemann_msg_protobuf_free(Msg *msg) /* {{{ */
-{
- size_t i;
-
- if (msg == NULL)
- return;
-
- for (i = 0; i < msg->n_events; i++)
- {
- riemann_event_protobuf_free (msg->events[i]);
- msg->events[i] = NULL;
- }
-
- sfree (msg->events);
- msg->n_events = 0;
-
- sfree (msg);
-} /* }}} void riemann_msg_protobuf_free */
+static char **riemann_tags;
+static size_t riemann_tags_num;
+static char **riemann_attrs;
+static size_t riemann_attrs_num;
/* host->lock must be held when calling this function. */
-static int riemann_connect(struct riemann_host *host) /* {{{ */
+static int wrr_connect(struct riemann_host *host) /* {{{ */
{
- int e;
- struct addrinfo *ai, *res, hints;
- char const *node;
- char const *service;
-
- if (host->flags & F_CONNECT)
- return 0;
-
- memset(&hints, 0, sizeof(hints));
- memset(&service, 0, sizeof(service));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = host->use_tcp ? SOCK_STREAM : SOCK_DGRAM;
-#ifdef AI_ADDRCONFIG
- hints.ai_flags |= AI_ADDRCONFIG;
+ char const *node;
+ int port;
+
+ if (host->client)
+ return 0;
+
+ node = (host->node != NULL) ? host->node : RIEMANN_HOST;
+ port = (host->port) ? host->port : RIEMANN_PORT;
+
+ host->client = NULL;
+
+ host->client = riemann_client_create(
+ host->client_type, node, port, RIEMANN_CLIENT_OPTION_TLS_CA_FILE,
+ host->tls_ca_file, RIEMANN_CLIENT_OPTION_TLS_CERT_FILE,
+ host->tls_cert_file, RIEMANN_CLIENT_OPTION_TLS_KEY_FILE,
+ host->tls_key_file, RIEMANN_CLIENT_OPTION_NONE);
+ if (host->client == NULL) {
+ c_complain(LOG_ERR, &host->init_complaint,
+ "write_riemann plugin: Unable to connect to Riemann at %s:%d",
+ node, port);
+ return -1;
+ }
+#if RCC_VERSION_NUMBER >= 0x010800
+ if (host->timeout.tv_sec != 0) {
+ if (riemann_client_set_timeout(host->client, &host->timeout) != 0) {
+ riemann_client_free(host->client);
+ host->client = NULL;
+ c_complain(LOG_ERR, &host->init_complaint,
+ "write_riemann plugin: Unable to connect to Riemann at %s:%d",
+ node, port);
+ return -1;
+ }
+ }
#endif
- node = (host->node != NULL) ? host->node : RIEMANN_HOST;
- service = (host->service != NULL) ? host->service : RIEMANN_PORT;
-
- if ((e = getaddrinfo(node, service, &hints, &res)) != 0) {
- ERROR ("write_riemann plugin: Unable to resolve host \"%s\": %s",
- node, gai_strerror(e));
- return -1;
- }
-
- host->s = -1;
- for (ai = res; ai != NULL; ai = ai->ai_next) {
- if ((host->s = socket(ai->ai_family,
- ai->ai_socktype,
- ai->ai_protocol)) == -1) {
- continue;
- }
-
- if (connect(host->s, ai->ai_addr, ai->ai_addrlen) != 0) {
- close(host->s);
- host->s = -1;
- continue;
- }
-
- host->flags |= F_CONNECT;
- DEBUG("write_riemann plugin: got a successful connection for: %s:%s",
- node, service);
- break;
- }
-
- freeaddrinfo(res);
-
- if (host->s < 0) {
- WARNING("write_riemann plugin: Unable to connect to Riemann at %s:%s",
- node, service);
- return -1;
- }
- return 0;
-} /* }}} int riemann_connect */
+ set_sock_opts(riemann_client_get_fd(host->client));
+
+ c_release(LOG_INFO, &host->init_complaint,
+ "write_riemann plugin: Successfully connected to %s:%d", node,
+ port);
+
+ return 0;
+} /* }}} int wrr_connect */
/* host->lock must be held when calling this function. */
-static int riemann_disconnect (struct riemann_host *host) /* {{{ */
+static int wrr_disconnect(struct riemann_host *host) /* {{{ */
{
- if ((host->flags & F_CONNECT) == 0)
- return (0);
+ if (!host->client)
+ return (0);
- close (host->s);
- host->s = -1;
- host->flags &= ~F_CONNECT;
+ riemann_client_free(host->client);
+ host->client = NULL;
- return (0);
-} /* }}} int riemann_disconnect */
+ return (0);
+} /* }}} int wrr_disconnect */
-static int riemann_send_msg (struct riemann_host *host, const Msg *msg) /* {{{ */
-{
- int status = 0;
- u_char *buffer = NULL;
- size_t buffer_len;
-
- status = riemann_connect (host);
- if (status != 0)
- return status;
-
- buffer_len = msg__get_packed_size(msg);
-
- if (host->use_tcp)
- buffer_len += 4;
-
- buffer = malloc (buffer_len);
- if (buffer == NULL) {
- ERROR ("write_riemann plugin: malloc failed.");
- return ENOMEM;
- }
- memset (buffer, 0, buffer_len);
-
- if (host->use_tcp)
- {
- uint32_t length = htonl ((uint32_t) (buffer_len - 4));
- memcpy (buffer, &length, 4);
- msg__pack(msg, buffer + 4);
- }
- else
- {
- msg__pack(msg, buffer);
- }
-
- status = (int) swrite (host->s, buffer, buffer_len);
- if (status != 0)
- {
- char errbuf[1024];
- ERROR ("write_riemann plugin: Sending to Riemann at %s:%s failed: %s",
- (host->node != NULL) ? host->node : RIEMANN_HOST,
- (host->service != NULL) ? host->service : RIEMANN_PORT,
- sstrerror (errno, errbuf, sizeof (errbuf)));
- sfree (buffer);
- return -1;
- }
-
- sfree (buffer);
- return 0;
-} /* }}} int riemann_send_msg */
-
-static int riemann_recv_ack(struct riemann_host *host) /* {{{ */
+/**
+ * Function to send messages to riemann.
+ *
+ * Acquires the host lock, disconnects on errors.
+ */
+static int wrr_send_nolock(struct riemann_host *host,
+ riemann_message_t *msg) /* {{{ */
{
- int status = 0;
- Msg *msg = NULL;
- uint32_t header;
+ int status = 0;
- status = (int) sread (host->s, &header, 4);
+ status = wrr_connect(host);
+ if (status != 0) {
+ return status;
+ }
- if (status != 0)
- return -1;
+ status = riemann_client_send_message(host->client, msg);
+ if (status != 0) {
+ wrr_disconnect(host);
+ return status;
+ }
- size_t size = ntohl(header);
+ /*
+ * For TCP we need to receive message acknowledgemenent.
+ */
+ if (host->client_type != RIEMANN_CLIENT_UDP) {
+ riemann_message_t *response;
- // Buffer on the stack since acknowledges are typically small.
- u_char buffer[size];
- memset (buffer, 0, size);
+ response = riemann_client_recv_message(host->client);
- status = (int) sread (host->s, buffer, size);
+ if (response == NULL) {
+ wrr_disconnect(host);
+ return errno;
+ }
+ riemann_message_free(response);
+ }
- if (status != 0)
- return status;
+ return 0;
+} /* }}} int wrr_send */
- msg = msg__unpack (NULL, size, buffer);
+static int wrr_send(struct riemann_host *host, riemann_message_t *msg) {
+ int status = 0;
- if (msg == NULL)
- return -1;
+ pthread_mutex_lock(&host->lock);
+ status = wrr_send_nolock(host, msg);
+ pthread_mutex_unlock(&host->lock);
+ return status;
+}
- if (!msg->ok)
- {
- ERROR ("write_riemann plugin: Sending to Riemann at %s:%s acknowledgement message reported error: %s",
- (host->node != NULL) ? host->node : RIEMANN_HOST,
- (host->service != NULL) ? host->service : RIEMANN_PORT,
- msg->error);
+static riemann_message_t *
+wrr_notification_to_message(struct riemann_host *host, /* {{{ */
+ notification_t const *n) {
+ riemann_message_t *msg;
+ riemann_event_t *event;
+ char service_buffer[6 * DATA_MAX_NAME_LEN];
+ char const *severity;
+
+ switch (n->severity) {
+ case NOTIF_OKAY:
+ severity = "ok";
+ break;
+ case NOTIF_WARNING:
+ severity = "warning";
+ break;
+ case NOTIF_FAILURE:
+ severity = "critical";
+ break;
+ default:
+ severity = "unknown";
+ }
+
+ format_name(service_buffer, sizeof(service_buffer),
+ /* host = */ "", n->plugin, n->plugin_instance, n->type,
+ n->type_instance);
+
+ event = riemann_event_create(
+ RIEMANN_EVENT_FIELD_HOST, n->host, RIEMANN_EVENT_FIELD_TIME,
+ (int64_t)CDTIME_T_TO_TIME_T(n->time), RIEMANN_EVENT_FIELD_TAGS,
+ "notification", NULL, RIEMANN_EVENT_FIELD_STATE, severity,
+ RIEMANN_EVENT_FIELD_SERVICE, &service_buffer[1],
+ RIEMANN_EVENT_FIELD_NONE);
+
+ if (n->host[0] != 0)
+ riemann_event_string_attribute_add(event, "host", n->host);
+ if (n->plugin[0] != 0)
+ riemann_event_string_attribute_add(event, "plugin", n->plugin);
+ if (n->plugin_instance[0] != 0)
+ riemann_event_string_attribute_add(event, "plugin_instance",
+ n->plugin_instance);
+
+ if (n->type[0] != 0)
+ riemann_event_string_attribute_add(event, "type", n->type);
+ if (n->type_instance[0] != 0)
+ riemann_event_string_attribute_add(event, "type_instance",
+ n->type_instance);
+
+ for (size_t i = 0; i < riemann_attrs_num; i += 2)
+ riemann_event_string_attribute_add(event, riemann_attrs[i],
+ riemann_attrs[i + 1]);
+
+ for (size_t i = 0; i < riemann_tags_num; i++)
+ riemann_event_tag_add(event, riemann_tags[i]);
+
+ if (n->message[0] != 0)
+ riemann_event_string_attribute_add(event, "description", n->message);
+
+ /* Pull in values from threshold and add extra attributes */
+ for (notification_meta_t *meta = n->meta; meta != NULL; meta = meta->next) {
+ if (strcasecmp("CurrentValue", meta->name) == 0 &&
+ meta->type == NM_TYPE_DOUBLE) {
+ riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D,
+ (double)meta->nm_value.nm_double,
+ RIEMANN_EVENT_FIELD_NONE);
+ continue;
+ }
- msg__free_unpacked(msg, NULL);
- return -1;
- }
+ if (meta->type == NM_TYPE_STRING) {
+ riemann_event_string_attribute_add(event, meta->name,
+ meta->nm_value.nm_string);
+ continue;
+ }
+ }
+
+ msg = riemann_message_create_with_events(event, NULL);
+ if (msg == NULL) {
+ ERROR("write_riemann plugin: riemann_message_create_with_events() failed.");
+ riemann_event_free(event);
+ return (NULL);
+ }
+
+ DEBUG("write_riemann plugin: Successfully created message for notification: "
+ "host = \"%s\", service = \"%s\", state = \"%s\"",
+ event->host, event->service, event->state);
+ return (msg);
+} /* }}} riemann_message_t *wrr_notification_to_message */
+
+static riemann_event_t *
+wrr_value_to_event(struct riemann_host const *host, /* {{{ */
+ data_set_t const *ds, value_list_t const *vl, size_t index,
+ gauge_t const *rates, int status) {
+ riemann_event_t *event;
+ char name_buffer[5 * DATA_MAX_NAME_LEN];
+ char service_buffer[6 * DATA_MAX_NAME_LEN];
+ size_t i;
+
+ event = riemann_event_new();
+ if (event == NULL) {
+ ERROR("write_riemann plugin: riemann_event_new() failed.");
+ return (NULL);
+ }
+
+ format_name(name_buffer, sizeof(name_buffer),
+ /* host = */ "", vl->plugin, vl->plugin_instance, vl->type,
+ vl->type_instance);
+ if (host->always_append_ds || (ds->ds_num > 1)) {
+ if (host->event_service_prefix == NULL)
+ ssnprintf(service_buffer, sizeof(service_buffer), "%s/%s",
+ &name_buffer[1], ds->ds[index].name);
+ else
+ ssnprintf(service_buffer, sizeof(service_buffer), "%s%s/%s",
+ host->event_service_prefix, &name_buffer[1],
+ ds->ds[index].name);
+ } else {
+ if (host->event_service_prefix == NULL)
+ sstrncpy(service_buffer, &name_buffer[1], sizeof(service_buffer));
+ else
+ ssnprintf(service_buffer, sizeof(service_buffer), "%s%s",
+ host->event_service_prefix, &name_buffer[1]);
+ }
+
+ riemann_event_set(
+ event, RIEMANN_EVENT_FIELD_HOST, vl->host, RIEMANN_EVENT_FIELD_TIME,
+ (int64_t)CDTIME_T_TO_TIME_T(vl->time), RIEMANN_EVENT_FIELD_TTL,
+ (float)CDTIME_T_TO_DOUBLE(vl->interval) * host->ttl_factor,
+ RIEMANN_EVENT_FIELD_STRING_ATTRIBUTES, "plugin", vl->plugin, "type",
+ vl->type, "ds_name", ds->ds[index].name, NULL,
+ RIEMANN_EVENT_FIELD_SERVICE, service_buffer, RIEMANN_EVENT_FIELD_NONE);
+
+ if (host->check_thresholds) {
+ const char *state = NULL;
+
+ switch (status) {
+ case STATE_OKAY:
+ state = "ok";
+ break;
+ case STATE_ERROR:
+ state = "critical";
+ break;
+ case STATE_WARNING:
+ state = "warning";
+ break;
+ case STATE_MISSING:
+ state = "unknown";
+ break;
+ }
+ if (state)
+ riemann_event_set(event, RIEMANN_EVENT_FIELD_STATE, state,
+ RIEMANN_EVENT_FIELD_NONE);
+ }
+
+ if (vl->plugin_instance[0] != 0)
+ riemann_event_string_attribute_add(event, "plugin_instance",
+ vl->plugin_instance);
+ if (vl->type_instance[0] != 0)
+ riemann_event_string_attribute_add(event, "type_instance",
+ vl->type_instance);
+
+ if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
+ char ds_type[DATA_MAX_NAME_LEN];
+
+ ssnprintf(ds_type, sizeof(ds_type), "%s:rate",
+ DS_TYPE_TO_STRING(ds->ds[index].type));
+ riemann_event_string_attribute_add(event, "ds_type", ds_type);
+ } else {
+ riemann_event_string_attribute_add(event, "ds_type",
+ DS_TYPE_TO_STRING(ds->ds[index].type));
+ }
+
+ {
+ char ds_index[DATA_MAX_NAME_LEN];
+
+ ssnprintf(ds_index, sizeof(ds_index), "%zu", index);
+ riemann_event_string_attribute_add(event, "ds_index", ds_index);
+ }
+
+ for (i = 0; i < riemann_attrs_num; i += 2)
+ riemann_event_string_attribute_add(event, riemann_attrs[i],
+ riemann_attrs[i + 1]);
+
+ for (i = 0; i < riemann_tags_num; i++)
+ riemann_event_tag_add(event, riemann_tags[i]);
+
+ if (ds->ds[index].type == DS_TYPE_GAUGE) {
+ riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D,
+ (double)vl->values[index].gauge,
+ RIEMANN_EVENT_FIELD_NONE);
+ } else if (rates != NULL) {
+ riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_D, (double)rates[index],
+ RIEMANN_EVENT_FIELD_NONE);
+ } else {
+ int64_t metric;
+
+ if (ds->ds[index].type == DS_TYPE_DERIVE)
+ metric = (int64_t)vl->values[index].derive;
+ else if (ds->ds[index].type == DS_TYPE_ABSOLUTE)
+ metric = (int64_t)vl->values[index].absolute;
+ else
+ metric = (int64_t)vl->values[index].counter;
+
+ riemann_event_set(event, RIEMANN_EVENT_FIELD_METRIC_S64, (int64_t)metric,
+ RIEMANN_EVENT_FIELD_NONE);
+ }
+
+ DEBUG("write_riemann plugin: Successfully created message for metric: "
+ "host = \"%s\", service = \"%s\"",
+ event->host, event->service);
+ return (event);
+} /* }}} riemann_event_t *wrr_value_to_event */
+
+static riemann_message_t *
+wrr_value_list_to_message(struct riemann_host const *host, /* {{{ */
+ data_set_t const *ds, value_list_t const *vl,
+ int *statuses) {
+ riemann_message_t *msg;
+ size_t i;
+ gauge_t *rates = NULL;
+
+ /* Initialize the Msg structure. */
+ msg = riemann_message_new();
+ if (msg == NULL) {
+ ERROR("write_riemann plugin: riemann_message_new failed.");
+ return (NULL);
+ }
+
+ if (host->store_rates) {
+ rates = uc_get_rate(ds, vl);
+ if (rates == NULL) {
+ ERROR("write_riemann plugin: uc_get_rate failed.");
+ riemann_message_free(msg);
+ return (NULL);
+ }
+ }
- msg__free_unpacked (msg, NULL);
- return 0;
-} /* }}} int riemann_recv_ack */
+ for (i = 0; i < vl->values_len; i++) {
+ riemann_event_t *event;
-/**
- * Function to send messages (Msg) to riemann.
- *
- * Acquires the host lock, disconnects on errors.
- */
-static int riemann_send(struct riemann_host *host, Msg const *msg) /* {{{ */
-{
- int status = 0;
- pthread_mutex_lock (&host->lock);
-
- status = riemann_send_msg(host, msg);
- if (status != 0) {
- riemann_disconnect (host);
- pthread_mutex_unlock (&host->lock);
- return status;
- }
-
- /*
- * For TCP we need to receive message acknowledgemenent.
- */
- if (host->use_tcp)
- {
- status = riemann_recv_ack(host);
-
- if (status != 0)
- {
- riemann_disconnect (host);
- pthread_mutex_unlock (&host->lock);
- return status;
- }
- }
-
- pthread_mutex_unlock (&host->lock);
- return 0;
-} /* }}} int riemann_send */
-
-static int riemann_event_add_tag (Event *event, char const *tag) /* {{{ */
-{
- return (strarray_add (&event->tags, &event->n_tags, tag));
-} /* }}} int riemann_event_add_tag */
-
-static int riemann_event_add_attribute(Event *event, /* {{{ */
- char const *key, char const *value)
-{
- Attribute **new_attributes;
- Attribute *a;
-
- new_attributes = realloc (event->attributes,
- sizeof (*event->attributes) * (event->n_attributes + 1));
- if (new_attributes == NULL)
- {
- ERROR ("write_riemann plugin: realloc failed.");
- return (ENOMEM);
- }
- event->attributes = new_attributes;
-
- a = malloc (sizeof (*a));
- if (a == NULL)
- {
- ERROR ("write_riemann plugin: malloc failed.");
- return (ENOMEM);
- }
- attribute__init (a);
-
- a->key = strdup (key);
- if (value != NULL)
- a->value = strdup (value);
-
- event->attributes[event->n_attributes] = a;
- event->n_attributes++;
-
- return (0);
-} /* }}} int riemann_event_add_attribute */
-
-static Msg *riemann_notification_to_protobuf(struct riemann_host *host, /* {{{ */
- notification_t const *n)
-{
- Msg *msg;
- Event *event;
- char service_buffer[6 * DATA_MAX_NAME_LEN];
- char const *severity;
- notification_meta_t *meta;
- int i;
-
- msg = malloc (sizeof (*msg));
- if (msg == NULL)
- {
- ERROR ("write_riemann plugin: malloc failed.");
- return (NULL);
- }
- memset (msg, 0, sizeof (*msg));
- msg__init (msg);
-
- msg->events = malloc (sizeof (*msg->events));
- if (msg->events == NULL)
- {
- ERROR ("write_riemann plugin: malloc failed.");
- sfree (msg);
- return (NULL);
- }
-
- event = malloc (sizeof (*event));
- if (event == NULL)
- {
- ERROR ("write_riemann plugin: malloc failed.");
- sfree (msg->events);
- sfree (msg);
- return (NULL);
- }
- memset (event, 0, sizeof (*event));
- event__init (event);
-
- msg->events[0] = event;
- msg->n_events = 1;
-
- event->host = strdup (n->host);
- event->time = CDTIME_T_TO_TIME_T (n->time);
- event->has_time = 1;
-
- switch (n->severity)
- {
- case NOTIF_OKAY: severity = "ok"; break;
- case NOTIF_WARNING: severity = "warning"; break;
- case NOTIF_FAILURE: severity = "critical"; break;
- default: severity = "unknown";
- }
- event->state = strdup (severity);
-
- riemann_event_add_tag (event, "notification");
- if (n->host[0] != 0)
- riemann_event_add_attribute (event, "host", n->host);
- if (n->plugin[0] != 0)
- riemann_event_add_attribute (event, "plugin", n->plugin);
- if (n->plugin_instance[0] != 0)
- riemann_event_add_attribute (event, "plugin_instance",
- n->plugin_instance);
-
- if (n->type[0] != 0)
- riemann_event_add_attribute (event, "type", n->type);
- if (n->type_instance[0] != 0)
- riemann_event_add_attribute (event, "type_instance",
- n->type_instance);
-
- for (i = 0; i < riemann_attrs_num; i += 2)
- riemann_event_add_attribute(event,
- riemann_attrs[i],
- riemann_attrs[i +1]);
-
- for (i = 0; i < riemann_tags_num; i++)
- riemann_event_add_tag (event, riemann_tags[i]);
-
- format_name (service_buffer, sizeof (service_buffer),
- /* host = */ "", n->plugin, n->plugin_instance,
- n->type, n->type_instance);
- event->service = strdup (&service_buffer[1]);
-
- if (n->message[0] != 0)
- riemann_event_add_attribute (event, "description", n->message);
-
- /* Pull in values from threshold and add extra attributes */
- for (meta = n->meta; meta != NULL; meta = meta->next)
- {
- if (strcasecmp ("CurrentValue", meta->name) == 0 && meta->type == NM_TYPE_DOUBLE)
- {
- event->metric_d = meta->nm_value.nm_double;
- event->has_metric_d = 1;
- continue;
- }
-
- if (meta->type == NM_TYPE_STRING) {
- riemann_event_add_attribute (event, meta->name, meta->nm_value.nm_string);
- continue;
- }
- }
-
- DEBUG ("write_riemann plugin: Successfully created protobuf for notification: "
- "host = \"%s\", service = \"%s\", state = \"%s\"",
- event->host, event->service, event->state);
- return (msg);
-} /* }}} Msg *riemann_notification_to_protobuf */
-
-static Event *riemann_value_to_protobuf(struct riemann_host const *host, /* {{{ */
- data_set_t const *ds,
- value_list_t const *vl, size_t index,
- gauge_t const *rates,
- int status)
-{
- Event *event;
- char name_buffer[5 * DATA_MAX_NAME_LEN];
- char service_buffer[6 * DATA_MAX_NAME_LEN];
- double ttl;
- int i;
-
- event = malloc (sizeof (*event));
- if (event == NULL)
- {
- ERROR ("write_riemann plugin: malloc failed.");
- return (NULL);
- }
- memset (event, 0, sizeof (*event));
- event__init (event);
-
- event->host = strdup (vl->host);
- event->time = CDTIME_T_TO_TIME_T (vl->time);
- event->has_time = 1;
-
- if (host->check_thresholds) {
- switch (status) {
- case STATE_OKAY:
- event->state = strdup("ok");
- break;
- case STATE_ERROR:
- event->state = strdup("critical");
- break;
- case STATE_WARNING:
- event->state = strdup("warning");
- break;
- case STATE_MISSING:
- event->state = strdup("unknown");
- break;
- }
- }
-
- ttl = CDTIME_T_TO_DOUBLE (vl->interval) * host->ttl_factor;
- event->ttl = (float) ttl;
- event->has_ttl = 1;
-
- riemann_event_add_attribute (event, "plugin", vl->plugin);
- if (vl->plugin_instance[0] != 0)
- riemann_event_add_attribute (event, "plugin_instance",
- vl->plugin_instance);
-
- riemann_event_add_attribute (event, "type", vl->type);
- if (vl->type_instance[0] != 0)
- riemann_event_add_attribute (event, "type_instance",
- vl->type_instance);
-
- if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL))
- {
- char ds_type[DATA_MAX_NAME_LEN];
-
- ssnprintf (ds_type, sizeof (ds_type), "%s:rate",
- DS_TYPE_TO_STRING(ds->ds[index].type));
- riemann_event_add_attribute (event, "ds_type", ds_type);
- }
- else
- {
- riemann_event_add_attribute (event, "ds_type",
- DS_TYPE_TO_STRING(ds->ds[index].type));
- }
- riemann_event_add_attribute (event, "ds_name", ds->ds[index].name);
- {
- char ds_index[DATA_MAX_NAME_LEN];
-
- ssnprintf (ds_index, sizeof (ds_index), "%zu", index);
- riemann_event_add_attribute (event, "ds_index", ds_index);
- }
-
- for (i = 0; i < riemann_attrs_num; i += 2)
- riemann_event_add_attribute(event,
- riemann_attrs[i],
- riemann_attrs[i +1]);
-
- for (i = 0; i < riemann_tags_num; i++)
- riemann_event_add_tag (event, riemann_tags[i]);
-
- if (ds->ds[index].type == DS_TYPE_GAUGE)
- {
- event->has_metric_d = 1;
- event->metric_d = (double) vl->values[index].gauge;
- }
- else if (rates != NULL)
- {
- event->has_metric_d = 1;
- event->metric_d = (double) rates[index];
- }
- else
- {
- event->has_metric_sint64 = 1;
- if (ds->ds[index].type == DS_TYPE_DERIVE)
- event->metric_sint64 = (int64_t) vl->values[index].derive;
- else if (ds->ds[index].type == DS_TYPE_ABSOLUTE)
- event->metric_sint64 = (int64_t) vl->values[index].absolute;
- else
- event->metric_sint64 = (int64_t) vl->values[index].counter;
- }
-
- format_name (name_buffer, sizeof (name_buffer),
- /* host = */ "", vl->plugin, vl->plugin_instance,
- vl->type, vl->type_instance);
- if (host->always_append_ds || (ds->ds_num > 1))
- {
- if (host->event_service_prefix == NULL)
- ssnprintf (service_buffer, sizeof (service_buffer), "%s/%s",
- &name_buffer[1], ds->ds[index].name);
- else
- ssnprintf (service_buffer, sizeof (service_buffer), "%s%s/%s",
- host->event_service_prefix, &name_buffer[1], ds->ds[index].name);
- }
- else
- {
- if (host->event_service_prefix == NULL)
- sstrncpy (service_buffer, &name_buffer[1], sizeof (service_buffer));
- else
- ssnprintf (service_buffer, sizeof (service_buffer), "%s%s",
- host->event_service_prefix, &name_buffer[1]);
- }
-
- event->service = strdup (service_buffer);
-
- DEBUG ("write_riemann plugin: Successfully created protobuf for metric: "
- "host = \"%s\", service = \"%s\"",
- event->host, event->service);
- return (event);
-} /* }}} Event *riemann_value_to_protobuf */
-
-static Msg *riemann_value_list_to_protobuf (struct riemann_host const *host, /* {{{ */
- data_set_t const *ds,
- value_list_t const *vl,
- int *statuses)
-{
- Msg *msg;
- size_t i;
- gauge_t *rates = NULL;
-
- /* Initialize the Msg structure. */
- msg = malloc (sizeof (*msg));
- if (msg == NULL)
- {
- ERROR ("write_riemann plugin: malloc failed.");
- return (NULL);
- }
- memset (msg, 0, sizeof (*msg));
- msg__init (msg);
-
- /* Set up events. First, the list of pointers. */
- msg->n_events = (size_t) vl->values_len;
- msg->events = calloc (msg->n_events, sizeof (*msg->events));
- if (msg->events == NULL)
- {
- ERROR ("write_riemann plugin: calloc failed.");
- riemann_msg_protobuf_free (msg);
- return (NULL);
- }
-
- if (host->store_rates)
- {
- rates = uc_get_rate (ds, vl);
- if (rates == NULL)
- {
- ERROR ("write_riemann plugin: uc_get_rate failed.");
- riemann_msg_protobuf_free (msg);
- return (NULL);
- }
- }
-
- for (i = 0; i < msg->n_events; i++)
- {
- msg->events[i] = riemann_value_to_protobuf (host, ds, vl,
- (int) i, rates, statuses[i]);
- if (msg->events[i] == NULL)
- {
- riemann_msg_protobuf_free (msg);
- sfree (rates);
- return (NULL);
- }
- }
-
- sfree (rates);
- return (msg);
-} /* }}} Msg *riemann_value_list_to_protobuf */
+ event = wrr_value_to_event(host, ds, vl, (int)i, rates, statuses[i]);
+ if (event == NULL) {
+ riemann_message_free(msg);
+ sfree(rates);
+ return (NULL);
+ }
+ riemann_message_append_events(msg, event, NULL);
+ }
+ sfree(rates);
+ return (msg);
+} /* }}} riemann_message_t *wrr_value_list_to_message */
/*
* Always call while holding host->lock !
*/
-static int riemann_batch_flush_nolock (cdtime_t timeout,
- struct riemann_host *host)
-{
- cdtime_t now;
- int status = 0;
-
- if (timeout > 0) {
- now = cdtime ();
- if ((host->batch_init + timeout) > now)
- return status;
+static int wrr_batch_flush_nolock(cdtime_t timeout, struct riemann_host *host) {
+ cdtime_t now;
+ int status = 0;
+
+ now = cdtime();
+ if (timeout > 0) {
+ if ((host->batch_init + timeout) > now) {
+ return status;
}
- riemann_send_msg(host, host->batch_msg);
- riemann_msg_protobuf_free(host->batch_msg);
-
- if (host->use_tcp && ((status = riemann_recv_ack(host)) != 0))
- riemann_disconnect (host);
+ }
+ wrr_send_nolock(host, host->batch_msg);
+ riemann_message_free(host->batch_msg);
- host->batch_init = cdtime();
- host->batch_msg = NULL;
- return status;
+ host->batch_init = now;
+ host->batch_msg = NULL;
+ return status;
}
-static int riemann_batch_flush (cdtime_t timeout,
- const char *identifier __attribute__((unused)),
- user_data_t *user_data)
-{
- struct riemann_host *host;
- int status;
+static int wrr_batch_flush(cdtime_t timeout,
+ const char *identifier __attribute__((unused)),
+ user_data_t *user_data) {
+ struct riemann_host *host;
+ int status;
+
+ if (user_data == NULL)
+ return (-EINVAL);
+
+ host = user_data->data;
+ pthread_mutex_lock(&host->lock);
+ status = wrr_batch_flush_nolock(timeout, host);
+ if (status != 0)
+ c_complain(
+ LOG_ERR, &host->init_complaint,
+ "write_riemann plugin: riemann_client_send failed with status %i",
+ status);
+ else
+ c_release(LOG_DEBUG, &host->init_complaint,
+ "write_riemann plugin: batch sent.");
+
+ pthread_mutex_unlock(&host->lock);
+ return status;
+}
- if (user_data == NULL)
- return (-EINVAL);
+static int wrr_batch_add_value_list(struct riemann_host *host, /* {{{ */
+ data_set_t const *ds,
+ value_list_t const *vl, int *statuses) {
+ riemann_message_t *msg;
+ size_t len;
+ int ret;
+ cdtime_t timeout;
- host = user_data->data;
- pthread_mutex_lock (&host->lock);
- status = riemann_batch_flush_nolock (timeout, host);
- if (status != 0)
- ERROR ("write_riemann plugin: riemann_send failed with status %i",
- status);
+ msg = wrr_value_list_to_message(host, ds, vl, statuses);
+ if (msg == NULL)
+ return -1;
- pthread_mutex_unlock(&host->lock);
- return status;
-}
+ pthread_mutex_lock(&host->lock);
-static int riemann_batch_add_value_list (struct riemann_host *host, /* {{{ */
- data_set_t const *ds,
- value_list_t const *vl,
- int *statuses)
-{
- size_t i;
- Event **events;
- Msg *msg;
- size_t len;
- int ret;
+ if (host->batch_msg == NULL) {
+ host->batch_msg = msg;
+ } else {
+ int status;
- msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
- if (msg == NULL)
- return -1;
+ status = riemann_message_append_events_n(host->batch_msg, msg->n_events,
+ msg->events);
+ msg->n_events = 0;
+ msg->events = NULL;
- pthread_mutex_lock(&host->lock);
+ riemann_message_free(msg);
- if (host->batch_msg == NULL) {
- host->batch_msg = msg;
- } else {
- len = msg->n_events + host->batch_msg->n_events;
- events = realloc(host->batch_msg->events,
- (len * sizeof(*host->batch_msg->events)));
- if (events == NULL) {
- pthread_mutex_unlock(&host->lock);
- ERROR ("write_riemann plugin: out of memory");
- riemann_msg_protobuf_free (msg);
- return -1;
- }
- host->batch_msg->events = events;
-
- for (i = host->batch_msg->n_events; i < len; i++)
- host->batch_msg->events[i] = msg->events[i - host->batch_msg->n_events];
-
- host->batch_msg->n_events = len;
- sfree (msg->events);
- msg->n_events = 0;
- sfree (msg);
+ if (status != 0) {
+ pthread_mutex_unlock(&host->lock);
+ ERROR("write_riemann plugin: out of memory");
+ return -1;
}
-
- len = msg__get_packed_size(host->batch_msg);
- ret = 0;
- if (len >= host->batch_max) {
- ret = riemann_batch_flush_nolock(0, host);
+ }
+
+ len = riemann_message_get_packed_size(host->batch_msg);
+ ret = 0;
+ if ((host->batch_max < 0) || (((size_t)host->batch_max) <= len)) {
+ ret = wrr_batch_flush_nolock(0, host);
+ } else {
+ if (host->batch_timeout > 0) {
+ timeout = TIME_T_TO_CDTIME_T((time_t)host->batch_timeout);
+ ret = wrr_batch_flush_nolock(timeout, host);
}
+ }
- pthread_mutex_unlock(&host->lock);
- return ret;
-} /* }}} Msg *riemann_batch_add_value_list */
-
-static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{ */
-{
- int status;
- struct riemann_host *host = ud->data;
- Msg *msg;
+ pthread_mutex_unlock(&host->lock);
+ return ret;
+} /* }}} riemann_message_t *wrr_batch_add_value_list */
- if (!host->notifications)
- return 0;
-
- /*
- * Never batch for notifications, send them ASAP
- */
- msg = riemann_notification_to_protobuf (host, n);
- if (msg == NULL)
- return (-1);
-
- status = riemann_send (host, msg);
- if (status != 0)
- ERROR ("write_riemann plugin: riemann_send failed with status %i",
- status);
-
- riemann_msg_protobuf_free (msg);
- return (status);
-} /* }}} int riemann_notification */
-
-static int riemann_write(const data_set_t *ds, /* {{{ */
- const value_list_t *vl,
- user_data_t *ud)
+static int wrr_notification(const notification_t *n, user_data_t *ud) /* {{{ */
{
- int status = 0;
- int statuses[vl->values_len];
- struct riemann_host *host = ud->data;
- Msg *msg;
+ int status;
+ struct riemann_host *host = ud->data;
+ riemann_message_t *msg;
+
+ if (!host->notifications)
+ return 0;
+
+ /*
+ * Never batch for notifications, send them ASAP
+ */
+ msg = wrr_notification_to_message(host, n);
+ if (msg == NULL)
+ return (-1);
+
+ status = wrr_send(host, msg);
+ if (status != 0)
+ c_complain(
+ LOG_ERR, &host->init_complaint,
+ "write_riemann plugin: riemann_client_send failed with status %i",
+ status);
+ else
+ c_release(LOG_DEBUG, &host->init_complaint,
+ "write_riemann plugin: riemann_client_send succeeded");
+
+ riemann_message_free(msg);
+ return (status);
+} /* }}} int wrr_notification */
+
+static int wrr_write(const data_set_t *ds, /* {{{ */
+ const value_list_t *vl, user_data_t *ud) {
+ int status = 0;
+ int statuses[vl->values_len];
+ struct riemann_host *host = ud->data;
+ riemann_message_t *msg;
+
+ if (host->check_thresholds) {
+ status = write_riemann_threshold_check(ds, vl, statuses);
+ if (status != 0)
+ return status;
+ } else {
+ memset(statuses, 0, sizeof(statuses));
+ }
+
+ if (host->client_type != RIEMANN_CLIENT_UDP && host->batch_mode) {
+ wrr_batch_add_value_list(host, ds, vl, statuses);
+ } else {
+ msg = wrr_value_list_to_message(host, ds, vl, statuses);
+ if (msg == NULL)
+ return (-1);
- if (host->check_thresholds)
- write_riemann_threshold_check(ds, vl, statuses);
+ status = wrr_send(host, msg);
- if (host->use_tcp == 1 && host->batch_mode) {
+ riemann_message_free(msg);
+ }
+ return status;
+} /* }}} int wrr_write */
- riemann_batch_add_value_list (host, ds, vl, statuses);
+static void wrr_free(void *p) /* {{{ */
+{
+ struct riemann_host *host = p;
+ if (host == NULL)
+ return;
- } else {
+ pthread_mutex_lock(&host->lock);
- msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
- if (msg == NULL)
- return (-1);
+ host->reference_count--;
+ if (host->reference_count > 0) {
+ pthread_mutex_unlock(&host->lock);
+ return;
+ }
- status = riemann_send (host, msg);
- if (status != 0)
- ERROR ("write_riemann plugin: riemann_send failed with status %i",
- status);
+ wrr_disconnect(host);
- riemann_msg_protobuf_free (msg);
- }
- return status;
-} /* }}} int riemann_write */
+ pthread_mutex_destroy(&host->lock);
+ sfree(host);
+} /* }}} void wrr_free */
-static void riemann_free(void *p) /* {{{ */
+static int wrr_config_node(oconfig_item_t *ci) /* {{{ */
{
- struct riemann_host *host = p;
-
- if (host == NULL)
- return;
-
- pthread_mutex_lock (&host->lock);
-
- host->reference_count--;
- if (host->reference_count > 0)
- {
- pthread_mutex_unlock (&host->lock);
- return;
- }
+ struct riemann_host *host = NULL;
+ int status = 0;
+ int i;
+ oconfig_item_t *child;
+ char callback_name[DATA_MAX_NAME_LEN];
+
+ if ((host = calloc(1, sizeof(*host))) == NULL) {
+ ERROR("write_riemann plugin: calloc failed.");
+ return ENOMEM;
+ }
+ pthread_mutex_init(&host->lock, NULL);
+ C_COMPLAIN_INIT(&host->init_complaint);
+ host->reference_count = 1;
+ host->node = NULL;
+ host->port = 0;
+ host->notifications = 1;
+ host->check_thresholds = 0;
+ host->store_rates = 1;
+ host->always_append_ds = 0;
+ host->batch_mode = 1;
+ host->batch_max = RIEMANN_BATCH_MAX; /* typical MSS */
+ host->batch_init = cdtime();
+ host->batch_timeout = 0;
+ host->ttl_factor = RIEMANN_TTL_FACTOR;
+ host->client = NULL;
+ host->client_type = RIEMANN_CLIENT_TCP;
+ host->timeout.tv_sec = 0;
+ host->timeout.tv_usec = 0;
+
+ status = cf_util_get_string(ci, &host->name);
+ if (status != 0) {
+ WARNING("write_riemann plugin: Required host name is missing.");
+ wrr_free(host);
+ return -1;
+ }
+
+ for (i = 0; i < ci->children_num; i++) {
+ /*
+ * The code here could be simplified but makes room
+ * for easy adding of new options later on.
+ */
+ child = &ci->children[i];
+ status = 0;
+
+ if (strcasecmp("Host", child->key) == 0) {
+ status = cf_util_get_string(child, &host->node);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("Notifications", child->key) == 0) {
+ status = cf_util_get_boolean(child, &host->notifications);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("EventServicePrefix", child->key) == 0) {
+ status = cf_util_get_string(child, &host->event_service_prefix);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("CheckThresholds", child->key) == 0) {
+ status = cf_util_get_boolean(child, &host->check_thresholds);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("Batch", child->key) == 0) {
+ status = cf_util_get_boolean(child, &host->batch_mode);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("BatchMaxSize", child->key) == 0) {
+ status = cf_util_get_int(child, &host->batch_max);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("BatchFlushTimeout", child->key) == 0) {
+ status = cf_util_get_int(child, &host->batch_timeout);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("Timeout", child->key) == 0) {
+#if RCC_VERSION_NUMBER >= 0x010800
+ status = cf_util_get_int(child, (int *)&host->timeout.tv_sec);
+ if (status != 0)
+ break;
+#else
+ WARNING("write_riemann plugin: The Timeout option is not supported. Please upgrade the Riemann client to at least 1.8.0.");
+#endif
+ } else if (strcasecmp("Port", child->key) == 0) {
+ host->port = cf_util_get_port_number(child);
+ if (host->port == -1) {
+ ERROR("write_riemann plugin: Invalid argument "
+ "configured for the \"Port\" "
+ "option.");
+ break;
+ }
+ } else if (strcasecmp("Protocol", child->key) == 0) {
+ char tmp[16];
+ status = cf_util_get_string_buffer(child, tmp, sizeof(tmp));
+ if (status != 0) {
+ ERROR("write_riemann plugin: cf_util_get_"
+ "string_buffer failed with "
+ "status %i.",
+ status);
+ break;
+ }
+
+ if (strcasecmp("UDP", tmp) == 0)
+ host->client_type = RIEMANN_CLIENT_UDP;
+ else if (strcasecmp("TCP", tmp) == 0)
+ host->client_type = RIEMANN_CLIENT_TCP;
+ else if (strcasecmp("TLS", tmp) == 0)
+ host->client_type = RIEMANN_CLIENT_TLS;
+ else
+ WARNING("write_riemann plugin: The value "
+ "\"%s\" is not valid for the "
+ "\"Protocol\" option. Use "
+ "either \"UDP\", \"TCP\" or \"TLS\".",
+ tmp);
+ } else if (strcasecmp("TLSCAFile", child->key) == 0) {
+ status = cf_util_get_string(child, &host->tls_ca_file);
+ if (status != 0) {
+ ERROR("write_riemann plugin: cf_util_get_"
+ "string_buffer failed with "
+ "status %i.",
+ status);
+ break;
+ }
+ } else if (strcasecmp("TLSCertFile", child->key) == 0) {
+ status = cf_util_get_string(child, &host->tls_cert_file);
+ if (status != 0) {
+ ERROR("write_riemann plugin: cf_util_get_"
+ "string_buffer failed with "
+ "status %i.",
+ status);
+ break;
+ }
+ } else if (strcasecmp("TLSKeyFile", child->key) == 0) {
+ status = cf_util_get_string(child, &host->tls_key_file);
+ if (status != 0) {
+ ERROR("write_riemann plugin: cf_util_get_"
+ "string_buffer failed with "
+ "status %i.",
+ status);
+ break;
+ }
+ } else if (strcasecmp("StoreRates", child->key) == 0) {
+ status = cf_util_get_boolean(child, &host->store_rates);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("AlwaysAppendDS", child->key) == 0) {
+ status = cf_util_get_boolean(child, &host->always_append_ds);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("TTLFactor", child->key) == 0) {
+ double tmp = NAN;
+ status = cf_util_get_double(child, &tmp);
+ if (status != 0)
+ break;
+ if (tmp >= 2.0) {
+ host->ttl_factor = tmp;
+ } else if (tmp >= 1.0) {
+ NOTICE("write_riemann plugin: The configured "
+ "TTLFactor is very small "
+ "(%.1f). A value of 2.0 or "
+ "greater is recommended.",
+ tmp);
+ host->ttl_factor = tmp;
+ } else if (tmp > 0.0) {
+ WARNING("write_riemann plugin: The configured "
+ "TTLFactor is too small to be "
+ "useful (%.1f). I'll use it "
+ "since the user knows best, "
+ "but under protest.",
+ tmp);
+ host->ttl_factor = tmp;
+ } else { /* zero, negative and NAN */
+ ERROR("write_riemann plugin: The configured "
+ "TTLFactor is invalid (%.1f).",
+ tmp);
+ }
+ } else {
+ WARNING("write_riemann plugin: ignoring unknown config "
+ "option: \"%s\"",
+ child->key);
+ }
+ }
+ if (status != 0) {
+ wrr_free(host);
+ return status;
+ }
+
+ ssnprintf(callback_name, sizeof(callback_name), "write_riemann/%s",
+ host->name);
+
+ user_data_t ud = {
+ .data = host,
+ .free_func = wrr_free
+ };
+
+ pthread_mutex_lock(&host->lock);
+
+ status = plugin_register_write(callback_name, wrr_write, &ud);
+
+ if (host->client_type != RIEMANN_CLIENT_UDP && host->batch_mode) {
+ ud.free_func = NULL;
+ plugin_register_flush(callback_name, wrr_batch_flush, &ud);
+ }
+ if (status != 0)
+ WARNING("write_riemann plugin: plugin_register_write (\"%s\") "
+ "failed with status %i.",
+ callback_name, status);
+ else /* success */
+ host->reference_count++;
+
+ status = plugin_register_notification(callback_name, wrr_notification, &ud);
+ if (status != 0)
+ WARNING("write_riemann plugin: plugin_register_notification (\"%s\") "
+ "failed with status %i.",
+ callback_name, status);
+ else /* success */
+ host->reference_count++;
+
+ if (host->reference_count <= 1) {
+ /* Both callbacks failed => free memory.
+ * We need to unlock here, because riemann_free() will lock.
+ * This is not a race condition, because we're the only one
+ * holding a reference. */
+ pthread_mutex_unlock(&host->lock);
+ wrr_free(host);
+ return (-1);
+ }
- riemann_disconnect (host);
+ host->reference_count--;
+ pthread_mutex_unlock(&host->lock);
- sfree(host->service);
- pthread_mutex_destroy (&host->lock);
- sfree(host);
-} /* }}} void riemann_free */
+ return status;
+} /* }}} int wrr_config_node */
-static int riemann_config_node(oconfig_item_t *ci) /* {{{ */
+static int wrr_config(oconfig_item_t *ci) /* {{{ */
{
- struct riemann_host *host = NULL;
- int status = 0;
- int i;
- oconfig_item_t *child;
- char callback_name[DATA_MAX_NAME_LEN];
- user_data_t ud;
-
- if ((host = calloc(1, sizeof (*host))) == NULL) {
- ERROR ("write_riemann plugin: calloc failed.");
- return ENOMEM;
- }
- pthread_mutex_init (&host->lock, NULL);
- host->reference_count = 1;
- host->node = NULL;
- host->service = NULL;
- host->notifications = 1;
- host->check_thresholds = 0;
- host->store_rates = 1;
- host->always_append_ds = 0;
- host->use_tcp = 1;
- host->batch_mode = 1;
- host->batch_max = RIEMANN_BATCH_MAX; /* typical MSS */
- host->batch_init = cdtime();
- host->ttl_factor = RIEMANN_TTL_FACTOR;
-
- status = cf_util_get_string (ci, &host->name);
- if (status != 0) {
- WARNING("write_riemann plugin: Required host name is missing.");
- riemann_free (host);
- return -1;
- }
-
- for (i = 0; i < ci->children_num; i++) {
- /*
- * The code here could be simplified but makes room
- * for easy adding of new options later on.
- */
- child = &ci->children[i];
- status = 0;
-
- if (strcasecmp ("Host", child->key) == 0) {
- status = cf_util_get_string (child, &host->node);
- if (status != 0)
- break;
- } else if (strcasecmp ("Notifications", child->key) == 0) {
- status = cf_util_get_boolean(child, &host->notifications);
- if (status != 0)
- break;
- } else if (strcasecmp ("EventServicePrefix", child->key) == 0) {
- status = cf_util_get_string (child, &host->event_service_prefix);
- if (status != 0)
- break;
- } else if (strcasecmp ("CheckThresholds", child->key) == 0) {
- status = cf_util_get_boolean(child, &host->check_thresholds);
- if (status != 0)
- break;
- } else if (strcasecmp ("Batch", child->key) == 0) {
- status = cf_util_get_boolean(child, &host->batch_mode);
- if (status != 0)
- break;
- } else if (strcasecmp("BatchMaxSize", child->key) == 0) {
- status = cf_util_get_int(child, &host->batch_max);
- if (status != 0)
- break;
- } else if (strcasecmp ("Port", child->key) == 0) {
- status = cf_util_get_service (child, &host->service);
- if (status != 0) {
- ERROR ("write_riemann plugin: Invalid argument "
- "configured for the \"Port\" "
- "option.");
- break;
- }
- } else if (strcasecmp ("Protocol", child->key) == 0) {
- char tmp[16];
- status = cf_util_get_string_buffer (child,
- tmp, sizeof (tmp));
- if (status != 0)
- {
- ERROR ("write_riemann plugin: cf_util_get_"
- "string_buffer failed with "
- "status %i.", status);
- break;
- }
-
- if (strcasecmp ("UDP", tmp) == 0)
- host->use_tcp = 0;
- else if (strcasecmp ("TCP", tmp) == 0)
- host->use_tcp = 1;
- else
- WARNING ("write_riemann plugin: The value "
- "\"%s\" is not valid for the "
- "\"Protocol\" option. Use "
- "either \"UDP\" or \"TCP\".",
- tmp);
- } else if (strcasecmp ("StoreRates", child->key) == 0) {
- status = cf_util_get_boolean (child, &host->store_rates);
- if (status != 0)
- break;
- } else if (strcasecmp ("AlwaysAppendDS", child->key) == 0) {
- status = cf_util_get_boolean (child,
- &host->always_append_ds);
- if (status != 0)
- break;
- } else if (strcasecmp ("TTLFactor", child->key) == 0) {
- double tmp = NAN;
- status = cf_util_get_double (child, &tmp);
- if (status != 0)
- break;
- if (tmp >= 2.0) {
- host->ttl_factor = tmp;
- } else if (tmp >= 1.0) {
- NOTICE ("write_riemann plugin: The configured "
- "TTLFactor is very small "
- "(%.1f). A value of 2.0 or "
- "greater is recommended.",
- tmp);
- host->ttl_factor = tmp;
- } else if (tmp > 0.0) {
- WARNING ("write_riemann plugin: The configured "
- "TTLFactor is too small to be "
- "useful (%.1f). I'll use it "
- "since the user knows best, "
- "but under protest.",
- tmp);
- host->ttl_factor = tmp;
- } else { /* zero, negative and NAN */
- ERROR ("write_riemann plugin: The configured "
- "TTLFactor is invalid (%.1f).",
- tmp);
- }
- } else {
- WARNING("write_riemann plugin: ignoring unknown config "
- "option: \"%s\"", child->key);
- }
- }
- if (status != 0) {
- riemann_free (host);
- return status;
- }
-
- ssnprintf (callback_name, sizeof (callback_name), "write_riemann/%s",
- host->name);
- ud.data = host;
- ud.free_func = riemann_free;
-
- pthread_mutex_lock (&host->lock);
-
- status = plugin_register_write (callback_name, riemann_write, &ud);
-
- if (host->use_tcp == 1 && host->batch_mode) {
- ud.free_func = NULL;
- plugin_register_flush(callback_name, riemann_batch_flush, &ud);
+ int i;
+ oconfig_item_t *child;
+ int status;
+
+ for (i = 0; i < ci->children_num; i++) {
+ child = &ci->children[i];
+
+ if (strcasecmp("Node", child->key) == 0) {
+ wrr_config_node(child);
+ } else if (strcasecmp(child->key, "attribute") == 0) {
+ char *key = NULL;
+ char *val = NULL;
+
+ if (child->values_num != 2) {
+ WARNING("riemann attributes need both a key and a value.");
+ return (-1);
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("riemann attribute needs string arguments.");
+ return (-1);
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
+ return (-1);
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
+ sfree(key);
+ return (-1);
+ }
+ strarray_add(&riemann_attrs, &riemann_attrs_num, key);
+ strarray_add(&riemann_attrs, &riemann_attrs_num, val);
+ DEBUG("write_riemann: got attr: %s => %s", key, val);
+ sfree(key);
+ sfree(val);
+ } else if (strcasecmp(child->key, "tag") == 0) {
+ char *tmp = NULL;
+ status = cf_util_get_string(child, &tmp);
+ if (status != 0)
+ continue;
+
+ strarray_add(&riemann_tags, &riemann_tags_num, tmp);
+ DEBUG("write_riemann plugin: Got tag: %s", tmp);
+ sfree(tmp);
+ } else {
+ WARNING("write_riemann plugin: Ignoring unknown "
+ "configuration option \"%s\" at top level.",
+ child->key);
}
- if (status != 0)
- WARNING ("write_riemann plugin: plugin_register_write (\"%s\") "
- "failed with status %i.",
- callback_name, status);
- else /* success */
- host->reference_count++;
-
- status = plugin_register_notification (callback_name,
- riemann_notification, &ud);
- if (status != 0)
- WARNING ("write_riemann plugin: plugin_register_notification (\"%s\") "
- "failed with status %i.",
- callback_name, status);
- else /* success */
- host->reference_count++;
-
- if (host->reference_count <= 1)
- {
- /* Both callbacks failed => free memory.
- * We need to unlock here, because riemann_free() will lock.
- * This is not a race condition, because we're the only one
- * holding a reference. */
- pthread_mutex_unlock (&host->lock);
- riemann_free (host);
- return (-1);
- }
-
- host->reference_count--;
- pthread_mutex_unlock (&host->lock);
-
- return status;
-} /* }}} int riemann_config_node */
-
-static int riemann_config(oconfig_item_t *ci) /* {{{ */
-{
- int i;
- oconfig_item_t *child;
- int status;
-
- for (i = 0; i < ci->children_num; i++) {
- child = &ci->children[i];
-
- if (strcasecmp("Node", child->key) == 0) {
- riemann_config_node (child);
- } else if (strcasecmp(child->key, "attribute") == 0) {
- char *key = NULL;
- char *val = NULL;
-
- if (child->values_num != 2) {
- WARNING("riemann attributes need both a key and a value.");
- return (-1);
- }
- if (child->values[0].type != OCONFIG_TYPE_STRING ||
- child->values[1].type != OCONFIG_TYPE_STRING) {
- WARNING("riemann attribute needs string arguments.");
- return (-1);
- }
- if ((key = strdup(child->values[0].value.string)) == NULL) {
- WARNING("cannot allocate memory for attribute key.");
- return (-1);
- }
- if ((val = strdup(child->values[1].value.string)) == NULL) {
- WARNING("cannot allocate memory for attribute value.");
- sfree (key);
- return (-1);
- }
- strarray_add(&riemann_attrs, &riemann_attrs_num, key);
- strarray_add(&riemann_attrs, &riemann_attrs_num, val);
- DEBUG("write_riemann: got attr: %s => %s", key, val);
- sfree(key);
- sfree(val);
- } else if (strcasecmp(child->key, "tag") == 0) {
- char *tmp = NULL;
- status = cf_util_get_string(child, &tmp);
- if (status != 0)
- continue;
-
- strarray_add (&riemann_tags, &riemann_tags_num, tmp);
- DEBUG("write_riemann plugin: Got tag: %s", tmp);
- sfree (tmp);
- } else {
- WARNING ("write_riemann plugin: Ignoring unknown "
- "configuration option \"%s\" at top level.",
- child->key);
- }
- }
- return (0);
-} /* }}} int riemann_config */
-
-void module_register(void)
-{
- plugin_register_complex_config ("write_riemann", riemann_config);
+ }
+ return (0);
+} /* }}} int wrr_config */
+
+void module_register(void) {
+ plugin_register_complex_config("write_riemann", wrr_config);
}
/* vim: set sw=8 sts=8 ts=8 noet : */
index 40093663f4ef42b8bfe361c51f2d13b89ad669b6..d393994b6a7f8820699250a4d8d9bccd6fd86026 100644 (file)
int *statuses)
{ /* {{{ */
int ret = -1;
- int i;
int status;
gauge_t values_copy[ds->ds_num];
}
/* Prepare `sum' and `num'. */
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
if (!isnan (values[i]))
{
num++;
if ((num == 0) /* All data sources are undefined. */
|| (sum == 0.0)) /* Sum is zero, cannot calculate percentage. */
{
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
values_copy[i] = NAN;
}
else /* We can actually calculate the percentage. */
{
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
values_copy[i] = 100.0 * values[i] / sum;
}
} /* if (UT_FLAG_PERCENTAGE) */
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
status = ut_check_one_data_source (ds, vl, th, values_copy, i);
if (status != -1) {
@@ -202,7 +201,9 @@ int write_riemann_threshold_check (const data_set_t *ds, const value_list_t *vl,
gauge_t *values;
int status;
+ assert (vl->values_len > 0);
memset(statuses, 0, vl->values_len * sizeof(*statuses));
+
if (threshold_tree == NULL)
return 0;
diff --git a/src/write_sensu.c b/src/write_sensu.c
index 0d568fe6118d8b9808710e22f10db2ff7d548d59..d764d2605351cefd716547a055d09437cac39ccb 100644 (file)
--- a/src/write_sensu.c
+++ b/src/write_sensu.c
#define _GNU_SOURCE
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
-#include "configfile.h"
#include "utils_cache.h"
-#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <inttypes.h>
-#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
#define SENSU_HOST "localhost"
#define SENSU_PORT "3030"
+#ifdef HAVE_ASPRINTF
+#define my_asprintf asprintf
+#define my_vasprintf vasprintf
+#else
+/*
+ * asprintf() is available from Solaris 10 update 11.
+ * For older versions, use asprintf() portable implementation from
+ * https://github.com/littlstar/asprintf.c/blob/master/
+ * copyright (c) 2014 joseph werle <joseph.werle@gmail.com> under MIT license.
+ */
+
+static int my_vasprintf(char **str, const char *fmt, va_list args) {
+ int size = 0;
+ va_list tmpa;
+ // copy
+ va_copy(tmpa, args);
+ // apply variadic arguments to
+ // sprintf with format to get size
+ size = vsnprintf(NULL, size, fmt, tmpa);
+ // toss args
+ va_end(tmpa);
+ // return -1 to be compliant if
+ // size is less than 0
+ if (size < 0) { return -1; }
+ // alloc with size plus 1 for `\0'
+ *str = (char *) malloc(size + 1);
+ // return -1 to be compliant
+ // if pointer is `NULL'
+ if (NULL == *str) { return -1; }
+ // format string with original
+ // variadic arguments and set new size
+ size = vsprintf(*str, fmt, args);
+ return size;
+}
+
+static int my_asprintf(char **str, const char *fmt, ...) {
+ int size = 0;
+ va_list args;
+ // init variadic argumens
+ va_start(args, fmt);
+ // format and get size
+ size = my_vasprintf(str, fmt, args);
+ // toss args
+ va_end(args);
+ return size;
+}
+
+#endif
+
struct str_list {
int nb_strs;
char **strs;
static void free_str_list(struct str_list *strs) /* {{{ */
{
- int i;
- for (i=0; i<strs->nb_strs; i++)
+ for (int i=0; i<strs->nb_strs; i++)
free(strs->strs[i]);
free(strs->strs);
}
static int sensu_connect(struct sensu_host *host) /* {{{ */
{
int e;
- struct addrinfo *ai, hints;
char const *node;
char const *service;
// Resolve the target if we haven't done already
if (!(host->flags & F_READY)) {
- memset(&hints, 0, sizeof(hints));
memset(&service, 0, sizeof(service));
host->res = NULL;
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_STREAM;
-#ifdef AI_ADDRCONFIG
- hints.ai_flags |= AI_ADDRCONFIG;
-#endif
node = (host->node != NULL) ? host->node : SENSU_HOST;
service = (host->service != NULL) ? host->service : SENSU_PORT;
- if ((e = getaddrinfo(node, service, &hints, &(host->res))) != 0) {
+ struct addrinfo ai_hints = {
+ .ai_family = AF_INET,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_socktype = SOCK_STREAM
+ };
+
+ if ((e = getaddrinfo(node, service, &ai_hints, &(host->res))) != 0) {
ERROR("write_sensu plugin: Unable to resolve host \"%s\": %s",
node, gai_strerror(e));
return -1;
struct linger so_linger;
host->s = -1;
- for (ai = host->res; ai != NULL; ai = ai->ai_next) {
+ for (struct addrinfo *ai = host->res; ai != NULL; ai = ai->ai_next) {
// create the socket
if ((host->s = socket(ai->ai_family,
ai->ai_socktype,
if (setsockopt(host->s, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger) != 0)
WARNING("write_sensu plugin: failed to set socket close() lingering");
+ set_sock_opts(host->s);
+
// connect the socket
if (connect(host->s, ai->ai_addr, ai->ai_addrlen) != 0) {
close(host->s);
static char *build_json_str_list(const char *tag, struct str_list const *list) /* {{{ */
{
int res;
- char *ret_str;
+ char *ret_str = NULL;
char *temp_str;
- int i;
if (list->nb_strs == 0) {
ret_str = malloc(sizeof(char));
if (ret_str == NULL) {
@@ -190,13 +236,14 @@ static char *build_json_str_list(const char *tag, struct str_list const *list) /
ret_str[0] = '\0';
}
- res = asprintf(&temp_str, "\"%s\": [\"%s\"", tag, list->strs[0]);
+ res = my_asprintf(&temp_str, "\"%s\": [\"%s\"", tag, list->strs[0]);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
+ free(ret_str);
return NULL;
}
- for (i=1; i<list->nb_strs; i++) {
- res = asprintf(&ret_str, "%s, \"%s\"", temp_str, list->strs[i]);
+ for (int i=1; i<list->nb_strs; i++) {
+ res = my_asprintf(&ret_str, "%s, \"%s\"", temp_str, list->strs[i]);
free(temp_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
@@ -204,7 +251,7 @@ static char *build_json_str_list(const char *tag, struct str_list const *list) /
}
temp_str = ret_str;
}
- res = asprintf(&ret_str, "%s]", temp_str);
+ res = my_asprintf(&ret_str, "%s]", temp_str);
free(temp_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
static void in_place_replace_sensu_name_reserved(char *orig_name) /* {{{ */
{
- int i;
int len=strlen(orig_name);
- for (i=0; i<len; i++) {
+ for (int i=0; i<len; i++) {
// some plugins like ipmi generate special characters in metric name
switch(orig_name[i]) {
case '(': orig_name[i] = '_'; break;
{
char name_buffer[5 * DATA_MAX_NAME_LEN];
char service_buffer[6 * DATA_MAX_NAME_LEN];
- int i;
char *ret_str;
char *temp_str;
char *value_str;
}
}
else {
- res = asprintf(&ret_str, "%s, %s", part1, handlers_str);
+ res = my_asprintf(&ret_str, "%s, %s", part1, handlers_str);
free(handlers_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
}
// incorporate the plugin name information
- res = asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, vl->plugin);
+ res = my_asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, vl->plugin);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
ret_str = temp_str;
// incorporate the plugin type
- res = asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, vl->type);
+ res = my_asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, vl->type);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// incorporate the plugin instance if any
if (vl->plugin_instance[0] != 0) {
- res = asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, vl->plugin_instance);
+ res = my_asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, vl->plugin_instance);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// incorporate the plugin type instance if any
if (vl->type_instance[0] != 0) {
- res = asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, vl->type_instance);
+ res = my_asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, vl->type_instance);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
char ds_type[DATA_MAX_NAME_LEN];
ssnprintf (ds_type, sizeof (ds_type), "%s:rate", DS_TYPE_TO_STRING(ds->ds[index].type));
- res = asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, ds_type);
+ res = my_asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, ds_type);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
}
ret_str = temp_str;
} else {
- res = asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, DS_TYPE_TO_STRING(ds->ds[index].type));
+ res = my_asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, DS_TYPE_TO_STRING(ds->ds[index].type));
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
}
// incorporate the data source name
- res = asprintf(&temp_str, "%s, \"collectd_data_source_name\": \"%s\"", ret_str, ds->ds[index].name);
+ res = my_asprintf(&temp_str, "%s, \"collectd_data_source_name\": \"%s\"", ret_str, ds->ds[index].name);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
{
char ds_index[DATA_MAX_NAME_LEN];
ssnprintf (ds_index, sizeof (ds_index), "%zu", index);
- res = asprintf(&temp_str, "%s, \"collectd_data_source_index\": %s", ret_str, ds_index);
+ res = my_asprintf(&temp_str, "%s, \"collectd_data_source_index\": %s", ret_str, ds_index);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
}
// add key value attributes from config if any
- for (i = 0; i < sensu_attrs_num; i += 2) {
- res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
+ for (size_t i = 0; i < sensu_attrs_num; i += 2) {
+ res = my_asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// incorporate sensu tags from config if any
if ((sensu_tags != NULL) && (strlen(sensu_tags) != 0)) {
- res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
+ res = my_asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// calculate the value and set to a string
if (ds->ds[index].type == DS_TYPE_GAUGE) {
- res = asprintf(&value_str, GAUGE_FORMAT, vl->values[index].gauge);
+ res = my_asprintf(&value_str, GAUGE_FORMAT, vl->values[index].gauge);
if (res == -1) {
free(ret_str);
ERROR("write_sensu plugin: Unable to alloc memory");
return NULL;
}
} else if (rates != NULL) {
- res = asprintf(&value_str, GAUGE_FORMAT, rates[index]);
+ res = my_asprintf(&value_str, GAUGE_FORMAT, rates[index]);
if (res == -1) {
free(ret_str);
ERROR("write_sensu plugin: Unable to alloc memory");
}
} else {
if (ds->ds[index].type == DS_TYPE_DERIVE) {
- res = asprintf(&value_str, "%"PRIi64, vl->values[index].derive);
+ res = my_asprintf(&value_str, "%"PRIi64, vl->values[index].derive);
if (res == -1) {
free(ret_str);
ERROR("write_sensu plugin: Unable to alloc memory");
}
}
else if (ds->ds[index].type == DS_TYPE_ABSOLUTE) {
- res = asprintf(&value_str, "%"PRIu64, vl->values[index].absolute);
+ res = my_asprintf(&value_str, "%"PRIu64, vl->values[index].absolute);
if (res == -1) {
free(ret_str);
ERROR("write_sensu plugin: Unable to alloc memory");
}
}
else {
- res = asprintf(&value_str, "%llu", vl->values[index].counter);
+ res = my_asprintf(&value_str, "%llu", vl->values[index].counter);
if (res == -1) {
free(ret_str);
ERROR("write_sensu plugin: Unable to alloc memory");
in_place_replace_sensu_name_reserved(service_buffer);
// finalize the buffer by setting the output and closing curly bracket
- res = asprintf(&temp_str, "%s, \"output\": \"%s %s %ld\"}\n", ret_str, service_buffer, value_str, CDTIME_T_TO_TIME_T(vl->time));
+ res = my_asprintf(&temp_str, "%s, \"output\": \"%s %s %lld\"}\n",ret_str, service_buffer, value_str, (long long)CDTIME_T_TO_TIME_T(vl->time));
free(ret_str);
free(value_str);
if (res == -1) {
} else
retlen = strlen(str);
- ret = malloc(retlen + 1);
+ ret = calloc(1, retlen + 1);
if (ret == NULL)
return NULL;
// added to original: not optimized, but keeps valgrind happy.
- memset(ret, 0, retlen + 1);
r = ret;
p = str;
{
char service_buffer[6 * DATA_MAX_NAME_LEN];
char const *severity;
- notification_meta_t *meta;
char *ret_str;
char *temp_str;
int status;
- int i;
+ size_t i;
int res;
// add the severity/status
switch (n->severity) {
severity = "UNKNOWN";
status = 3;
}
- res = asprintf(&temp_str, "{\"status\": %d", status);
+ res = my_asprintf(&temp_str, "{\"status\": %d", status);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
return NULL;
ret_str = temp_str;
// incorporate the timestamp
- res = asprintf(&temp_str, "%s, \"timestamp\": %ld", ret_str, CDTIME_T_TO_TIME_T(n->time));
+ res = my_asprintf(&temp_str, "%s, \"timestamp\": %lld", ret_str, (long long)CDTIME_T_TO_TIME_T(n->time));
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
}
// incorporate the handlers
if (strlen(handlers_str) != 0) {
- res = asprintf(&temp_str, "%s, %s", ret_str, handlers_str);
+ res = my_asprintf(&temp_str, "%s, %s", ret_str, handlers_str);
free(ret_str);
free(handlers_str);
if (res == -1) {
// incorporate the plugin name information if any
if (n->plugin[0] != 0) {
- res = asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, n->plugin);
+ res = my_asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, n->plugin);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// incorporate the plugin type if any
if (n->type[0] != 0) {
- res = asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, n->type);
+ res = my_asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, n->type);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// incorporate the plugin instance if any
if (n->plugin_instance[0] != 0) {
- res = asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, n->plugin_instance);
+ res = my_asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, n->plugin_instance);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// incorporate the plugin type instance if any
if (n->type_instance[0] != 0) {
- res = asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, n->type_instance);
+ res = my_asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, n->type_instance);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// add key value attributes from config if any
for (i = 0; i < sensu_attrs_num; i += 2) {
- res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
+ res = my_asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
// incorporate sensu tags from config if any
if ((sensu_tags != NULL) && (strlen(sensu_tags) != 0)) {
- res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
+ res = my_asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
n->type, n->type_instance, host->separator);
// replace sensu event name chars that are considered illegal
in_place_replace_sensu_name_reserved(service_buffer);
- res = asprintf(&temp_str, "%s, \"name\": \"%s\"", ret_str, &service_buffer[1]);
+ res = my_asprintf(&temp_str, "%s, \"name\": \"%s\"", ret_str, &service_buffer[1]);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
free(ret_str);
return NULL;
}
- res = asprintf(&temp_str, "%s, \"output\": \"%s - %s\"", ret_str, severity, msg);
+ res = my_asprintf(&temp_str, "%s, \"output\": \"%s - %s\"", ret_str, severity, msg);
free(ret_str);
free(msg);
if (res == -1) {
}
// Pull in values from threshold and add extra attributes
- for (meta = n->meta; meta != NULL; meta = meta->next) {
+ for (notification_meta_t *meta = n->meta; meta != NULL; meta = meta->next) {
if (strcasecmp("CurrentValue", meta->name) == 0 && meta->type == NM_TYPE_DOUBLE) {
- res = asprintf(&temp_str, "%s, \"current_value\": \"%.8f\"", ret_str, meta->nm_value.nm_double);
+ res = my_asprintf(&temp_str, "%s, \"current_value\": \"%.8f\"", ret_str, meta->nm_value.nm_double);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
ret_str = temp_str;
}
if (meta->type == NM_TYPE_STRING) {
- res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, meta->name, meta->nm_value.nm_string);
+ res = my_asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, meta->name, meta->nm_value.nm_string);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
}
// close the curly bracket
- res = asprintf(&temp_str, "%s}\n", ret_str);
+ res = my_asprintf(&temp_str, "%s}\n", ret_str);
free(ret_str);
if (res == -1) {
ERROR("write_sensu plugin: Unable to alloc memory");
int statuses[vl->values_len];
struct sensu_host *host = ud->data;
gauge_t *rates = NULL;
- int i;
char *msg;
pthread_mutex_lock(&host->lock);
return -1;
}
}
- for (i = 0; i < (size_t) vl->values_len; i++) {
+ for (size_t i = 0; i < vl->values_len; i++) {
msg = sensu_value_to_json(host, ds, vl, (int) i, rates, statuses[i]);
if (msg == NULL) {
sfree(rates);
{
struct sensu_host *host = NULL;
int status = 0;
- int i;
oconfig_item_t *child;
char callback_name[DATA_MAX_NAME_LEN];
- user_data_t ud;
if ((host = calloc(1, sizeof(*host))) == NULL) {
ERROR("write_sensu plugin: calloc failed.");
return -1;
}
- for (i = 0; i < ci->children_num; i++) {
+ for (int i = 0; i < ci->children_num; i++) {
child = &ci->children[i];
status = 0;
}
ssnprintf(callback_name, sizeof(callback_name), "write_sensu/%s", host->name);
- ud.data = host;
- ud.free_func = sensu_free;
+
+ user_data_t ud = {
+ .data = host,
+ .free_func = sensu_free
+ };
pthread_mutex_lock(&host->lock);
static int sensu_config(oconfig_item_t *ci) /* {{{ */
{
- int i;
oconfig_item_t *child;
int status;
struct str_list sensu_tags_arr;
sensu_tags_arr.nb_strs = 0;
sensu_tags_arr.strs = NULL;
- for (i = 0; i < ci->children_num; i++) {
+ for (int i = 0; i < ci->children_num; i++) {
child = &ci->children[i];
if (strcasecmp("Node", child->key) == 0) {
diff --git a/src/write_tsdb.c b/src/write_tsdb.c
index ee4db2384a2848b9466b3bbedf155579f3225877..b670f3ae583d3d401565c019ed5df900667f87b8 100644 (file)
--- a/src/write_tsdb.c
+++ b/src/write_tsdb.c
*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
#include "utils_cache.h"
-#include <pthread.h>
-#include <sys/socket.h>
#include <netdb.h>
#ifndef WT_DEFAULT_NODE
return 0;
}
- if (cb->send_buf_fill <= 0)
+ if (cb->send_buf_fill == 0)
{
cb->send_buf_init_time = cdtime();
return 0;
static int wt_callback_init(struct wt_callback *cb)
{
- struct addrinfo ai_hints;
struct addrinfo *ai_list;
- struct addrinfo *ai_ptr;
int status;
const char *node = cb->node ? cb->node : WT_DEFAULT_NODE;
if (cb->sock_fd > 0)
return 0;
- memset(&ai_hints, 0, sizeof(ai_hints));
-#ifdef AI_ADDRCONFIG
- ai_hints.ai_flags |= AI_ADDRCONFIG;
-#endif
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_STREAM;
-
- ai_list = NULL;
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_socktype = SOCK_STREAM
+ };
status = getaddrinfo(node, service, &ai_hints, &ai_list);
if (status != 0)
}
assert (ai_list != NULL);
- for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+ for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
{
cb->sock_fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype,
ai_ptr->ai_protocol);
if (cb->sock_fd < 0)
continue;
+ set_sock_opts(cb->sock_fd);
+
status = connect(cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
if (status != 0)
{
{
int status;
char *temp = NULL;
- char *prefix = "";
+ const char *prefix = "";
const char *meta_prefix = "tsdb_prefix";
if (vl->meta) {
const char* host, meta_data_t *md)
{
int status;
- int message_len;
+ size_t message_len;
char *temp = NULL;
- char *tags = "";
+ const char *tags = "";
char message[1024];
- char *host_tags = cb->host_tags ? cb->host_tags : "";
+ const char *host_tags = cb->host_tags ? cb->host_tags : "";
const char *meta_tsdb = "tsdb_tags";
/* skip if value is NaN */
}
}
- message_len = ssnprintf (message,
+ status = ssnprintf (message,
sizeof(message),
"put %s %.0f %s fqdn=%s %s %s\r\n",
key,
host,
tags,
host_tags);
-
sfree(temp);
+ if (status < 0)
+ return -1;
+ message_len = (size_t) status;
if (message_len >= sizeof(message)) {
ERROR("write_tsdb plugin: message buffer too small: "
- "Need %d bytes.", message_len + 1);
+ "Need %zu bytes.", message_len + 1);
return -1;
}
char key[10*DATA_MAX_NAME_LEN];
char values[512];
- int status, i;
+ int status;
if (0 != strcmp(ds->type, vl->type))
{
return -1;
}
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
const char *ds_name = NULL;
static int wt_config_tsd(oconfig_item_t *ci)
{
struct wt_callback *cb;
- user_data_t user_data;
char callback_name[DATA_MAX_NAME_LEN];
- int i;
- cb = malloc(sizeof(*cb));
+ cb = calloc(1, sizeof(*cb));
if (cb == NULL)
{
- ERROR("write_tsdb plugin: malloc failed.");
+ ERROR("write_tsdb plugin: calloc failed.");
return -1;
}
- memset(cb, 0, sizeof(*cb));
cb->sock_fd = -1;
cb->node = NULL;
cb->service = NULL;
pthread_mutex_init (&cb->send_lock, NULL);
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
cb->node != NULL ? cb->node : WT_DEFAULT_NODE,
cb->service != NULL ? cb->service : WT_DEFAULT_SERVICE);
- memset(&user_data, 0, sizeof(user_data));
- user_data.data = cb;
- user_data.free_func = wt_callback_free;
+ user_data_t user_data = {
+ .data = cb,
+ .free_func = wt_callback_free
+ };
+
plugin_register_write(callback_name, wt_write, &user_data);
user_data.free_func = NULL;
static int wt_config(oconfig_item_t *ci)
{
- int i;
-
- for (i = 0; i < ci->children_num; i++)
+ for (int i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
diff --git a/src/xencpu.c b/src/xencpu.c
--- /dev/null
+++ b/src/xencpu.c
@@ -0,0 +1,164 @@
+/**
+ * collectd - src/xencpu.c
+ * Copyright (C) 2016 Pavel Rochnyak
+ *
+ * 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:
+ * Pavel Rochnyak <pavel2000 ngs.ru>
+ **/
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+
+#include <xenctrl.h>
+
+#ifdef XENCTRL_HAS_XC_INTERFACE
+
+//Xen-4.1+
+#define XC_INTERFACE_INIT_ARGS NULL,NULL,0
+xc_interface *xc_handle;
+
+#else /* XENCTRL_HAS_XC_INTERFACE */
+
+//For xen-3.4/xen-4.0
+#include <string.h>
+#define xc_strerror(xc_interface, errcode) strerror(errcode)
+#define XC_INTERFACE_INIT_ARGS
+typedef int xc_interface;
+xc_interface xc_handle = 0;
+
+#endif /* XENCTRL_HAS_XC_INTERFACE */
+
+uint32_t num_cpus = 0;
+xc_cpuinfo_t *cpu_info;
+static value_to_rate_state_t *cpu_states;
+
+static int xencpu_init (void)
+{
+ xc_handle = xc_interface_open(XC_INTERFACE_INIT_ARGS);
+ if (!xc_handle)
+ {
+ ERROR ("xencpu: xc_interface_open() failed");
+ return (-1);
+ }
+
+ xc_physinfo_t *physinfo;
+
+ physinfo = calloc(1, sizeof(xc_physinfo_t));
+ if (physinfo == NULL)
+ {
+ ERROR ("xencpu plugin: calloc() for physinfo failed.");
+ xc_interface_close(xc_handle);
+ return (ENOMEM);
+ }
+
+ if (xc_physinfo(xc_handle, physinfo) < 0)
+ {
+ ERROR ("xencpu plugin: xc_physinfo() failed");
+ xc_interface_close(xc_handle);
+ free(physinfo);
+ return (-1);
+ }
+
+ num_cpus = physinfo->nr_cpus;
+ free(physinfo);
+
+ INFO ("xencpu plugin: Found %"PRIu32" processors.", num_cpus);
+
+ cpu_info = calloc(num_cpus, sizeof(xc_cpuinfo_t));
+ if (cpu_info == NULL)
+ {
+ ERROR ("xencpu plugin: calloc() for num_cpus failed.");
+ xc_interface_close(xc_handle);
+ return (ENOMEM);
+ }
+
+ cpu_states = calloc (num_cpus, sizeof (value_to_rate_state_t));
+ if (cpu_states == NULL)
+ {
+ ERROR ("xencpu plugin: calloc() for cpu_states failed.");
+ xc_interface_close(xc_handle);
+ free(cpu_info);
+ return (ENOMEM);
+ }
+
+ return (0);
+} /* static int xencpu_init */
+
+static int xencpu_shutdown (void)
+{
+ free(cpu_states);
+ free(cpu_info);
+ xc_interface_close(xc_handle);
+
+ return 0;
+} /* static int xencpu_shutdown */
+
+static void submit_value (int cpu_num, gauge_t percent)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = percent;
+
+ vl.values = values;
+ vl.values_len = 1;
+
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "xencpu", sizeof (vl.plugin));
+ sstrncpy (vl.type, "percent", sizeof (vl.type));
+ sstrncpy (vl.type_instance, "load", sizeof (vl.type_instance));
+
+ if (cpu_num >= 0) {
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ "%i", cpu_num);
+ }
+ plugin_dispatch_values (&vl);
+} /* static void submit_value */
+
+static int xencpu_read (void)
+{
+ cdtime_t now = cdtime ();
+
+ int rc, nr_cpus;
+
+ rc = xc_getcpuinfo(xc_handle, num_cpus, cpu_info, &nr_cpus);
+ if (rc < 0) {
+ ERROR ("xencpu: xc_getcpuinfo() Failed: %d %s\n", rc, xc_strerror(xc_handle,errno));
+ return (-1);
+ }
+
+ int status;
+ for (int cpu = 0; cpu < nr_cpus; cpu++) {
+ gauge_t rate = NAN;
+ value_t value = {.derive = cpu_info[cpu].idletime};
+
+ status = value_to_rate (&rate, value, DS_TYPE_DERIVE, now, &cpu_states[cpu]);
+ if (status == 0) {
+ submit_value(cpu, 100 - rate/10000000);
+ }
+ }
+
+ return (0);
+} /* static int xencpu_read */
+
+void module_register (void)
+{
+ plugin_register_init ("xencpu", xencpu_init);
+ plugin_register_read ("xencpu", xencpu_read);
+ plugin_register_shutdown ("xencpu", xencpu_shutdown);
+} /* void module_register */
diff --git a/src/xmms.c b/src/xmms.c
index 29f2acd0f630977b42d3dff37b59965e8b60be21..353599502fe5f53f3193fbc59ccac2a38ef8f24a 100644 (file)
--- a/src/xmms.c
+++ b/src/xmms.c
**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
diff --git a/src/zfs_arc.c b/src/zfs_arc.c
index 8feb31d55c0bfc75f571e0398edfef965e8fcc78..c7d782c6370c7d308d1ad56ed63f942e3db5bec5 100644 (file)
--- a/src/zfs_arc.c
+++ b/src/zfs_arc.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
typedef llist_t kstat_t;
-static long long get_zfs_value(kstat_t *zfs_stats __attribute__((unused)),
- char *name)
+static int put_zfs_value (kstat_t *ksp, char const *k, value_t v)
+{
+ llentry_t *e;
+ char *k_copy;
+ value_t *v_copy;
+
+ k_copy = strdup (k);
+ if (k_copy == NULL)
+ return ENOMEM;
+
+ v_copy = malloc (sizeof (*v_copy));
+ if (v_copy == NULL)
+ {
+ sfree (k_copy);
+ return ENOMEM;
+ }
+ *v_copy = v;
+
+ e = llentry_create (k_copy, v_copy);
+ if (e == NULL)
+ {
+ sfree (v_copy);
+ sfree (k_copy);
+ return ENOMEM;
+ }
+
+ llist_append (ksp, e);
+ return 0;
+}
+
+static long long get_zfs_value(kstat_t *ksp, const char *key)
{
llentry_t *e;
+ value_t *v;
- e = llist_search (zfs_stats, name);
+ e = llist_search (ksp, key);
if (e == NULL)
{
- ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", name);
+ ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", key);
return (-1);
}
- return (*(long long int*)e->value);
+ v = e->value;
+ return ((long long) v->derive);
}
-#elif !defined(__FreeBSD__) // Solaris
+static void free_zfs_values (kstat_t *ksp)
+{
+ if (ksp == NULL)
+ return;
+
+ for (llentry_t *e = llist_head (ksp); e != NULL; e = e->next)
+ {
+ sfree (e->key);
+ sfree (e->value);
+ }
+
+ llist_destroy (ksp);
+}
+
+#elif defined(KERNEL_SOLARIS)
extern kstat_ctl_t *kc;
static long long get_zfs_value(kstat_t *ksp, char *name)
return (get_kstat_value(ksp, name));
}
-#else // FreeBSD
+#elif defined(KERNEL_FREEBSD)
#include <sys/types.h>
#include <sys/sysctl.h>
value_t l2_io[2];
kstat_t *ksp = NULL;
-#if KERNEL_LINUX
- long long int *llvalues = NULL;
- char file_contents[1024 * 10];
- char *fields[3];
- int numfields;
- ssize_t len;
+#if defined(KERNEL_LINUX)
+ FILE *fh;
+ char buffer[1024];
+
+ fh = fopen (ZOL_ARCSTATS_FILE, "r");
+ if (fh == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("zfs_arc plugin: Opening \"%s\" failed: %s", ZOL_ARCSTATS_FILE,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
ksp = llist_create ();
if (ksp == NULL)
{
ERROR ("zfs_arc plugin: `llist_create' failed.");
+ fclose (fh);
return (-1);
}
- len = read_file_contents (ZOL_ARCSTATS_FILE, file_contents, sizeof(file_contents) - 1);
- if (len > 1)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
+ char *fields[3];
+ value_t v;
+ int status;
- int i=0;
- char *pnl = file_contents;
- char *pnnl;
-
- file_contents[len] = '\0';
-
- while (pnl != NULL)
- {
- pnl = strchr(pnl, '\n');
- i++;
- if (pnl && (*pnl != '\0'))
- pnl++;
- }
-
- if (i > 0)
- {
- llentry_t *e;
- llvalues = malloc(sizeof(long long int) * i);
- if (llvalues == NULL)
- {
- ERROR ("zfs_arc plugin: `malloc' failed.");
- llist_destroy (ksp);
- return (-1);
- }
- int j = 0;
-
- pnl = file_contents;
- while (pnl != NULL)
- {
- pnnl = strchr(pnl, '\n');
- if (pnnl != NULL)
- *pnnl = '\0';
-
- numfields = strsplit (pnl, fields, 4);
- if (numfields == 3)
- {
- llvalues[j] = atoll (fields[2]);
-
- e = llentry_create (fields[0], &llvalues[j]);
- if (e == NULL)
- {
- ERROR ("zfs_arc plugin: `llentry_create' failed.");
- }
- else
- {
- llist_append (ksp, e);
- }
- j++;
- }
- pnl = pnnl;
- if (pnl != NULL)
- pnl ++;
- }
- }
+ status = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+ if (status != 3)
+ continue;
+
+ status = parse_value (fields[2], &v, DS_TYPE_DERIVE);
+ if (status != 0)
+ continue;
+
+ put_zfs_value (ksp, fields[0], v);
}
-#elif !defined(__FreeBSD__) // Solaris
+ fclose (fh);
+
+#elif defined(KERNEL_SOLARIS)
get_kstat (&ksp, "zfs", 0, "arcstats");
if (ksp == NULL)
{
#endif
/* Sizes */
- za_read_gauge (ksp, "size", "cache_size", "arc");
+ za_read_gauge (ksp, "anon_size", "cache_size", "anon_size");
+ za_read_gauge (ksp, "c", "cache_size", "c");
+ za_read_gauge (ksp, "c_max", "cache_size", "c_max");
+ za_read_gauge (ksp, "c_min", "cache_size", "c_min");
+ za_read_gauge (ksp, "hdr_size", "cache_size", "hdr_size");
+ za_read_gauge (ksp, "metadata_size", "cache_size", "metadata_size");
+ za_read_gauge (ksp, "mfu_ghost_size", "cache_size", "mfu_ghost_size");
+ za_read_gauge (ksp, "mfu_size", "cache_size", "mfu_size");
+ za_read_gauge (ksp, "mru_ghost_size", "cache_size", "mru_ghost_size");
+ za_read_gauge (ksp, "mru_size", "cache_size", "mru_size");
+ za_read_gauge (ksp, "other_size", "cache_size", "other_size");
+ za_read_gauge (ksp, "p", "cache_size", "p");
+ za_read_gauge (ksp, "size", "cache_size", "arc");
/* The "l2_size" value has disappeared from Solaris some time in
* early 2013, and has only reappeared recently in Solaris 11.2.
/* Operations */
za_read_derive (ksp, "deleted", "cache_operation", "deleted");
-#if __FreeBSD__
+#if defined(KERNEL_FREEBSD)
za_read_derive (ksp, "allocated","cache_operation", "allocated");
-#if defined(__FreeBSD_version) && (__FreeBSD_version < 1002501)
- /* stolen removed from sysctl kstat.zfs.misc.arcstats on FreeBSD 10.2+ */
- za_read_derive (ksp, "stolen", "cache_operation", "stolen");
-#endif
#endif
/* Issue indicators */
za_read_derive (ksp, "mutex_miss", "mutex_operations", "miss");
za_read_derive (ksp, "hash_collisions", "hash_collisions", "");
+ za_read_derive (ksp, "memory_throttle_count", "memory_throttle_count", "");
/* Evictions */
za_read_derive (ksp, "evict_l2_cached", "cache_eviction", "cached");
za_read_derive (ksp, "demand_metadata_misses", "cache_result", "demand_metadata-miss");
za_read_derive (ksp, "prefetch_data_misses", "cache_result", "prefetch_data-miss");
za_read_derive (ksp, "prefetch_metadata_misses", "cache_result", "prefetch_metadata-miss");
+ za_read_derive (ksp, "mfu_hits", "cache_result", "mfu-hit");
+ za_read_derive (ksp, "mfu_ghost_hits", "cache_result", "mfu_ghost-hit");
+ za_read_derive (ksp, "mru_hits", "cache_result", "mru-hit");
+ za_read_derive (ksp, "mru_ghost_hits", "cache_result", "mru_ghost-hit");
/* Ratios */
arc_hits = (gauge_t) get_zfs_value(ksp, "hits");
za_submit ("io_octets", "L2", l2_io, /* num values = */ 2);
#if defined(KERNEL_LINUX)
- if (llvalues != NULL)
- {
- free(llvalues);
- }
- if (ksp != NULL)
- {
- llist_destroy (ksp);
- }
+ free_zfs_values (ksp);
#endif
return (0);
static int za_init (void) /* {{{ */
{
-#if !defined(__FreeBSD__) && !defined(KERNEL_LINUX) // Solaris
+#if defined(KERNEL_SOLARIS)
/* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */
if (kc == NULL)
{
diff --git a/src/zone.c b/src/zone.c
--- /dev/null
+++ b/src/zone.c
@@ -0,0 +1,205 @@
+/**
+ * collectd - src/zone.c
+ * Copyright (C) 2011 Mathijs Mohlmann
+ *
+ * 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:
+ * Mathijs Mohlmann
+ * Dagobert Michelsen (forward-porting)
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+# undef HAVE_CONFIG_H
+#endif
+/* avoid procfs.h error "Cannot use procfs in the large file compilation environment" */
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+# undef _FILE_OFFSET_BITS
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+
+#include <procfs.h>
+#include <zone.h>
+
+#include "utils_avltree.h"
+
+#define MAX_PROCFS_PATH 40
+#define FRC2PCT(pp)(((float)(pp))/0x8000*100)
+
+typedef struct zone_stats {
+ ushort_t pctcpu;
+ ushort_t pctmem;
+} zone_stats_t;
+
+static int
+zone_compare(const void *a, const void *b)
+{
+ if (*(const zoneid_t *)a == *(const zoneid_t *)b)
+ return(0);
+ if (*(const zoneid_t *)a < *(const zoneid_t *)b)
+ return(-1);
+ return(1);
+}
+
+static int
+zone_read_procfile(char const *pidstr, char const *name, void *buf, size_t bufsize)
+{
+ int fd;
+
+ char procfile[MAX_PROCFS_PATH];
+ (void)snprintf(procfile, sizeof(procfile), "/proc/%s/%s", pidstr, name);
+ if ((fd = open(procfile, O_RDONLY)) == -1) {
+ return (1);
+ }
+
+ if (sread(fd, buf, bufsize) != 0) {
+ char errbuf[1024];
+ ERROR ("zone plugin: Reading \"%s\" failed: %s", procfile,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ close(fd);
+ return (1);
+ }
+
+ close(fd);
+ return (0);
+}
+
+static int
+zone_submit_value(char *zone, gauge_t value)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ value_t values[1];
+
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1; /*STATIC_ARRAY_SIZE (values);*/
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "zone", sizeof (vl.plugin));
+ sstrncpy (vl.type, "percent", sizeof (vl.type));
+ sstrncpy (vl.type_instance, zone, sizeof (vl.type_instance));
+
+ return(plugin_dispatch_values (&vl));
+}
+
+static zone_stats_t *
+zone_find_stats(c_avl_tree_t *tree, zoneid_t zoneid)
+{
+ zone_stats_t *ret = NULL;
+ zoneid_t *key = NULL;
+
+ if (c_avl_get(tree, (void **)&zoneid, (void **)&ret)) {
+ if (!(ret = malloc(sizeof(*ret)))) {
+ WARNING("zone plugin: no memory");
+ return(NULL);
+ }
+ if (!(key = malloc(sizeof(*key)))) {
+ WARNING("zone plugin: no memory");
+ free(ret);
+ return(NULL);
+ }
+ *key = zoneid;
+ if (c_avl_insert(tree, key, ret)) {
+ WARNING("zone plugin: error inserting into tree");
+ return(NULL);
+ }
+ }
+ return(ret);
+}
+
+static void
+zone_submit_values(c_avl_tree_t *tree)
+{
+ char zonename[ZONENAME_MAX];
+ zoneid_t *zoneid = NULL;
+ zone_stats_t *stats = NULL;
+
+ while (c_avl_pick (tree, (void **)&zoneid, (void **)&stats) == 0)
+ {
+ if (getzonenamebyid(*zoneid, zonename, sizeof( zonename )) == -1) {
+ WARNING("zone plugin: error retrieving zonename");
+ } else {
+ zone_submit_value(zonename, (gauge_t)FRC2PCT(stats->pctcpu));
+ }
+ free(stats);
+ free(zoneid);
+ }
+ c_avl_destroy(tree);
+}
+
+static c_avl_tree_t *
+zone_scandir(DIR *procdir)
+{
+ pid_t pid;
+ dirent_t *direntp;
+ psinfo_t psinfo;
+ c_avl_tree_t *tree;
+ zone_stats_t *stats;
+
+ if (!(tree=c_avl_create(zone_compare))) {
+ WARNING("zone plugin: Failed to create tree");
+ return(NULL);
+ }
+
+ rewinddir(procdir);
+ while ((direntp = readdir(procdir))) {
+ char const *pidstr = direntp->d_name;
+ if (pidstr[0] == '.') /* skip "." and ".." */
+ continue;
+
+ pid = atoi(pidstr);
+ if (pid == 0 || pid == 2 || pid == 3)
+ continue; /* skip sched, pageout and fsflush */
+
+ if (zone_read_procfile(pidstr, "psinfo", &psinfo, sizeof(psinfo_t)) != 0)
+ continue;
+
+ stats = zone_find_stats(tree, psinfo.pr_zoneid);
+ if( stats ) {
+ stats->pctcpu += psinfo.pr_pctcpu;
+ stats->pctmem += psinfo.pr_pctmem;
+ }
+ }
+ return(tree);
+}
+
+static int zone_read (void)
+{
+ DIR *procdir;
+ c_avl_tree_t *tree;
+
+ if ((procdir = opendir("/proc")) == NULL) {
+ ERROR("zone plugin: cannot open /proc directory\n");
+ return (-1);
+ }
+
+ tree=zone_scandir(procdir);
+ closedir(procdir);
+ if (tree == NULL) {
+ return (-1);
+ }
+ zone_submit_values(tree); /* this also frees tree */
+ return (0);
+}
+
+void module_register (void)
+{
+ plugin_register_read ("zone", zone_read);
+} /* void module_register */
diff --git a/src/zookeeper.c b/src/zookeeper.c
index 5aa94e3469091101a559dd2116e34d1d5dbba668..84174853d24c62bd8ba22aaa17bc28e5f68aaa3d 100644 (file)
--- a/src/zookeeper.c
+++ b/src/zookeeper.c
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include <netdb.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
{
int sk = -1;
int status;
- struct addrinfo ai_hints;
- struct addrinfo *ai;
struct addrinfo *ai_list;
- char *host;
- char *port;
-
- memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
- ai_hints.ai_family = AF_UNSPEC;
- ai_hints.ai_socktype = SOCK_STREAM;
+ const char *host;
+ const char *port;
host = (zk_host != NULL) ? zk_host : ZOOKEEPER_DEF_HOST;
port = (zk_port != NULL) ? zk_port : ZOOKEEPER_DEF_PORT;
+
+ struct addrinfo ai_hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM
+ };
+
status = getaddrinfo (host, port, &ai_hints, &ai_list);
if (status != 0)
{
return (-1);
}
- for (ai = ai_list; ai != NULL; ai = ai->ai_next)
+ for (struct addrinfo *ai = ai_list; ai != NULL; ai = ai->ai_next)
{
sk = socket (ai->ai_family, SOCK_STREAM, 0);
if (sk < 0)
static int zookeeper_query (char *buffer, size_t buffer_size)
{
- int sk = -1;
- int status;
+ int sk, status;
size_t buffer_fill;
sk = zookeeper_connect();
diff --git a/testwrapper.sh b/testwrapper.sh
--- /dev/null
+++ b/testwrapper.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+#
+# collectd -- testwrapper.sh
+#
+# A wrapper script for running tests. If valgrind is available, memory
+# checking will be enabled for all tests.
+
+set -e
+
+MEMCHECK=""
+
+if test -n "$VALGRIND"; then
+ MEMCHECK="$VALGRIND --quiet --tool=memcheck --error-exitcode=1"
+ MEMCHECK="$MEMCHECK --trace-children=yes"
+ MEMCHECK="$MEMCHECK --leak-check=full"
+ MEMCHECK="$MEMCHECK --gen-suppressions=all"
+
+ for f in "valgrind.$( uname -s ).suppress" "valgrind.suppress"; do
+ filename="$( dirname "$0" )/src/$f"
+ if test -e "$filename"; then
+ # Valgrind supports up to 100 suppression files.
+ MEMCHECK="$MEMCHECK --suppressions=$filename"
+ fi
+ done
+fi
+
+exec $MEMCHECK "$@"
+
+# vim: set tw=78 sw=4 ts=4 noexpandtab :
+
diff --git a/version-gen.sh b/version-gen.sh
index 45e5a53467fbdfe1c70ab454c5314cdbb5b2be0e..e106d80503b12dfdf9e3fc44437651d14b9d6638 100755 (executable)
--- a/version-gen.sh
+++ b/version-gen.sh
#!/bin/sh
-DEFAULT_VERSION="5.5.3.git"
+DEFAULT_VERSION="5.6.1.git"
-VERSION="`git describe 2> /dev/null | grep collectd | sed -e 's/^collectd-//'`"
+if [ -d .git ]; then
+ VERSION="`git describe --dirty=+ --abbrev=7 2> /dev/null | grep collectd | sed -e 's/^collectd-//' -e 's/-/./g'`"
+fi
if test -z "$VERSION"; then
VERSION="$DEFAULT_VERSION"
fi
-VERSION="`echo \"$VERSION\" | sed -e 's/-/./g'`"
-
printf "%s" "$VERSION"